# HG changeset patch # User Tero Marttila # Date 1398023261 -10800 # Node ID 504c2310cddb71844f8e213f7a0fb25f91d97ea7 # Parent 975a2dffdcdaef7cece1db659af0f49c022d11d8 timer: continuous interval-sleep operation diff -r 975a2dffdcda -r 504c2310cddb src/timer.c --- 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; } }