+/* $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);
+}