timer/counter questions

obrienwhoi

New member
This is on a teensy 4.1
I have been pounding my head with ChatGPT for weeks on this. i have a 39 KHz signal on my FSYNC pin teensy pin 0. i have a 10 MHz signal on my DCLK pin teensy pin 27. pins 6,10,11,12,13,14,15,16 and pin 38 are used. i would like to take any other pin lets call it 'output pin' preferably pin 37 or 39 (next door to pin38) but not required and drive it high and low in hardware with this logic. on every rising edge of the FSYNC line i would like to drive output pin low and then start counting edges on the DCLK pin from 0. when DCLK count gets 192 edges i would like to drive output pin high. and then wait for the next rising edge on FSYNC. when it sees that next FSYNC rising edge it drives output low, resets the counter to zero and then counts to 192 again drives output high and so on and so on.

i am using LPSPI3 in slave mode as a shift register to shift in 24 bytes of data from my ADC to a ring buffer via DMA. i had this all working with interrupts and then found that when i was dumping ring buffer to uSD card my data was getting corrupt exactly during sd writes. i feel this is caused by the interrupt driven nature of the system at the moment. i would like all the data capture to be purely done in hardware but the LPSI shif register seems to need the chip select line to behave like a chip select line so i would like to try this aproach to drive the CS pin with another pin. if i can get this to work i think i'll be in business with no interrupts. all of the attempts with QTMR and DMA ISRs and FLEXIO and cross bar this to that have been failures. i can't even seem to get a simple proof of concept sketch working where i can check the expected pulse train and width on a scope. meaning strip everything else out and just see if you can get the above logic to create the desired output in the output pin. any help and a kick in the right direction and maybe example code would be greatly appreciated!
Thanks,
Jeff
 
here is what chatGPT recommended but doesn't work

Code:
#include <Arduino.h>
#include "imxrt.h"

/*
  FSYNC  -> pin 19  (GPIO_B0_00 = QTMR1_TIMER0)
  DCLK   -> pin 18  (GPIO_B0_01 = QTMR1_TIMER1)
  OUTPUT -> pin 37  (GPIO_B1_01 = QTMR1_TIMER1)
*/

void setup() {
  // Enable QTMR1 clock
  CCM_CCGR6 |= CCM_CCGR6_QTIMER1(CCM_CCGR_ON);

  // -----------------------------
  // Pin muxing
  // -----------------------------

  // FSYNC pin 19 -> QTMR1_TIMER0
  IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_00 = 1;   // ALT1
  IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_00 =
      IOMUXC_PAD_DSE(7) | IOMUXC_PAD_SRE;

  // DCLK pin 18 -> QTMR1_TIMER1
  IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_01 = 1;   // ALT1
  IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_01 =
      IOMUXC_PAD_DSE(7) | IOMUXC_PAD_SRE;

  // OUTPUT pin 37 -> QTMR1_TIMER1
  IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_01 = 1;   // ALT1
  IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_01 =
      IOMUXC_PAD_DSE(7) | IOMUXC_PAD_SRE;

  // Disable all QTMR1 channels while configuring
  TMR1_ENBL = 0;

  // =================================================
  // QTMR1 Channel 0 — FSYNC master
  // =================================================
  TMR1_CNTR0 = 0;
  TMR1_LOAD0 = 0;

  // CM=1  count rising edges
  // PCS=2 external clock from TIMER0 pin (pin 19)
  TMR1_CTRL0 =
      TMR_CTRL_CM(1) |
      TMR_CTRL_PCS(2);

  // Make channel 0 the master
  TMR1_SCTRL0 = TMR_SCTRL_MSTR;

  // Master event clears / reloads channel 1
  TMR1_CSCTRL0 = TMR_CSCTRL_CL1(1);

  // =================================================
  // QTMR1 Channel 1 — DCLK counter + output
  // =================================================
  TMR1_CNTR1 = 0;
  TMR1_LOAD1 = 0;

  // Compare at 192 DCLK edges
  TMR1_COMP11  = 192;
  TMR1_CMPLD11 = 192;

  // CM=1  count rising edges
  // PCS=2 external clock from TIMER1 pin (pin 18)
  // LENGTH stop at compare
  // OUTMODE=2 set output on compare
  TMR1_CTRL1 =
      TMR_CTRL_CM(1) |
      TMR_CTRL_PCS(2) |
      TMR_CTRL_LENGTH |
      TMR_CTRL_OUTMODE(2);

  // Enable output, start low
  TMR1_SCTRL1 = TMR_SCTRL_OEN;

  // Enable channels 0 and 1
  TMR1_ENBL = (1 << 0) | (1 << 1);
}

void loop() {
  // Nothing here — hardware only
}
 
Back
Top