timer.inc
changeset 18 79b25e81721f
child 21 95549ce0e3da
--- /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
+