timer.inc
author Tero Marttila <terom@fixme.fi>
Sat, 08 May 2010 20:07:18 +0300
changeset 21 95549ce0e3da
parent 18 79b25e81721f
child 29 453550e69e07
permissions -rw-r--r--
timer: try and actually sleep
;; vim: filetype=avr
;;
;; Timer unit control and use
;;

; 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

.set SLEEP_MODE = 0b000			; Idle

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)]

Sleep_init:
		; Select sleep mode
		; Enable `sleep`
		poke		[SMCR, r16, (SLEEP_MODE << SM0) | (1 << SE)]

		; Disable ADC
		poke		[SMCR, r16, (1 << PRTWI) | (1 << PRUSART0) | (1 << PRADC)]

		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