I am trying to understand this piece of code, What I am not able to understand is how the interrupt routine works as the OCR1A is getting updated. I am using AVR series of controller to run this code.
void TimerInit(void)
{
DISABLE_TIMER_INT; // Disable timer interrupt
m_nGlobalTime = 0; // Reset system time
OCR1A += TICKS_PER_MSECOND; // Set first clock period
TCCR1A = 0;// Set TimerMode to Normal
TCCR1B |= (1 << CS10);// ClckIo, no pre-scaler; set TimerMode
ENABLE_INTERRUPTS;
ENABLE_TIMER_INT;// Enable send timer interrupt (1 ms)
}
ISR( TIMER1_COMPA_vect) {
uint16_t nTemp;
nTemp = TCNT1; // Get current time
nTemp -= OCR1A; // Subtract interrupt time
if (nTemp < (TICKS_PER_MSECOND / 2))// If more than half period left
{
OCR1A += (TICKS_PER_MSECOND);// Add Offset to OCR1A relative
}
else
{
OCR1A = TCNT1 + (TICKS_PER_MSECOND);// Set OCR1A to 1 ms absolute
}
m_nGlobalTime++;
}
The usual way to get an output compare interrupt to fire at a regular interval is to add a constant amount to the OCR1A
. This is happening at
OCR1A += (TICKS_PER_MSECOND);
For some reason, the writer added some extra logic to handle bad luck. Perhaps, the period is too short, or maybe the OC interrupt may be delayed due to some other interrupt running.
If these cases were to occur, then the next OC interrupt would not occur TICKS_PER_MSECOND
later than the last, but rather TICKS_PER_MSECOND
plus an entire cycle of the counter. That is, the correct time would be missed, as the OC register would be set to a number after the number has been passed.
This code is an attempt to correct for this situation. That being said, I'm not sure it works correctly. The potential problem is that nTemp
is unsigned, so the <
comparison might not do what the writer expects.