Hi,
I am trying to get input capture working but fails. Pin 5 is connected to the pps output of a gps. I have verified that I can read the pulse using digitalRead() so I know the pulse is there and the Due can measure it. I just cant get the input capture to work.
I have followed the "Timer interrupts on Due" thread and read the data sheet and some but not all relevant source code in the arduino 1.5 package.
This is the code I am running, based on the code examples in the other thread. I tried to comment it to explain what it does.
/*
trying to get input capture working for Arduion Due with GPS PPS signal connected to
pin 5. Based on the information in this discussion thread: Arduino Forum
It does not work, for some reason!
by Paul Dreik http://www.pauldreik.se/
*/
volatile boolean l;/*
interrupt callback. TC6=timer counter TC2 channel 0
*/
void TC6_Handler()
{
//reads the interrupt. necessary to clear the interrupt flag.
const uint32_t status=TC_GetStatus(TC2, 0);//has the timer overflowed?
const bool overflowed=status & TC_SR_COVFS;//input capture
const bool inputcaptureA=status & TC_SR_LDRAS;//loading overrun
const bool loadoverrun=status & TC_SR_LOVRS;Serial.print("TC6 interrupt! value=");
Serial.print(TC_ReadCV(TC2,0));//read LDRA
if(inputcaptureA) {
const uint32_t ra= TC2->TC_CHANNEL[0].TC_RA;
Serial.print(" ra=");
Serial.print(ra);
}Serial.print(" overflow=");
Serial.print(overflowed);
Serial.print(" LDRA=");
Serial.print(inputcaptureA);
Serial.print(" loadoverrun=");
Serial.print(loadoverrun);
Serial.print(" status=");
Serial.println(status);
}void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq) {
//see 37.7.9
REG_TC2_WPMR=0x54494D00;//enable configuring the io registers. see 32.7.42
REG_PIOC_WPMR=0x50494F00;//we need to configure the pin to be controlled by the right peripheral.
//pin 5 is port C. PIOC_PDR is defined in hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/instance/instance_pioc.h
//and PIO_PDR_P25 is defined in hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/component/component_pio.h
//this disables the pio from controlling the pin. see 32.7.2REG_PIOC_PDR |= PIO_PDR_P25;
//next thing is to assign the io line to the peripheral. See 32.7.24.
//we need to know which peripheral we should use. Read table 37-4 in section 37.5.1.
//TIOA6 is peripheral B, so we want to set that bit to 1.
//REG_PIOC_ABSR is defined in hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/instance/instance_pioc.h
//PIO_ABSR_P25 is defined in hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/component/component_pio.h
REG_PIOC_ABSR |= PIO_ABSR_P25;//allow configuring the clock.
pmc_set_writeprotect(false);/*
Every peripheral in the SAM3X is off by default (to save power) and
should be turned on.
*/
pmc_enable_periph_clk(ID_TC6);/*
configure the timer. All this is about setting TC_CMRx, see 37.7.10 in atmel pdf.
CLOCK1 is 42 MHz. We want input capture. Nothing else should be necessary.
*/
TC_Configure(tc, channel, TC_CMR_TCCLKS_TIMER_CLOCK1 | TC_CMR_LDRA_RISING);//set the interrupt flags. We want interrupt on overflow and TIOA6 (pin 5) going high.
const uint32_t flags=TC_IER_COVFS | TC_IER_LDRAS;
tc->TC_CHANNEL[channel].TC_IER=flags;
tc->TC_CHANNEL[channel].TC_IDR=~flags;//assume IER and IDR are equally defined.NVIC_EnableIRQ(irq);
//read away the status.
// TC_GetStatus(tc, channel);//start the timer
TC_Start(tc,channel);
}void setup(){
Serial.begin(115200);
startTimer(TC2, 0, TC6_IRQn); //TC2 channel 0, the IRQ for that channel
Serial.println("setup complete");
}//just repeatedly print the timer value, so we know that the processor is alive.
void loop(){
Serial.print("timer value is ");
Serial.println( TC_ReadCV(TC2,0));
delay(4000);}
This is the output I get:
setup complete
timer value is 105013
TC6 interrupt! value=15911893 ra=15842838 overflow=0 LDRA=1 loadoverrun=0 status=458784
timer value is 168425172
timer value is 336509174
timer value is 504593174
(snip)
timer value is 3866273174
timer value is 4034357174
timer value is 4202441174
TC6 interrupt! value=69116 overflow=1 LDRA=0 loadoverrun=0 status=327697
timer value is 75768118
timer value is 243809998
timer value is 411893996
As you see, there is an LDRA interrupt just at start and the overflow interrupt works as it should, but I would expect to get the LDRA interrupt (PPS) once per second.
Does anyone know what is going on?
thanks,
Paul