diff --git a/magictimerasused220416.ino b/magictimerasused220416.ino new file mode 100644 index 0000000..f1b0738 --- /dev/null +++ b/magictimerasused220416.ino @@ -0,0 +1,132 @@ +#include + +void TimersStart() { + + uint32_t config = 0; + + // Set up the power management controller for TC0 and TC2 + + pmc_set_writeprotect(false); // Enable write access to power management chip + pmc_enable_periph_clk(ID_TC0); // Turn on power for timer block 0 channel 0 + pmc_enable_periph_clk(ID_TC6); // Turn on power for timer block 2 channel 0 + + // Timer block zero channel zero is connected only to the PPS + // We set it up to load regester RA on each PPS and reset + // So RA will contain the number of clock ticks between two PPS, this + // value should be very stable +/- one tick + + config = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Select fast clock MCK/2 = 42 MHz + TC_CMR_ETRGEDG_RISING | // External trigger rising edge on TIOA0 + TC_CMR_ABETRG | // Use the TIOA external input line + TC_CMR_LDRA_RISING; // Latch counter value into RA + + TC_Configure(TC0, 0, config); // Configure channel 0 of TC0 + TC_Start(TC0, 0); // Start timer running + + TC0->TC_CHANNEL[0].TC_IER = TC_IER_LDRAS; // Enable the load AR channel 0 interrupt each PPS + TC0->TC_CHANNEL[0].TC_IDR = ~TC_IER_LDRAS; // and disable the rest of the interrupt sources + NVIC_EnableIRQ(TC0_IRQn); // Enable interrupt handler for channel 0 + + // Timer block 2 channel zero is connected to the OR of the PPS and the RAY event + + config = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Select fast clock MCK/2 = 42 MHz + TC_CMR_ETRGEDG_RISING | // External trigger rising edge on TIOA1 + TC_CMR_ABETRG | // Use the TIOA external input line + TC_CMR_LDRA_RISING; // Latch counter value into RA + + TC_Configure(TC2, 0, config); // Configure channel 0 of TC2 + TC_Start(TC2, 0); // Start timer running + + TC2->TC_CHANNEL[0].TC_IER = TC_IER_LDRAS; // Enable the load AR channel 0 interrupt each PPS + TC2->TC_CHANNEL[0].TC_IDR = ~TC_IER_LDRAS; // and disable the rest of the interrupt sources + NVIC_EnableIRQ(TC6_IRQn); // Enable interrupt handler for channel 0 + + // Set up the PIO controller to route input pins for TC0 and TC2 + + PIO_Configure(PIOC,PIO_INPUT, + PIO_PB25B_TIOA0, // D2 Input + PIO_DEFAULT); + + PIO_Configure(PIOC,PIO_INPUT, + PIO_PC25B_TIOA6, // D5 Input + PIO_DEFAULT); +} + +// Define some output debug pins to monitor whats going on via my scope + +#define PPS_PIN 13 // PPS (Pulse Per Second) and LED +#define EVT_PIN 12 // Cosmic ray event detected +#define FLG_PIN 11 // Debug flag + +static uint32_t displ = 1; // Display values in loop + +static uint32_t ppsfl = LOW, // PPS Flag boolean + rega0 = 0, // RA reg + stsr0 = 0, // Interrupt status register + ppcnt = 0; // PPS count + + +static uint32_t event = 0, // Time of the last event (This should be a queue !) + rega1 = 0, + stsr1 = 0; + +void TC0_Handler() { + + // This ISR is connected only to the PPS (Pulse Per Second) GPS event + // Each time this runs, set the flag to tell the TC6 ISR we have seen it + // This logic only works if the TC0 handler gets called before the TC6 handler + // hence the debug flag which I look at with a scope to be sure. + // I may introduce a small delay line to ensure this is true, so far it is. + + //ppsfl = HIGH; // Seen a rising edge on the PPS + //digitalWrite(PPS_PIN,HIGH); // PPS arrived + //digitalWrite(FLG_PIN,ppsfl); // Flag set (for debug) + rega0 = TC0->TC_CHANNEL[0].TC_RA; // Read the RA reg (PPS period) + stsr0 = TC_GetStatus(TC0, 0); // Read status and clear load bits + //event = 0; + + ppcnt++; // PPS count + displ = 1; // Display stuff in the loop +} + + +void TC6_Handler() { + + // This ISR is connected to the OR of the event and the PPS + // If the TC0 has seen the PPS it sets the flag high + // and if its high we are seeing the PPS here, but if the + // flag is not set then this is a cosmic ray event. + + //if (ppsfl == HIGH) { // Was ther a PPS ? + //ppsfl = LOW; // Yes so we have seen it here + //digitalWrite(PPS_PIN,LOW); // Reset PPS + //digitalWrite(EVT_PIN,LOW); // Not an event + //} else { + //digitalWrite(EVT_PIN,HIGH); // Event detected + //event = TC2->TC_CHANNEL[0].TC_RA; + //} + + //digitalWrite(FLG_PIN,ppsfl); // Flag out + //Serial.print("event"); + + event = TC0->TC_CHANNEL[0].TC_CV; // Read thge RA on channel 1 (PPS period) + stsr1 = TC_GetStatus(TC2, 0); // Read status clear load bits +} + +void setup() { + //pinMode(FLG_PIN, OUTPUT); // Pin for the ppsfl flag for debug + //pinMode(EVT_PIN, OUTPUT); // Pin for the cosmic ray event + //pinMode(PPS_PIN, OUTPUT); // Pin for the PPS (LED pin) + Serial.begin(115200); // Start the serial line + TimersStart(); // Start timers +} + +void loop() { + if (displ) { + Serial.print("ppcnt: "); Serial.print(ppcnt);Serial.print(", "); + Serial.print("rega0: "); Serial.print(rega0);Serial.print(", "); + Serial.print("event: "); Serial.print(event); + Serial.println(""); + displ = 0; + } +}