--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/timer.inc Sat May 08 17:27:27 2010 +0300
@@ -0,0 +1,93 @@
+;; vim: filetype=avr
+;;
+;; Timer unit control and use
+;;
+
+.include "macros.inc"
+
+; Waveform Generation Mode (nibble low/high)
+.set TIMER_WGML = 0b00
+.set TIMER_WGMH = 0b01
+
+; Clock Source
+.set TIMER_CS = 0b101
+
+.equ TIMER_FLAGS = GPIOR0
+.equ TIMER_BUSY = 1
+
+Timer_Init:
+ ; OC1A/B disconnected from output
+ ; No PWM mode
+ poke [TCCR1A, r16, (0b00 << COM1A0) | (0b00 << COM1B0) | (TIMER_WGML << WGM10)]
+
+ ; Clear
+ poke [TCCR1B, r16, 0]
+ poke [TCCR1C, r16, 0]
+
+ ; Enable timer overflow interrupt
+ poke [TIMSK1, r16, (1 << OCIE1A)]
+
+ ret
+
+Timer_Start:
+ ; Initialize timer
+ poke [TCNT1H, r16, high(0)]
+ poke [TCNT1L, r16, low(0)]
+
+ ; Set flag
+ sbi TIMER_FLAGS, TIMER_BUSY
+
+ ; WGM
+ ; Clock Source
+ poke [TCCR1B, r16, (TIMER_WGMH << WGM12) | (TIMER_CS << CS10)]
+
+ ret
+
+Timer_Stop:
+ ; WGM
+ ; Clock off
+ poke [TCCR1B, r16, (TIMER_WGMH << WGM12) | (0b00 << CS10)]
+
+ ; Clear flag
+ cbi TIMER_FLAGS, TIMER_BUSY
+
+ ret
+
+;; Timer Compare 1A interrupt handler
+Timer_OC1A:
+ in r0, SREG
+
+ ; Stop timer
+ rcall Timer_Stop
+
+ out SREG, r0
+ reti
+
+;; Count to X
+Timer_Sleep:
+ ; Set TOP
+ sts OCR1AH, XH
+ sts OCR1AL, XL
+
+ ; Start timer
+ rcall Timer_Start
+
+ ; Wait for timer to complete
+_timer_sleep:
+ ;sleep
+
+ sbic TIMER_FLAGS, TIMER_BUSY
+ rjmp _timer_sleep
+
+ ; Done
+ ret
+
+;; Prime the timer and sleep for 1s
+Timer_Sleep_1s:
+ ; Initialize counter to 16k cycles
+ ldi XH, high(16 * 1024)
+ ldi XL, low(16 * 1024)
+
+ ; Start timer
+ rjmp Timer_Sleep
+