--- /dev/null
+/* $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 <avr/io.h>
+#include <avr/interrupt.h>
+#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);
+}
--- /dev/null
+/* $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_ */