//TestT4013 - QTIMER TEST PROGRAM for T4 (CAPTURE TEST on QT1 Timer2)
//===================================================================
//Author: TelephoneBill
//Original Example from: MANITOU's https://github.com/manitou48/teensy4/blob/master/qtmr_capture.ino
//Date: 29 AUG 2019
//Version: 001
//NOTES:
//TestT4013 - Have now changed "external pin 11" from being an OFLAG output in my last experiment (TestT4012) to being a CAPTURE input.
//You will need to jumper pin 23 (sq wave generator) to pin 11 in order to trigger the capture mechanism (from the rising edges of the sq wave input).
//HOWEVER - There is something ODD happening when the program first runs. Typing "v" to print "ISRTicks, ISRCompTicks, ISRCaptTicks" does not always print
//correctly in the serial monitor. It seems to fail to send output to the monitor, but after very many (about 17) attempts at typing "v<CRLF>" then it will suddenly display
//all the data that should have done previously. Typing "w<CRLF>" will then print out the current CAPTURE value (should be less than 10000, which is the CMPLD2 value).
//It looks like a buffer size has to get filled up first before any more characters will be output to the monitor (Teensyduino code area - maybe a bug).
//Notice that pin 11 is defined by the IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02 statement. The interesting fact is that in the previous experiment, this was an output pin
//for the OFLAG, but now it is an input pin - but there is nothing specifying the pins direction, so it must be "bi-directional" internally.
//OPERATION:
//The external T4 pin 11 becomes the trigger for making a CAPTURE. The analogWrite command on pin 23 generates a 4.5 KHz sq wave. The rising edges of this input signal (when
//jumpered from pin 23 to pin 11) then provide the stimulus to activate the internal capture, which is stored in register TMR1_CAPT2 (16 bits). By using the Input Edge Flag (IEF)
//of the SCTRL2 register (bit 10, R.M. page 3130), then an interrupt can be created which allows the TMR1_CAPT2 value to be stored into a local variable. This IEF flag must
//be cleared (in the ISR) in order to allow further interrupts to take place.
//definitions
byte Byte1;
volatile uint32_t ISRTicks, ISRCompTicks, ISRCaptTicks;
volatile uint16_t TMR1Capt2Value;
float CPUTemp;
//SETUP
//=====
void setup() {
//initialise general hardware
Serial.begin(9600); //setup serial port
pinMode(13, OUTPUT); //pin 13 as digital output
FlashLED(4); //confidence boost on startup
//turn on clocks for Timer QT1 (CG13)
CCM_CCGR6 |= CCM_CCGR6_QTIMER1(CCM_CCGR_ON);
//intialise QT1 Timer2 registers
TMR1_CTRL2 = 0; //stop all functions of QT1 Timer2 (Timers are known as 0,1,2,3)
//status and control register
TMR1_SCTRL2 = 0; //clear prior to setting
TMR1_SCTRL2 |= 0b0000010001000000; //no compare interrupt, no overflow, input edge flag enabled, rising capture, no forcing, no invert, external pin is input
TMR1_LOAD2 = 0; //counter starts counting from zero
TMR1_COMP12 = 10000-1; //66.7uS - count up to this value
TMR1_CMPLD12 = 10000-1; //load compare register with value from this register
//comparator status and control register
TMR1_CSCTRL2 = 0; //clear prior to setting
TMR1_CSCTRL2 |= 0b0000001001000001; //no debug, no fault, no altload, no reload, no trigger, count up, TCF1EN, no COMP2, COMP1
attachInterruptVector(IRQ_QTIMER1, QT1_isr);
NVIC_ENABLE_IRQ(IRQ_QTIMER1);
//configure Teensy pin Capture pin
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02 = 1; //sets up pin 11 as the "external pin" for QT1 Timer2 (see R.M. page 309).
//start timer
TMR1_CTRL2 = 0b0011000100100011; // 001(Count rising edges Primary Source),1000(IP Bus Clock),10 (Secondary Source = Timer2 input pin),
// 0(Count Once),1(Count up to Compare),0(Count Up),0(Co Channel Init),011(Toggle OFLAG on Compare)
analogWrite(23,128); //generate PWM 4.5 KHz sq wave
}
//ISR ROUTINE FOR QT1
//===================
void QT1_isr() { //ISR for QT1
//test flags
if (TMR1_CSCTRL2 & TMR_CSCTRL_TCF1) { //test if COMP1 flag set
TMR1_CSCTRL2 &= ~(TMR_CSCTRL_TCF1); //clear COMP1 flag
ISRCompTicks++;
}
if (TMR1_SCTRL2 & TMR_SCTRL_IEF) { //test if input edge capture event
TMR1_SCTRL2 &= ~(TMR_SCTRL_IEF); //clear input edge flag
ISRCaptTicks++;
TMR1Capt2Value = TMR1_CAPT2; //read the capture value
}
//update count
ISRTicks++;
asm volatile ("dsb"); // wait for clear memory barrier
}
//MAIN LOOP
//=========
void loop() {
//call KeyInput() routine
KeyInput();
}
//SUBROUTINES
//===========
//Flash LED routine
void FlashLED(int m) {
for (int n=0;n<m;n++) {
digitalWriteFast(13, 1); //set pin 13 high
delay(100);
digitalWriteFast(13, 0); //set pin 13 low
delay(100);
}
}
//KeyInput routine
void KeyInput() {
//process any keystrokes available
if (Serial.available()>0) {
//read the incoming byte
Byte1 = Serial.read();
if (Byte1>0x20) {
switch (Byte1) {
case 'T': //CPU core temp
//task goes here...
CPUTemp = tempmonGetTemp();
Serial.print("CPUTemp (deg C) = "); Serial.println(CPUTemp);
break;
case 'v': //print ISRTicks, ISRCompTicks, ISRCaptTicks
//task goes here...
Serial.print("ISRTicks = "); Serial.println(ISRTicks);
Serial.print("ISRCompTicks = "); Serial.println(ISRCompTicks);
Serial.print("ISRCaptTicks = "); Serial.println(ISRCaptTicks);
break;
case 'w': //print QT3 Timer1 Capture Value
//task goes here...
Serial.print("TMR1Capt2Value = "); Serial.println(TMR1Capt2Value);
break;
}
}
}
}