// Fast Timer
// Written by John Wasser
//
// Returns the current time in 16ths of a microsecond.
// Overflows every 268.435456 seconds.
// Note: Since this uses Timer1, Pin 9 and Pin 10 can't be used for
// analogWrite().
void StartFastTimer()
{
noInterrupts (); // protected code
// Reset Timer 1 to WGM 0, no PWM, and no clock
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0; // Reset the counter
TIMSK1 = 0; // Turn off all Timer1 interrupts
// Clear the Timer1 Overflow Flag (yes, by writing 1 to it)
// so we don't get an immediate interrupt when we enable it.
TIFR1 = _BV(TOV1);
TCCR1B = _BV(CS10); // start Timer 1, no prescale
// Note: For longer intervals you could use a prescale of 8
// to get 8 times the duration at 1/8th the resolution (1/2
// microsecond intervals). Set '_BV(CS11)' instead.
TIMSK1 = _BV(TOIE1); // Timer 1 Overflow Interrupt Enable
interrupts ();
}
volatile uint16_t Overflows = 0;
ISR(TIMER1_OVF_vect)
{
Overflows++;
}
unsigned long FastTimer()
{
unsigned long currentTime;
uint16_t overflows;
noInterrupts();
overflows = Overflows; // Make a local copy
// If an overflow happened but has not been handled yet
// and the timer count was close to zero, count the
// overflow as part of this time.
if ((TIFR1 & _BV(TOV1)) && (TCNT1 < 1024))
overflows++;
currentTime = overflows; // Upper 16 bits
currentTime = (currentTime << 16) | TCNT1;
interrupts();
return currentTime;
}
// Demonstration of use
#if 1
void setup()
{
Serial.begin(115200);
while (!Serial);
StartFastTimer();
}
void loop()
{
static unsigned long previousTime = 0;
unsigned long currentTime = FastTimer();
Serial.println(currentTime - previousTime);
previousTime = currentTime;
delay(100);
}
#endif