Test use of Timer0
authorTero Marttila <terom@fixme.fi>
Sun, 09 May 2010 23:17:14 +0300
changeset 29 453550e69e07
parent 28 51344df466ca
child 30 5226e512755c
Test use of Timer0
Makefile
timer.inc
timer.s
--- a/Makefile	Sat May 08 21:27:44 2010 +0300
+++ b/Makefile	Sun May 09 23:17:14 2010 +0300
@@ -9,12 +9,13 @@
 AD = avrdude
 ADFLAGS = -p $(AD_PART) -c $(AD_PROG) -b $(AD_BAUD) -P $(AD_PORT)
 
-PROG = led7seg
-
-led7seg.hex: spi.inc led7seg.inc adc.inc timer.inc delay.inc
+PROG = timer
 
 all: $(PROG).hex
 
+led7seg.hex: spi.inc led7seg.inc adc.inc timer.inc delay.inc macros.inc
+timer.hex: timer.inc macros.inc
+
 %.hex: %.s
 	$(AS) $(ASFLAGS) $<
 	mv $<.hex $@
--- a/timer.inc	Sat May 08 21:27:44 2010 +0300
+++ b/timer.inc	Sun May 09 23:17:14 2010 +0300
@@ -3,28 +3,60 @@
 ;; Timer unit control and use
 ;;
 
-; Waveform Generation Mode (nibble low/high)
-.set TIMER_WGML = 0b00
-.set TIMER_WGMH = 0b01
+.equ TIMER_FLAGS = GPIOR0
+
+;; Timer0
+; Compare output mode
+.set TIMER0_COMA = 0b00			; null
+.set TIMER0_COMB = 0b00			; null
+
+; Waveform Generation Mode (triplet low/high)
+.set TIMER0_WGML = 0b10			; CTC
+.set TIMER0_WGMH = 0b0			; CTC
 
 ; Clock Source
-.set TIMER_CS = 0b101
+.set TIMER0_CS = 0b101			; 1/1024
 
-.equ TIMER_FLAGS = GPIOR0
-.equ TIMER_BUSY = 1
+;; Timer1
+; Waveform Generation Mode (nibble low/high)
+.set TIMER1_WGML = 0b00			; CTC
+.set TIMER1_WGMH = 0b01			; CTC
+
+; Clock Source
+.set TIMER1_CS = 0b101			; 1/1024
+
+; Flags
+.equ TIMER1_BUSY = 1
 
 .set SLEEP_MODE = 0b000			; Idle
 
 Timer_Init:
+Timer0_Init:
+		; OC0A/B disconnected from output
+		; No PWM mode
+		ldi			r16, (TIMER0_COMA << COM0A0) | (TIMER0_COMB << COM0B0) | (TIMER0_WGML << WGM00)
+		out			TCCR0A, r16
+
+		; Clear
+		ldi			r16, 0
+		out			OCR0A, r16
+		out			OCR0B, r16
+		out			TCCR0B, r16
+
+		; Enable compare interrupt
+		ldi			r16, (1 << OCIE0A)
+		sts			TIMSK0, r16
+
+Timer1_Init:
 		; OC1A/B disconnected from output
 		; No PWM mode
-		poke		[TCCR1A, r16, (0b00 << COM1A0) | (0b00 << COM1B0) | (TIMER_WGML << WGM10)]
+		poke		[TCCR1A, r16, (0b00 << COM1A0) | (0b00 << COM1B0) | (TIMER1_WGML << WGM10)]
 
 		; Clear
 		poke		[TCCR1B, r16, 0]
 		poke		[TCCR1C, r16, 0]
 
-		; Enable timer overflow interrupt
+		; Enable compare interrupt
 		poke		[TIMSK1, r16, (1 << OCIE1A)]
 
 Sleep_init:
@@ -37,36 +69,72 @@
 
 		ret
 
-Timer_Start:
+;; Timer0 is recurring; this starts it running, and it keeps hitting OC0A periodically
+;;  Input: r16 (period, in 1k-cycles)
+Timer0_Start:
+	; Initialize timer
+		; set CTC trigger from r16
+		out			OCR0A, r16
+
+		; clear counter
+		ldi			r16, 0
+		out			TCNT0, r16
+
+	; Start
+		; WGM
+		; Clock Source
+		ldi			r16, (TIMER0_WGMH << WGM02) | (TIMER0_CS << CS00)
+		out			TCCR0B, r16
+
+		ret
+
+Timer0_Read8:
+		in			r16, TCNT0
+
+		ret
+
+;; Timer0 Compare A interrupt handler
+Timer_OC0A:
+		in			r0, SREG
+
+		; Run callback
+		rcall		TIMER0_CB_A
+
+		out			SREG, r0
+		reti
+
+;; Timer1 is one-shot; this starts it running, and it is then stopped once it hits OC1A
+Timer1_Start:
 	; Initialize timer
 		poke		[TCNT1H, r16, high(0)]
 		poke		[TCNT1L, r16, low(0)]
 
 	; Set flag
-		sbi			TIMER_FLAGS, TIMER_BUSY
-
+		sbi			TIMER_FLAGS, TIMER1_BUSY
+	
+	; Start
 		; WGM
 		; Clock Source
-		poke		[TCCR1B, r16, (TIMER_WGMH << WGM12) | (TIMER_CS << CS10)]
+		poke		[TCCR1B, r16, (TIMER1_WGMH << WGM12) | (TIMER1_CS << CS10)]
 
 		ret
 
-Timer_Stop:
+Timer1_Stop:
 		; WGM
 		; Clock off
-		poke		[TCCR1B, r16, (TIMER_WGMH << WGM12) | (0b00 << CS10)]
+		poke		[TCCR1B, r16, (TIMER1_WGMH << WGM12) | (0b00 << CS10)]
 		
 	; Clear flag
-		cbi			TIMER_FLAGS, TIMER_BUSY
+		cbi			TIMER_FLAGS, TIMER1_BUSY
 
 		ret
 
-;; Timer Compare 1A interrupt handler
+;; Timer1 Compare A interrupt handler
 Timer_OC1A:
 		in			r0, SREG
 	
 	; Stop timer
-		rcall		Timer_Stop
+		rcall		Timer1_Stop
 
 		out			SREG, r0
 		reti
@@ -78,14 +146,14 @@
 		sts			OCR1AL, XL
 
 	; Start timer
-		rcall		Timer_Start
+		rcall		Timer1_Start
 
 	; Wait for timer to complete
-_timer_sleep:
+_timer1_sleep:
 		sleep
 		
-		sbic		TIMER_FLAGS, TIMER_BUSY
-		rjmp		_timer_sleep
+		sbic		TIMER_FLAGS, TIMER1_BUSY
+		rjmp		_timer1_sleep
 
 	; Done
 		ret
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/timer.s	Sun May 09 23:17:14 2010 +0300
@@ -0,0 +1,68 @@
+.nolist
+.include "m168def.inc"      ; Same family as 328P
+.list
+
+;; Interrupt Vector
+.org 0x00
+        rjmp        init
+
+.org OC1Aaddr
+		; Timer/Counter1 Compare Output A
+		rjmp		Timer_OC1A
+
+.org OC0Aaddr
+        ; Timer/Counter0 Compare Output A
+        rjmp        Timer_OC0A
+
+.org 0x40
+
+;; Syntax
+.include "macros.inc"
+
+;; Timer0 Compare A handler
+Tick:
+	; Toggle
+		sbi			PIND, PORTD7
+
+		ret
+
+;; Timer
+.set TIMER0_CB_A = Tick
+.include "timer.inc"
+
+Main:
+init:
+    ; Stack
+        ldi         r16, high(RAMEND)
+        ldi         r17, low(RAMEND)
+        out         SPH, r16
+        out         SPL, r17
+
+    ; Enable interrupts
+        sei
+
+	; Turn off LED7
+		sbi			DDRB, PORTB1
+		sbi			PORTB, PORTB1
+
+
+	; DEBUG
+		sbi			DDRD, PORTD7
+		cbi			PORTD, PORTD7
+
+		sbi			DDRD, PORTD6
+		sbi			DDRD, PORTD5
+		
+
+    ; Timer
+		; setup
+        rcall       Timer0_Init
+		
+		; run with 255k cycles
+		ldi			r16, 255
+		rcall		Timer0_Start	
+
+loop:
+	; Run timer
+		rjmp		loop
+