This version implements:
1. A 64-bit counter (in software, using interrupts) and 64-bit ring buffers. Thanks to the Hardware Timer library, using interrupts adds a single line of C to the setup code, and the callback function contains a single line of actual code, to increment the overflow counter!
2. I am testing the generation of an analog output with 16-bit resolution by taking advantage of the 16-bit resolution of the PWM output pins. Note that to really get 16-bit PWM resolution, a small typo has to be fixed in the current 2.0.0 release of STM32 core, see GitHub issue #1378.
On the hardware side, I put together/wired two more GPSDOs on breadboards, since I had the parts available to do so. This allows me to test the firmware on one GPSDO while having two more as backups.
Here is the Timer 2 setup code:
Code: Select all
// Setup and start Timer 2 which measures OCXO frequency
// setup pin used as ETR (10MHz external clock from OCXO)
pinMode(PA15, INPUT_PULLUP); // setup PA15 as input pin
pinModeAF(PA15, GPIO_AF1_TIM2); // setup PA15 as TIM2 channel 1 / ETR
// setup Timer 2 in input capture mode, active input channel 3
// to latch counter value on rising edge
// Instantiate HardwareTimer object. Thanks to 'new' instantiation, HardwareTimer is not destructed when setup() function is finished.
HardwareTimer *FreqMeasTim = new HardwareTimer(TIM2);
// Configure rising edge detection to measure frequency
FreqMeasTim->setMode(3, TIMER_INPUT_CAPTURE_RISING, PB10);
// Configure 32-bit auto-reload register (ARR) with maximum possible value
TIM2->ARR = 0xffffffff; // count to 2^32, then wraparound (approximately every 429 seconds)
#ifdef COUNT_64_TEST
// Configure the ISR for the timer overflow interrupt
FreqMeasTim->attachInterrupt(Timer2_Overflow_ISR);
#endif // COUNT_64_TEST
// select external clock source mode 2 by writing ECE=1 in the TIM2_SMCR register
TIM2->SMCR |= TIM_SMCR_ECE; // 0x4000
// start the timer
FreqMeasTim->resume();
Code: Select all
#ifdef COUNT_64_TEST
// Interrupt Service Routine for TIM2 counter overflow / wraparound
void Timer2_Overflow_ISR(void)
{
tim2overflowcounter++;
// do we have to manually clear the UIF bit in TIM2 status register? It seems so...
}
#endif // COUNT_64_TEST