Files
aqhomecontrol/avr/timer.asm
Martin Preuss 16be96ada9 Initial import.
2023-01-16 23:12:09 +01:00

195 lines
3.9 KiB
NASM

; ***************************************************************************
; defs
.equ TIMER_FLAGS_100MS = 1
.equ TIMER_FLAGS_1S = 2
; ***************************************************************************
; data
.dseg
timerModuleData:
timerModuleTickCounter: .byte 1 ; only low byte used
timerModuleFlags: .byte 1
timerModuleCounterSecs: .byte 4
timerModuleData_end:
; ***************************************************************************
; code
.cseg
; ***************************************************************************
; Timer_Init
;
; IN:
; - nothing
; OUT:
; - nothing
; USED: r16, r17, x
Timer_Init: ; setup timer for 15.2588 interrupts per second (e.g. every 65.5 ms)
; reset data in SDRAM
ldi xh, HIGH(timerModuleData)
ldi xl, LOW(timerModuleData)
ldi r16, 0
ldi r17, (timerModuleData_end-timerModuleData)
rcall Utils_FillSram
; CTC mode (WGM2:0=2, OCR0A=value, OCF0A Flag =1, -> IRQ_OC0A
; CMP-A interrupt about every 100ms
ldi r16, (1<<CS02) | (1<<CS00) ; Prescaler 1024
out TCCR0B, r16
ldi r16, (1<<WGM01) ; CTC mode
out TCCR0A, r16
ldi r16, 98-1 ; (1,000,000/1024)/10 = 97.65625
out OCR0A, r16
ldi r16, (1<<OCF0A) ; clear pending interrupts
out TIFR0, r16
ldi r16, (1<<OCIE0A)
out TIMSK0, r16
ret
; ***************************************************************************
; Timer_Fini
;
; IN:
; - nothing
; OUT:
; - nothing
; USED:
Timer_Fini:
ret
; ***************************************************************************
; Timer_Run
;
; IN:
; - nothing
; OUT:
; - CFLAG: set if something done, reset otherwise
; USED: r15, r16, r17 (more depending on called routines)
Timer_Run:
in r15, SREG
cli
clr r16
lds r17, timerModuleFlags
sts timerModuleFlags, r16
out SREG, r15 ; restore global IRQ flag
mov r16, r17
andi r16, TIMER_FLAGS_100MS
breq Timer_Run_l1
push r17
rcall onEvery100ms
pop r17
Timer_Run_l1:
mov r16, r17
andi r16, TIMER_FLAGS_1S
breq Timer_Run_l2
push r17
rcall onEverySecond
pop r17
Timer_Run_l2:
sec
tst r17
brne Timer_Run_end
clc
Timer_Run_end:
ret
; ***************************************************************************
; OC0A interrupt handler
;
; Called every 100 milliseconds, sets flag TIMER_FLAGS_100MS.
; Increments an internal counter. If that counter reaches 10 the seconds counter is incremented and a the flag
; TIMER_FLAGS_1S is set.
timerIrqOC0A:
push r15
in r15, SREG
push r16
push r17
lds r17, timerModuleFlags
ori r17, TIMER_FLAGS_100MS
lds r16, timerModuleTickCounter
inc r16
cpi r16, 10
brcc timerIrq2_l1
sts timerModuleTickCounter, r16
rjmp timerIrq2_l2
timerIrq2_l1: ; increment seconds
; reset 100ms counter
clr r16
sts timerModuleTickCounter, r16
; increment seconds
push xh
push xl
push r18
push r19
push r20
push r21
push r22
ldi xh, HIGH(timerModuleCounterSecs)
ldi xl, LOW(timerModuleCounterSecs)
ld r18, x+
ld r19, x+
ld r20, x+
ld r21, x
clr r22
inc r18
adc r19, r22
adc r20, r22
adc r21, r22
st x, r21
st -x, r20
st -x, r19
st -x, r18
pop r22
pop r21
pop r20
pop r19
pop r18
pop xl
pop xh
ori r17, TIMER_FLAGS_1S
timerIrq2_l2:
sts timerModuleFlags, r17 ; store new timer flags
pop r17
pop r16
out SREG, r15
pop r15
reti