diff -r ec6271f0637b -r 237d1f5c1c32 src/timer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/timer.c Thu Apr 03 19:44:53 2014 +0300 @@ -0,0 +1,92 @@ +#include + +#define TIMER_FLAGS GPIOR0 +#define TIMER1_BUSY 1 + +/* + * Setup timers. + */ +void timer_init (void) +{ + TCCR1A = ( + // OC1A output pin disconnected + 0b00 << COM1A0 + // OC1B output pin disconnected + | 0b00 << COM1B0 + // no PWM + | 0b00 << WGM10 + ); + TCCR1B = ( + // CTC mode + 0b01 << WGM12 + ); + TCCR1C = 0; +} + +void timer1_start (short cycles) +{ + // count up from zero... + TCNT1 = 0; + + // ...to the given number of timer cycles + OCR1A = cycles; + + // start! + sbi(&TIMER_FLAGS, TIMER1_BUSY); + TIMSK1 = ( + // OCA interrupt + 0b1 << OCIE1A // enable + ); + TCCR1B = ( + // WGM + 0b01 << WGM12 // CTC + + // clocksource + | 0b101 << CS10 // 1024'th + ); +} + +static void timer1_stop () +{ + // WGM: normal + // clocksource: stop + TCCR1B = 0; + + cbi(&TIMER_FLAGS, TIMER1_BUSY); +} + +ISR(TIMER1_COMPA_vect) +{ + timer1_stop(); + + // XXX: cpu will automatically wake up from sleep() +} + +/* + * Sleep on timer1 interrupt. + */ +void timer_sleep (int cycles) +{ + // set timer + timer1_start(cycles); + + // sleep + // TODO: PRR + SMCR = ( + // idle sleep + (0b00 << SM0) + + // enable sleep + | (0b1 << SE) + ); + + // sleep + while (tbi(&TIMER_FLAGS, TIMER1_BUSY)) { + __asm__ ( "sleep" :: ); + } + + // cleanup + SMCR = 0; +} + +