This seems a simple thing to make. But I've tried many approaches and have not been successful. If you have done it, it will be greatly appreciated if you can share. It doesn't have to be QTMR.
Interrupt-driven won't work for me because I am dealing with input in >200KHz.
I am looking for a way without much of intervention of the processor.
Input to QTMR flips states (hi to lo, lo to hi) in various interval.
The output that I am trying to construct is a short pulse, say... 0.5 uSec wide.
Got a solution. It is kind of twisted:
Assuming the signal I am dealing with, a variable width of square waves, is generated by QTMR4 Timer2. Fold it back into QTMR3 Timer0 using XBAR1:
// QTMR3 Timer0 to receive output from QTMR4 Timer3...
IOMUXC_GPR->GPR6 |= IOMUXC_GPR_GPR6_QTIMER3_TRM0_INPUT_SEL_MASK; // Sel XBAR as QTMR3's Timer3 input
XBARA1->SEL47 |= XBARA_SEL47_SEL94( 38 ); // XBAR1_IN38 (QTMR4 Timer2) to QTMR3 Timer0
Make QTMR3 Time0 a "follower" of the variable width square wave, i.e. a delay line. The delay is provided by QTMR's filter.
// Configure QTMR3 timer3 as a delay line...
TMR3->CHANNEL[ 0 ].CTRL = TMR_CTRL_PCS( 0 ) | TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE( 3 ); // Toggle output
TMR3->CHANNEL[ 0 ].FILT = TMR_FILT_FILT_CNT( 3 ) | TMR_FILT_FILT_PER( 10 ); // Latency = (3+3)*10+2=62 clks @ 150MHz IPG, i.e. 413nS (Actual ~470nS)
TMR3->CHANNEL[ 0 ].COMP1 = TMR_COMP1_COMPARISON_1( 0 ); // COMP1 == 0 for toggling on every input edge
TMR3->CHANNEL[ 0 ].SCTRL |= TMR_SCTRL_OEN_MASK; // Output OFLAG
TMR3->CHANNEL[ 0 ].CSCTRL = TMR_CSCTRL_DBG_EN( 1 ); // Hold counter when debug
TMR3->CHANNEL[ 0 ].CTRL |= TMR_CTRL_CM( 2 ); // Count both edges of input
Bring both QTMR4 Timer2's and QTMR3 Timer0's output into XBAR2:
// For Exclusive-OR gate in AOI1 function, route QTMR3 Timer0's output to XBAR2's input and to AOI's input
XBARB2->SEL0 = XBARB_SEL0_SEL0( 18 ); // XBAR2_IN19 (QTMR4 Timer2) to XBAR2_OUT00 (AOI1_IN00)
XBARB2->SEL0 |= XBARB_SEL0_SEL1( 12 ); // XBAR2_IN12 (QTMR3 Timer0) to XBAR2_OUT01 (AOI1_IN01)
Create exclusive-OR logic:
// Configure AOI1's Event0 as Exclusive-OR gate
AOI1->BFCRT[ 0 ].BFCRT01 = 0x6f9f;
AOI1->BFCRT[ 0 ].BFCRT23 = 0x0000;
Finally, output the result (a 0.5uS pulses synchronized to input edges) to pin GPIO_SD_B0_03 (IOMUX_XBAR_INOUT07):
// Route AOI1 Event0 (AOI1_OUT0, i.e. XBAR1_IN72) to GPIO_SD_B0_03 pin (IOMUX_XBAR_INOUT07)
IOMUXC->SW_MUX_CTL_PAD[ kIOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_03 ] = IOMUXC_SW_MUX_CTL_PAD_MUX_MODE( 3 ); // ALT3 = IOMUX_XBAR_INOUT07
IOMUXC_GPR->GPR6 |= IOMUXC_GPR_GPR6_IOMUXC_XBAR_DIR_SEL_7_MASK; // IOMUX_XBAR_INOUT07 as output
XBARA1->SEL3 |= XBARA_SEL3_SEL7( 72 ); // AOI1_OUT0 (XBAR1_IN72) to XBAR1_OUT7 (GPIO_SD_B0_03)
I would suggest looking at using a timer that can be triggered to start, that can set a high output at count value 1 and a low output at count value 2, and then stops.
Trigger it to start using an XBAR_IN pin.
XBAR discribed here:
Yes, I've connected my "variable-interval signal input" to QTMR via XBAR. Also, I can start timer to set output to high. But subsequently to set the output to low proved to be difficult.
I even tried DMA to set an GPIO to high and link to 2nd DMA to start a timer. Upon expiration of the timer, it triggers 3rd DMA to set the GPIO to low. But the QTMR timer is not built for generating DMA event that I was hoping for.