Hi,
I have a working Flextimer (FTM1) program based on some code found on the forum and I wanted to know if it was possible to reset / modify the FTM1_MOD in the main loop :
Basically, I am comparing a 10Mhz signal with a 1pps from GPS.
The goal is to, once the 10mhz is setlled and corrected thanks to the GPS 1pps, only count the 10mhz, to derive a second : I therefore need to go from FTM1_MOD=0xFFFF to FTM1_MOD=0x270F (=9999) in order to precisely calculate a second.
Of course, if you have a better idea, just let me know !
Thanks for your help !
I have a working Flextimer (FTM1) program based on some code found on the forum and I wanted to know if it was possible to reset / modify the FTM1_MOD in the main loop :
Code:
/*https://forum.pjrc.com/threads/30822-Teensy-3-1-and-Flextimer(s)-Counting-external-pulses-accurately
* Connect pin 10 (CMP1_OUT) to pin 23 (FTM1_QD_PHA)
* Connect 10 MHz sinewave input (200 mV peak) to Teensy pin 3 (A9)
* Connect 1 pps trigger to pin 16 (A2)
*/
const int base_frequency = 10000000;
volatile uint32_t CountValue, CountValueOld;
volatile uint32_t FTM1CountOVFlow; // don't need to initialize since rollover is handled
volatile bool CaptureFlag = false;
bool CountingOK = false;
void setup() {
pinMode(4, INPUT_PULLUP); // Needed for Quad decoder
Serial.begin(0);
while (!Serial);
Serial.println(__FILE__ " " __DATE__ " " __TIME__);
//ComparatorSetup();
FTM1Setup();
Serial.printf("%9s %11s\n", "Frequency", "CountValue");
}
void loop() {
unsigned long ppsWatchdog = millis() + 1100;
while (!CaptureFlag && millis() < ppsWatchdog); // loop and wait up to 1.1 s
if (CaptureFlag) {
CaptureFlag = false; // clear flag from channel
if (CountingOK) Serial.printf("%9lu %11ld\n", CountValue-CountValueOld,CountValue-CountValueOld-base_frequency);
CountValueOld = CountValue;
CountingOK = true; // postpones displaying until 2 CaptureFlags in a row
} else {
Serial.println("1 pps missing.");
CountingOK = false;
}
}
// Setup FlexTimer1
void FTM1Setup() {
// input capture 1 pps on Teensy pin 16 (A2), 10 MHz clock from Teensy pin 3
// FTM1 Channel 0
FTM1_MODE = FTM_MODE_WPDIS | FTM_MODE_FTMEN;
FTM1_FILTER = 0x00; // no filtering
FTM1_SC = 0;
FTM1_CNTIN = 0; // Count initial value
FTM1_CNT = 0x0000; // Reset the count to CNTIN
FTM1_MOD = 0xFFFF; // max modulus = 65535 (0xFFFF)
FTM1_C0SC = FTM_CSC_ELSA; // Rising edge no interrupts
//configure Teensy input capture channels
PORTA_PCR12 |= PORT_PCR_MUX(7); //MUX = alternative function 7 on Chip Pin 28 (FTM1_QD_PHA) = Teensy Pin 3 -- Signal to count
PORTA_PCR13 |= PORT_PCR_MUX(7); //MUX = alternative function 7 on Chip Pin 29 (FTM1_QD_PHB) = Teensy Pin 4 -- Tie high
PORTB_PCR0 |= PORT_PCR_MUX(3); //MUX = alternative function 3 on Chip Pin 35 (FTM1_CH0) = Teensy Pin 16 (A2)
SIM_SOPT4 |= SIM_SOPT4_FTM1CH0SRC(0); // 00 source is FTM1_CH0 signal (1 pps)
//set flextimer quad decode mode and enable overflow interrupt
FTM1_QDCTRL = FTM_QDCTRL_QUADMODE | FTM_QDCTRL_QUADIR | FTM_QDCTRL_QUADEN; // comes in on pin 3
FTM1_SC = FTM_SC_TOIE | FTM_SC_CLKS(0); // actually not important in QUAD mode ?
NVIC_ENABLE_IRQ(IRQ_FTM1);
// NVIC_SET_PRIORITY(IRQ_FTM1, 48);
Serial.println("FlexTimer FTM1 Setup Complete");
}
extern "C" void FASTRUN ftm1_isr(void) { // Process CHF first, unless counter is close to overflow
if (FTM1_SC & FTM_SC_TOF) { // read the timer overflow flag (TOF in FTM1_SC) rate = 10 MHz/65536 ~ 152 Hz, 6.6 ms
FTM1_SC &= ~FTM_SC_TOF; // clear interrupt from timer overflow
FTM1CountOVFlow++;
} // TOF
// now poll CH0 and see if it had any activity
if (FTM1_C0SC & FTM_CSC_CHF) { // rate = 1 pps
FTM1_C0SC &= ~FTM_CSC_CHF; // clear flag from channel
CaptureFlag = true;
if (FTM1_C0V < FTM1_CNT) {CountValue = (FTM1CountOVFlow << 16) + FTM1_C0V; return;} // very rare - just happened since interrupt
else {CountValue = (FTM1CountOVFlow << 16) + FTM1_C0V - (1 << 16); return;} // from 10 us into previous cycle
}
delayMicroseconds(10); // to split the interval -- should be longer than max. interrupt latency
if (FTM1_C0SC & FTM_CSC_CHF) { // try again, now 10 us into new cycle; good if no other interrupts are > 10 us
FTM1_C0SC &= ~FTM_CSC_CHF; // clear flag from channel
CaptureFlag = true;
CountValue = (FTM1CountOVFlow << 16) + FTM1_C0V; // happened between just after start and 100 us into cycle
}
} // ISR
Basically, I am comparing a 10Mhz signal with a 1pps from GPS.
The goal is to, once the 10mhz is setlled and corrected thanks to the GPS 1pps, only count the 10mhz, to derive a second : I therefore need to go from FTM1_MOD=0xFFFF to FTM1_MOD=0x270F (=9999) in order to precisely calculate a second.
Of course, if you have a better idea, just let me know !
Thanks for your help !