Hi Arne,
I have been playing some with your new overflow handler, and mostly have replicated your results. I've also validated it by showing that your function yields the same values for timer0_millis and timer0_clock_cycles as the 0012 handler when F_CPU is 16MHz, 8MHz, or even 32MHz.
The timings I get when doing 100 million loops are as follows:
F_CPU = 16000000
Old = 613163ms
Arne's = 265139ms
2.31 speed improvement
F_CPU = 8000000
Old = 961640ms
Arne's = 265593ms
3.62 speed improvement
F_CPU = 32000000
Old = 438924ms
Arne's = 262063ms
1.67 speed improvement
The code I used to time and validate your results is as follows. Would you mind trying my sketch to see if you get the same results? If so, I'll type up a summary and present it to the developer's forum.
Mikal
volatile unsigned long old_timer0_clock_cycles = 0;
volatile unsigned long old_timer0_millis = 0;
void old_overflow()
{
old_timer0_clock_cycles += 64UL * 256UL;
while (old_timer0_clock_cycles > clockCyclesPerMicrosecond() * 1000UL) {
old_timer0_clock_cycles -= clockCyclesPerMicrosecond() * 1000UL;
old_timer0_millis++;
}
}
#if F_CPU > 32500L*1000L
typedef uint32_t t0cc_t;
#else
typedef uint16_t t0cc_t;
#endif
volatile t0cc_t arnes_timer0_clock_cycles = 0;
volatile unsigned long arnes_timer0_millis = 0;
#if F_CPU % 1000 != 0
#warning F_CPU is no integer multiple of 1000 Hz
#endif
// clock cycles per milli second
#define CPM (F_CPU / 1000UL)
// timer 0 prescale factor is 64 and the timer overflows at 256
#define BF (64U * 256U)
void arnes_overflow()
{
register t0cc_t tmp = arnes_timer0_clock_cycles + BF % CPM;
if (tmp > CPM) {
arnes_timer0_clock_cycles = tmp - CPM;
arnes_timer0_millis += BF / CPM + 1;
} else {
arnes_timer0_clock_cycles = tmp;
arnes_timer0_millis += BF / CPM;
}
}
void setup()
{
Serial.begin(9600);
Serial.println("Hello!");
unsigned long start = millis();
for (long i=100000000; i; --i)
old_overflow();
start = millis() - start;
Serial.print("The old overflow function took ");
Serial.println(start);
start = millis();
for (long i=100000000; i; --i)
arnes_overflow();
start = millis() - start;
Serial.print("Arne's overflow function took ");
Serial.println(start);
old_timer0_clock_cycles = old_timer0_millis = 0;
arnes_timer0_clock_cycles = arnes_timer0_millis = 0;
for (unsigned long i=0; i<100000000; ++i)
{
if (old_timer0_clock_cycles != arnes_timer0_clock_cycles || old_timer0_millis != arnes_timer0_millis)
{
Serial.println("Mismatch!");
exit(1);
}
old_overflow(); arnes_overflow();
}
Serial.println("Both functions calculated the same values OK!");
}
void loop(){}