timing functions - offering low res 'tick' counts, and high res timestamp counts...
[moodlight.git] / timers.c
diff --git a/timers.c b/timers.c
new file mode 100644 (file)
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 <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);
+}
This page took 0.062592 seconds and 4 git commands to generate.