understanding timer interrupts

hi everyone,

I'm trying to port over some code to the Due, and I'm having trouble understanding the section that deals with ISR and timer/counters - more specifically, I'm unsure exactly with which settings the timer is being initialized. I'm looking at the following:

  TCCR1A = 0;
  TCCR1B = _BV(WGM13);

  ICR1 = (F_CPU / 4000000) * TIME_CHUNK; // goes twice as often as time chunk, but every other event turns off pins
  TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
  TIMSK1 = _BV(TOIE1);
  TCCR1B |= _BV(CS10);

I plan on using the following timer library on the due in order to handle timer ISR, however I'm uncertain about how the original timer is setup. Could someone please shed some light into this? I'm afraid I still don't quite understand bit math so I can't tell to which value each of the register values is being set. I was hoping someone could simply tell me to what frequency the timer is set as well as which mode.

Furthermore, I don't understand how ICR1 works in this case since from the rest of the code, I understand that once timer1 overflows an ISR is called because the code contains
ISR(TIMERx_OVF_vect) there is no mention of the timer input capture interrupt service routine within the original code.

Thanks for the help and enlightenment everyone!

This is from the Atmega328, right?

This line doesn't seem to me to do anything useful:

  TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));

So we can ignore that.


This seems to turn on mode 8: PWM, phase correct, top at ICR1:

  TCCR1B = _BV(WGM13);

  TIMSK1 = _BV(TOIE1);

You get an interrupt on Timer 1 overflow (TIMER1_OVF_vect).


This won't do anything:

ISR(TIMERx_OVF_vect)

Start the timer with no prescaler:

  TCCR1B |= _BV(CS10);

  ICR1 = (F_CPU / 4000000) * TIME_CHUNK; // goes twice as often as time chunk, but every other event turns off pins

Assuming F_CPU is 16000000 it will count up to 4 * TIME_CHUNK.

Plus 1, because the count is zero-relative.

Are the Mega328P register names going to work on the Due?
Will they work the same way?

I think he just wants to understand what the original is doing, so he can plug the correct values into the Due library.

That's correct.

I'm understanding (please correct if wrong) that timer1 is simply setup to interrupt on overflow. Is it correct to assume that the timer overflows every
(F_CPU / 4000000) * TIME_CHUNK; // goes twice as often as time chunk, but every other event turns off pins?

So, using the Due timer/interrupt library I could simply do:

long freq = (F_CPU / 4000000) * TIME_CHUNK; // goes twice as often as time chunk, but every other event turns off pins
startTimer1(freq, interruptRoutine); // (Frequency, function)

where interruptRoutine is the function that is called upon timer overflow?

Is it correct to assume that the timer overflows every ...

Yes, plus 1.

If the number happens to be 50, it will count 51 times because it includes zero.

So, using the Due timer/interrupt library I could simply do: ...

I haven't used the Due yet, but in principle that looks OK.

Hi Nick!

thanks for the speedy replies and help, I'll get to some testing this week and post back if I'm having any difficulty!

This is a phase and frequency correct PWM mode, so the counter will count to N, turn around and count back down to 0. It will then call the overflow ISR. It doesn't seem to be doing anything other than using ICR1 to set the TOP value (probably because it is double buffered). So if N is 50, it will generate an overflow every 100 counts.

For example: If ICR1 was set to 3, the TCNT1 register progression would be to start at 0, 1, 2, 3, 2, 1, 0, 1, 2,.... Since it started at 0, three ticks to get to the TOP and three ticks to get back to 0.

I assume that the overflow ISR is doing something with toggling pins based upon the comments.

In the original the ISR didn't do anything at all because it was misnamed:

ISR(TIMERx_OVF_vect)

I saw that too, but I figured since the OP wasn't asking for help with mysterious resets, that the real program must have it correctly spelled out somewhere. :wink: But yeah, any routine named exactly the way the OP showed isn't being called by the interrupt processor.

afremont:
I assume that the overflow ISR is doing something with toggling pins based upon the comments.

Yep, you assumed correctly. The code is used to drive a stepper motor which needs an alternating HIGH/LOW sequence of pin actuation.

Yep, it was misnamed, must have happened while I was doing some reading on TIMERx, the correct version should be:

ISR(TIMER1_OVF_vect)