From: simimeie Date: Sun, 27 Jun 2010 22:18:26 +0000 (+0000) Subject: timing functions - offering low res 'tick' counts, and high res timestamp counts... X-Git-Url: http://git.rrze.uni-erlangen.de/gitweb/?a=commitdiff_plain;h=10ee5c5d2f67244662b528199b9f0d406fd2fefa;p=moodlight.git timing functions - offering low res 'tick' counts, and high res timestamp counts (exact to one cpu cyle, except you can never use that precision because a few hundred cycles are probably neede for processing it) desperately needed for the IR decoding code. --- diff --git a/timers.c b/timers.c new file mode 100644 index 0000000..754db06 --- /dev/null +++ b/timers.c @@ -0,0 +1,85 @@ +/* $Id: timers.c,v 1.1 2010/06/27 22:18:26 simimeie Exp $ + * Functions for timing. + * This mainly allows you to get a timestamp value + */ + +#include +#include +#include "timers.h" + +/* Internal ticks */ +static volatile uint16_t ticks = 0; + +/* FIXME TCNT1H TCNT1L */ + +/* Executes every 65536 cpu cycles when the timer overflows */ +ISR(TIMER1_OVF_vect) +{ + ticks++; +} + +uint16_t getticks(void) +{ + uint16_t res; + cli(); + res = ticks; + sei(); + return res; +} + +uint16_t getticks_noirq(void) +{ + return ticks; +} + +struct timestamp gettimestamp(void) +{ + uint16_t cou1, cou2, tick1; + struct timestamp res; + /* Low byte must be read first for 16bit registers */ + cou1 = TCNT1L; + cou1 |= (uint16_t)(TCNT1H) << 8; + tick1 = getticks(); /* enables interrupts! */ + cou2 = TCNT1L; + cou2 |= (uint16_t)(TCNT1H) << 8; + if (cou1 > cou2) { /* An overflow occured in between */ + /* get new ticks value - we could already have it, but we do not know + * for sure. If we get another one now, we do - because there is no + * way we're going to need another 65k cpu cycles. */ + res.ticks = getticks(); + } else { /* no overflow. */ + res.ticks = tick1; + } + res.partticks = cou2; + return res; +} + +struct timestamp gettimestamp_noirq(void) +{ + uint16_t cou1, cou2; uint8_t ovf; + struct timestamp res; + /* Low byte must be read first for 16bit registers */ + cou1 = TCNT1L; + cou1 |= (uint16_t)(TCNT1H) << 8; + /* Check if there is an overflow pending */ + ovf = TIFR1 & _BV(TOV1); + if (ovf) { + /* Overflow pending, reread the counter to be sure */ + cou2 = TCNT1L; + cou2 |= (uint16_t)(TCNT1H) << 8; + res.ticks = ticks + 1; + res.partticks = cou2; + } else { + res.ticks = ticks; + res.partticks = cou1; + } + return res; +} + +void timers_init(void) +{ + /* Enable counter1, no prescaling (1 increment per clock cycle!) */ + TCCR1B |= _BV(CS10); + /* Enable interrupt when timer overflows (at 65536) */ + TIMSK1 |= _BV(TOIE1); +} diff --git a/timers.h b/timers.h new file mode 100644 index 0000000..75cf012 --- /dev/null +++ b/timers.h @@ -0,0 +1,41 @@ +/* $Id: timers.h,v 1.1 2010/06/27 22:18:26 simimeie Exp $ + * Functions for timing. + * This mainly allows you to get a timestamp value + */ + +#ifndef _TIMERS_H_ +#define _TIMERS_H_ + +/* timestamps are usually delivered in 'ticks'. + * At 8.0 MHz, there are ca. 122 ticks per second, and the 16 bit tick counter + * overflows about every 536 seconds. + * If you need exacter timing, you can also get a struct timestamp. + * That will contain the tick value and the current counter value as + * an uint16, giving you a precision of up to 1 cpu cycle. */ + +#define TICKSPERSECOND (CPUFREQ / 65536UL) +#define TICKSPERSECONDF ((float)CPUFREQ / 65536.0) + +struct timestamp { + uint16_t ticks; + uint16_t partticks; +}; + +/* Init timers */ +void timers_init(void); + +/* get ticks. + * Warning: Will reenable interrupts if they were disabled. */ +uint16_t getticks(void); +/* The same, but won't touch the global interrupt enable bit. + * MUST BE CALLED WITH INTERRUPTS DISABLED */ +uint16_t getticks_noirq(void); + +/* get timestamp + * Warning: Will reenable interrupts if they were disabled. */ +struct timestamp gettimestamp(void); +/* The same, but won't touch the global interrupt enable bit. + * MUST BE CALLED WITH INTERRUPTS DISABLED */ +struct timestamp gettimestamp_noirq(void); + +#endif /* _TIMERS_H_ */