I'm trying to add oversampling capability to some old code that used a single timer interrupt using a second timer with an interrupt. I've been using this thread as reference: Arduino Due - Arduino Forum
So far from testing this it doesn't seem that TC4_Handler() ever gets called, as realTotal and imagTotal never get changed from zero. TC3_Handler() gets called as expected however. I feel like I must have made a silly mistake.
Relevant parts of code:
#define OVERSAMPLE 4
/* Pins for reading impedance */
#define REAL_1 A0
#define IMAG_1 A1
/* Impedance reading global variables */
volatile unsigned int real1 = 0;
volatile unsigned int imag1 = 0;
volatile unsigned int realTotal = 0;
volatile unsigned int imagTotal = 0;
/* Misc Global Variables */
volatile byte dataReady = 0;
volatile byte finished = 0;
void readImpedanceAvg()
{
realTotal += analogRead(REAL_1);
imagTotal += analogRead(IMAG_1);
}
void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq, uint32_t frequency)
{
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)irq);
TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4);
uint32_t rc = VARIANT_MCK/128/frequency; //128 because we selected TIMER_CLOCK4 above
TC_SetRA(tc, channel, rc/2); //50% high, 50% low
TC_SetRC(tc, channel, rc);
TC_Start(tc, channel);
tc->TC_CHANNEL[channel].TC_IER=TC_IER_CPCS;
tc->TC_CHANNEL[channel].TC_IDR=~TC_IER_CPCS;
NVIC_EnableIRQ(irq);
}
void setup()
{
// ...
currentDecade = 0;
currentFreq = START_FREQ;
updateFreq(START_FREQ);
if(SWEEP)
{
// This timer will take multiple readings to average out
startTimer(TC1, 1, TC4_IRQn, 1000/INTERVAL/OVERSAMPLE);
delay(1);
// Since the timer ISR begins with a read, I need to start the first
// frequency before starting the timer, and the first call to this ISR
// will update to the SECOND frequency, hence currentIncrement = 1
currentIncrement = 1;
startTimer(TC1, 0, TC3_IRQn, 1000/INTERVAL);
}
else
{
// Start TC5 to handle constant frequency impedance measurement at
// 100 samples per second
startTimer(TC1, 2, TC5_IRQn, 1000/10); // 10 ms period for timer
}
}
void loop()
{
if(dataReady)
{
sendReading();
dataReady = 0;
}
if(finished)
{
// stop timer
NVIC_DisableIRQ(TC3_IRQn);
NVIC_DisableIRQ(TC4_IRQn);
setup();
}
// ...
}
byte oversample_lookup(byte oversample_amount)
{
switch(oversample_amount)
{
case 1: return 0;
case 2: return 1;
case 4: return 2;
case 8: return 3;
case 16: return 4;
case 32: return 5;
case 64: return 6;
default: return 0;
}
}
/* -----------------------------------------------------------------------------
TC3_HANDLER
---
This is the ISR for when the 3rd timer runs out.
This is specifically the ISR for the timer that is enabled if we are doing
a frequency sweep.
----------------------------------------------------------------------------- */
void TC3_Handler()
{
TC_GetStatus(TC1, 0); // accept interrupt
// Since the frequency is about to be updated, I need to store
// the frequency associated with the read immediately prior to this for
// whenver the main loop gets to it
sendFreq = currentFreq;
// Average out the previous readings
real1 = realTotal >> oversample_lookup(OVERSAMPLE);
imag1 = imagTotal >> oversample_lookup(OVERSAMPLE);
realTotal = imagTotal = 0;
dataReady = 1; // lets the main loop know a reading is ready to send
currentFreq = START_FREQ*pow(10, (double)currentIncrement/NUM_INCR + currentDecade);
if(currentFreq <= END_FREQ)
{
updateFreq(currentFreq);
++currentIncrement;
}
else
{
finished = 1;
}
// End of a decade
if(currentIncrement >= NUM_INCR)
{
++currentDecade;
currentIncrement = 0;
}
}
/* -----------------------------------------------------------------------------
TC4_HANDLER
---
The ISR to take readings at a single frequency to be averaged out in TC3 ISR
before sending to LabVIEW in the main loop
----------------------------------------------------------------------------- */
void TC4_Handler()
{
TC_GetStatus(TC1, 1); // accept interrupt
readImpedanceAvg();
}
/* -----------------------------------------------------------------------------
TC5_HANDLER
---
This is the ISR for when the 4th timer runs out. It should read the analog
values for the impedances, then set the serial write flag that is checked
in the main loop, as the Serial library does not work in an interrupt.
This is specifically the ISR for the timer that is enabled if we are doing
a constant frequency, so it simply reads the impedance and doesn't change
any frequencies.
----------------------------------------------------------------------------- */
void TC5_Handler()
{
TC_GetStatus(TC1, 2); // accept interrupt
readImpedance();
dataReady = 1;
}
Thanks in advance for any help!