timing functions - offering low res 'tick' counts, and high res timestamp counts...
authorsimimeie <simimeie>
Sun, 27 Jun 2010 22:18:26 +0000 (22:18 +0000)
committersimimeie <simimeie>
Sun, 27 Jun 2010 22:18:26 +0000 (22:18 +0000)
desperately needed for the IR decoding code.

timers.c [new file with mode: 0644]
timers.h [new file with mode: 0644]

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);
+}
diff --git a/timers.h b/timers.h
new file mode 100644 (file)
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_ */
This page took 0.074377 seconds and 4 git commands to generate.