--- 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
+