--- a/src/timer.c Sun Apr 20 21:55:44 2014 +0300
+++ b/src/timer.c Sun Apr 20 22:47:41 2014 +0300
@@ -18,11 +18,16 @@
);
TCCR1B = (
// CTC mode
- 0b01 << WGM12
+ 0b01 << WGM12
);
TCCR1C = 0;
}
+static void timer1_set ()
+{
+ sbi(&TIMER_FLAGS, TIMER1_BUSY);
+}
+
void timer1_start (short cycles)
{
// count up from zero...
@@ -32,7 +37,7 @@
OCR1A = cycles;
// start!
- sbi(&TIMER_FLAGS, TIMER1_BUSY);
+ timer1_set();
TIMSK1 = (
// OCA interrupt
0b1 << OCIE1A // enable
@@ -46,58 +51,76 @@
);
}
+/*
+ * Keep the timer running, but clear the flag..
+ */
+static void timer1_clear ()
+{
+ cbi(&TIMER_FLAGS, TIMER1_BUSY);
+}
+
+/*
+ * Stop the timer at its current value.
+ */
static void timer1_stop ()
{
// WGM: normal
// clocksource: stop
TCCR1B = 0;
- cbi(&TIMER_FLAGS, TIMER1_BUSY);
+ timer1_clear();
}
ISR(TIMER1_COMPA_vect)
{
- timer1_stop();
+ timer1_clear();
- // XXX: cpu will automatically wake up from sleep()
+ // cpu will wake up from sleep()
}
/*
* Sleep on timer1 interrupt.
*
- * Returns 0 on interrupt, 1 on timeout.
+ * Starts fresh timer that sleeps given cycles if given, or continues on the running timer.
+ *
+ * Returns 1 on timeout, 0 on other interrupt.
*/
char timer_sleep (unsigned cycles)
{
if (cycles) {
- // set timer
+ // set fresh timer
timer1_start(cycles);
+ } else {
+ // wait for next cycle...
+ timer1_set();
}
- // sleep
- // TODO: PRR
- SMCR = (
- // idle sleep
- (0b00 << SM0)
+ // sleep while timer is running
+ // XXX: atomic?
+ if (tbi(&TIMER_FLAGS, TIMER1_BUSY)) {
+ // TODO: PRR
+ SMCR = (
+ // idle sleep
+ (0b00 << SM0)
- // enable sleep
- | (0b1 << SE)
- );
-
- // sleep
- __asm__ ( "sleep" :: );
+ // enable sleep
+ | (0b1 << SE)
+ );
- // cleanup
- SMCR = 0;
-
- if (cycles && !tbi(&TIMER_FLAGS, TIMER1_BUSY)) {
+ // sleep
+ __asm__ ( "sleep" :: );
+
+ // cleanup
+ SMCR = 0;
+ }
+
+ if (tbi(&TIMER_FLAGS, TIMER1_BUSY)) {
+ // interrupt
+ return 0;
+
+ } else {
// timeout
return 1;
- } else {
- timer1_stop();
-
- // interrupt
- return 0;
}
}