Hi all,
Here's my attempt to make the millis and micros function smaller and faster with a fast ISR .
Please feel free to point out any oversights since I'm more of a tinkerer than a programmer.
I realize this will only work with chips that use TIFR0 since you can set OCR0A other than 255.
You also need a 16Mhz (OCR0A = 249) or 8Mhz clock (OCR0A = 124).
#IFDEF statements could make wiring.c compatible with older chips by using the original method when TIFR is used.
So here's what I did for a 16Mhz clock:
The init() function has two lines added
1- Set Timer0 to Fast PWM mode 7. It's normally set to Fast PWM mode 3. See Page 108 Table 14-8 ATMega48/88/168/328
sbi(TCCR0B, WGM02); // Yes in TCCR0B
sbi(TCCR0A, WGM01);
sbi(TCCR0A, WGM00);
2- Set OCR0A to 249. Including 0 this will make 250 ticks.
16Mhz / (64 * (249 + 1)) = 1000uS per Overflow
OCR0A = 249; // For 16Mhz clock
The ISR would now be much shorter because fractions are gone:
SIGNAL(TIMER0_OVF_vect)
{unsigned long m = timer0_millis;
m++;
timer0_millis = m; }
The millis() function stays the same
The micros() function has 3 lines changed
m = timer0_millis; // used to be m = timer0_overflow_count;
if ((TIFR0 & _BV(TOV0)) && (t < 249)) // 249 instead of 255
return ((m * 1000ul) + (unsigned int(t) * 4); // (64 / clockCyclesPerMicrosecond()) would also work in place of 4
// An 8Mhz clock would use 8 since it has a resolution of 8uS
For testing, the only thing the ISR for Timer0 did was toggle pin 13: PORTB ^= B00100000.
I checked the frequency with a frequency counter on my DMM and it was super close to calculated = 500HZ.
I am using an ATMega168 Boarduino with 16Mhz resonator.
I didn't test with 8Mhz.
Thanks for reading,
Charlie Hughes