TIMER: improved module, added some callbacks.
This commit is contained in:
306
avr/timer.asm
306
avr/timer.asm
@@ -6,6 +6,14 @@
|
|||||||
.equ TIMER_FLAGS_100MS = 1
|
.equ TIMER_FLAGS_100MS = 1
|
||||||
.equ TIMER_FLAGS_1S = 2
|
.equ TIMER_FLAGS_1S = 2
|
||||||
|
|
||||||
|
.equ TIMER_CALLBACK_10S = 0x01
|
||||||
|
.equ TIMER_CALLBACK_30S = 0x02
|
||||||
|
.equ TIMER_CALLBACK_1M = 0x04
|
||||||
|
.equ TIMER_CALLBACK_15M = 0x08
|
||||||
|
.equ TIMER_CALLBACK_30M = 0x10
|
||||||
|
.equ TIMER_CALLBACK_1H = 0x20
|
||||||
|
.equ TIMER_CALLBACK_12H = 0x40
|
||||||
|
.equ TIMER_CALLBACK_1D = 0x80
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -17,9 +25,17 @@
|
|||||||
timerModuleData:
|
timerModuleData:
|
||||||
timerModuleTickCounter: .byte 1 ; only low byte used
|
timerModuleTickCounter: .byte 1 ; only low byte used
|
||||||
timerModuleFlags: .byte 1
|
timerModuleFlags: .byte 1
|
||||||
timerModuleCounter10s: .byte 1
|
|
||||||
timerModuleCounter1m: .byte 1
|
|
||||||
timerModuleCounterSecs: .byte 4
|
timerModuleCounterSecs: .byte 4
|
||||||
|
|
||||||
|
timerModuleDerivedCounters: ; order of the following vars matters!!
|
||||||
|
timerModuleCounterFor10s: .byte 1 ; change Timer_IncrementCounters when changing the
|
||||||
|
timerModuleCounterFor1m: .byte 1 ; order here!
|
||||||
|
timerModuleCounterFor15m: .byte 1
|
||||||
|
timerModuleCounterFor30m: .byte 1
|
||||||
|
timerModuleCounterFor1h: .byte 1
|
||||||
|
timerModuleCounterFor12h: .byte 1
|
||||||
|
timerModuleCounterFor1d: .byte 1
|
||||||
|
|
||||||
timerModuleData_end:
|
timerModuleData_end:
|
||||||
|
|
||||||
|
|
||||||
@@ -71,7 +87,7 @@ Timer_Init: ; setup timer for 15.2588 interrupts per second (e.g. eve
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
; ***************************************************************************
|
; ---------------------------------------------------------------------------
|
||||||
; Timer_Fini
|
; Timer_Fini
|
||||||
;
|
;
|
||||||
; IN:
|
; IN:
|
||||||
@@ -85,81 +101,211 @@ Timer_Fini:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
; ***************************************************************************
|
; ---------------------------------------------------------------------------
|
||||||
; Timer_Run
|
; Timer_Run
|
||||||
;
|
;
|
||||||
; IN:
|
; IN:
|
||||||
; - nothing
|
; - nothing
|
||||||
; OUT:
|
; OUT:
|
||||||
; - CFLAG: set if something done, reset otherwise
|
; - CFLAG: set if something done, cleared otherwise
|
||||||
; USED: r15, r16, r17 (more depending on called routines)
|
; USED: r15, r16, r17, R19 (more depending on called routines)
|
||||||
|
|
||||||
Timer_Run:
|
Timer_Run:
|
||||||
in r15, SREG
|
in r15, SREG
|
||||||
cli
|
cli
|
||||||
lds r17, timerModuleFlags
|
lds r17, timerModuleFlags ; get timer flags
|
||||||
clr r16
|
clr r16 ; replace with 0 for next IRQ
|
||||||
sts timerModuleFlags, r16
|
sts timerModuleFlags, r16
|
||||||
out SREG, r15 ; restore global IRQ flag
|
|
||||||
mov r16, r17
|
mov r16, r17
|
||||||
andi r16, TIMER_FLAGS_100MS
|
andi r16, TIMER_FLAGS_100MS ; timer irq occurred?
|
||||||
breq Timer_Run_l1
|
brne Timer_Run_100ms_passed ; yes, go handle
|
||||||
push r17
|
out SREG, r15 ; restore global IRQ flag
|
||||||
rcall onEvery100ms
|
clc ; nothing done
|
||||||
pop r17
|
ret
|
||||||
Timer_Run_l1:
|
Timer_Run_100ms_passed:
|
||||||
mov r16, r17
|
mov r16, r17
|
||||||
andi r16, TIMER_FLAGS_1S
|
andi r16, TIMER_FLAGS_1S
|
||||||
breq Timer_Run_l2
|
brne Timer_Run_1s_passed
|
||||||
; another 1s passed, invoke callback, check for 10s and 1m
|
out SREG, r15 ; restore global IRQ flag
|
||||||
push r17
|
rcall onEvery100ms ; only call this one
|
||||||
rcall onEverySecond
|
sec
|
||||||
pop r17
|
ret
|
||||||
; 1s
|
Timer_Run_1s_passed:
|
||||||
lds r16, timerModuleCounter10s
|
clr r19 ; flags for additional callbacks to be called
|
||||||
inc r16
|
rcall Timer_IncrementCounters ; 1s passed, handle depending counters, sample callback flags
|
||||||
sts timerModuleCounter10s, r16
|
out SREG, r15 ; restore global IRQ flag
|
||||||
cpi r16, 10
|
mov r16, r19
|
||||||
brcs Timer_Run_check1m
|
rcall Timer_CallOnEveryHandlers
|
||||||
clr r16
|
|
||||||
sts timerModuleCounter10s, r16
|
|
||||||
push r17
|
|
||||||
rcall onEvery10s
|
|
||||||
pop r17
|
|
||||||
|
|
||||||
Timer_Run_check1m:
|
|
||||||
; 1m
|
|
||||||
lds r16, timerModuleCounter1m
|
|
||||||
inc r16
|
|
||||||
sts timerModuleCounter1m, r16
|
|
||||||
cpi r16, 30 ; check for every 30s
|
|
||||||
brne Timer_Run_l4
|
|
||||||
push r16
|
|
||||||
push r17
|
|
||||||
rcall onEvery30s
|
|
||||||
pop r17
|
|
||||||
pop r16
|
|
||||||
Timer_Run_l4:
|
|
||||||
cpi r16, 60
|
|
||||||
brcs Timer_Run_l2
|
|
||||||
clr r16
|
|
||||||
sts timerModuleCounter1m, r16
|
|
||||||
push r17
|
|
||||||
rcall onEvery30s
|
|
||||||
rcall onEveryMinute
|
|
||||||
pop r17
|
|
||||||
|
|
||||||
Timer_Run_l2:
|
|
||||||
sec
|
sec
|
||||||
tst r17
|
|
||||||
brne Timer_Run_end
|
|
||||||
clc
|
|
||||||
Timer_Run_end:
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; ***************************************************************************
|
; ---------------------------------------------------------------------------
|
||||||
|
; Call "onEvery*" handlers according to given flags.
|
||||||
|
;
|
||||||
|
; IN:
|
||||||
|
; - R16: flags
|
||||||
|
; OUT:
|
||||||
|
; - nothing
|
||||||
|
; REGS: depending on called routines, expect clobbering of all registers
|
||||||
|
|
||||||
|
Timer_CallOnEveryHandlers:
|
||||||
|
push r16
|
||||||
|
rcall onEvery100ms ; always call this one
|
||||||
|
rcall onEverySecond ; and this
|
||||||
|
pop r16
|
||||||
|
tst r16 ; any flag set?
|
||||||
|
breq Timer_CallOnEveryHandlers_done ; nope, nothing more to call
|
||||||
|
mov r17, r16
|
||||||
|
andi r17, TIMER_CALLBACK_10S
|
||||||
|
breq Timer_CallOnEveryHandlers_l1
|
||||||
|
push r16
|
||||||
|
rcall onEvery10s
|
||||||
|
pop r16
|
||||||
|
Timer_CallOnEveryHandlers_l1:
|
||||||
|
mov r17, r16
|
||||||
|
andi r17, TIMER_CALLBACK_30S
|
||||||
|
breq Timer_CallOnEveryHandlers_l2
|
||||||
|
push r16
|
||||||
|
rcall onEvery30s
|
||||||
|
pop r16
|
||||||
|
Timer_CallOnEveryHandlers_l2:
|
||||||
|
mov r17, r16
|
||||||
|
andi r17, TIMER_CALLBACK_1M
|
||||||
|
breq Timer_CallOnEveryHandlers_l3
|
||||||
|
push r16
|
||||||
|
rcall onEveryMinute
|
||||||
|
pop r16
|
||||||
|
Timer_CallOnEveryHandlers_l3:
|
||||||
|
mov r17, r16
|
||||||
|
andi r17, TIMER_CALLBACK_15M
|
||||||
|
breq Timer_CallOnEveryHandlers_l4
|
||||||
|
push r16
|
||||||
|
rcall onEvery15m
|
||||||
|
pop r16
|
||||||
|
Timer_CallOnEveryHandlers_l4:
|
||||||
|
mov r17, r16
|
||||||
|
andi r17, TIMER_CALLBACK_30M
|
||||||
|
breq Timer_CallOnEveryHandlers_l5
|
||||||
|
push r16
|
||||||
|
rcall onEvery30m
|
||||||
|
pop r16
|
||||||
|
Timer_CallOnEveryHandlers_l5:
|
||||||
|
mov r17, r16
|
||||||
|
andi r17, TIMER_CALLBACK_1H
|
||||||
|
breq Timer_CallOnEveryHandlers_l6
|
||||||
|
push r16
|
||||||
|
rcall onEvery1h
|
||||||
|
pop r16
|
||||||
|
Timer_CallOnEveryHandlers_l6:
|
||||||
|
mov r17, r16
|
||||||
|
andi r17, TIMER_CALLBACK_12H
|
||||||
|
breq Timer_CallOnEveryHandlers_l7
|
||||||
|
push r16
|
||||||
|
rcall onEvery12h
|
||||||
|
pop r16
|
||||||
|
Timer_CallOnEveryHandlers_l7:
|
||||||
|
mov r17, r16
|
||||||
|
andi r17, TIMER_CALLBACK_1D
|
||||||
|
breq Timer_CallOnEveryHandlers_done
|
||||||
|
push r16
|
||||||
|
rcall onEvery1d
|
||||||
|
pop r16
|
||||||
|
Timer_CallOnEveryHandlers_done:
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; Increments the list of dependent counters and sets flag in R19 accordingly.
|
||||||
|
;
|
||||||
|
; IN:
|
||||||
|
; - R19: flags to add to
|
||||||
|
; OUT:
|
||||||
|
; - R19: flags for callback handlers to be called
|
||||||
|
; REGS: R16, R19, X
|
||||||
|
|
||||||
|
Timer_IncrementCounters:
|
||||||
|
ldi xl, LOW(timerModuleDerivedCounters) ; points to first counter: timerModuleCounterFor10s
|
||||||
|
ldi xh, HIGH(timerModuleDerivedCounters)
|
||||||
|
clr r19
|
||||||
|
|
||||||
|
ldi r17, 10 ; overflow after 10s
|
||||||
|
ldi r18, TIMER_CALLBACK_10S
|
||||||
|
rcall timerInc8CheckVar
|
||||||
|
brcc Timer_IncrementCounters_done
|
||||||
|
|
||||||
|
ldi r17, 3 ; overflow after 3*10s
|
||||||
|
ldi r18, TIMER_CALLBACK_30S
|
||||||
|
rcall timerInc8CheckVar
|
||||||
|
brcc Timer_IncrementCounters_done
|
||||||
|
|
||||||
|
ldi r17, 2 ; overflow after 2*30s
|
||||||
|
ldi r18, TIMER_CALLBACK_1M
|
||||||
|
rcall timerInc8CheckVar
|
||||||
|
brcc Timer_IncrementCounters_done
|
||||||
|
|
||||||
|
ldi r17, 30 ; overflow after 30*1m
|
||||||
|
ldi r18, TIMER_CALLBACK_30M
|
||||||
|
rcall timerInc8CheckVar
|
||||||
|
brcc Timer_IncrementCounters_done
|
||||||
|
|
||||||
|
ldi r17, 2 ; overflow after 2*30m
|
||||||
|
ldi r18, TIMER_CALLBACK_1H
|
||||||
|
rcall timerInc8CheckVar
|
||||||
|
brcc Timer_IncrementCounters_done
|
||||||
|
|
||||||
|
ldi r17, 12 ; overflow after 12*1h
|
||||||
|
ldi r18, TIMER_CALLBACK_12H
|
||||||
|
rcall timerInc8CheckVar
|
||||||
|
brcc Timer_IncrementCounters_done
|
||||||
|
|
||||||
|
ldi r17, 2 ; overflow after 2*12h
|
||||||
|
ldi r18, TIMER_CALLBACK_1D
|
||||||
|
rcall timerInc8CheckVar
|
||||||
|
brcc Timer_IncrementCounters_done
|
||||||
|
Timer_IncrementCounters_done:
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; Increment an 8 bit counter and check result.
|
||||||
|
;
|
||||||
|
; If the incremented counter is equal or greater than the given value the counter
|
||||||
|
; is reset, the given flag is ORed to the flags and carry flag is set on return.
|
||||||
|
; Otherwise the counter is just incremented and carry flag cleared.
|
||||||
|
;
|
||||||
|
; IN:
|
||||||
|
; - X: ptr to counter
|
||||||
|
; - R17: value to compare against
|
||||||
|
; - R18: flag to add on overflow
|
||||||
|
; - R19: flags to add to
|
||||||
|
; OUT:
|
||||||
|
; - CFLAG set if overflow occurred, cleared otherwise
|
||||||
|
; - X: points to next counter (advanced by one byte)
|
||||||
|
; REGS: R16, R19, X
|
||||||
|
|
||||||
|
timerInc8CheckVar:
|
||||||
|
ld r16, X
|
||||||
|
inc r16
|
||||||
|
cp r16, r17
|
||||||
|
brcs timerInc8CheckVar_stillSmaller
|
||||||
|
clr r16
|
||||||
|
st X+, r16
|
||||||
|
or r19, r18
|
||||||
|
sec
|
||||||
|
ret
|
||||||
|
timerInc8CheckVar_stillSmaller:
|
||||||
|
st X+, r16
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
; OC0A interrupt handler
|
; OC0A interrupt handler
|
||||||
;
|
;
|
||||||
; Called every 100 milliseconds, sets flag TIMER_FLAGS_100MS.
|
; Called every 100 milliseconds, sets flag TIMER_FLAGS_100MS.
|
||||||
@@ -188,30 +334,22 @@ timerIrq2_l1: ; increment seconds
|
|||||||
push xh
|
push xh
|
||||||
push xl
|
push xl
|
||||||
push r18
|
push r18
|
||||||
push r19
|
ldi xh, HIGH(timerModuleCounterSecs)
|
||||||
push r20
|
ldi xl, LOW(timerModuleCounterSecs)
|
||||||
push r21
|
ldi r18, 1
|
||||||
push r22
|
ld r16, X ; byte 0
|
||||||
ldi xh, HIGH(timerModuleCounterSecs)
|
adc r16, r18 ; inc by 1
|
||||||
ldi xl, LOW(timerModuleCounterSecs)
|
dec r18 ; doesn't affect carry flag! (r18 becomes 0 for following ADC)
|
||||||
ld r18, x+
|
st X+, r16
|
||||||
ld r19, x+
|
ld r16, X ; byte 1
|
||||||
ld r20, x+
|
adc r16, r18
|
||||||
ld r21, x
|
st X+, r16
|
||||||
ldi r22, 1
|
ld r16, X ; byte 2
|
||||||
add r18, r22
|
adc r16, r18
|
||||||
dec r22
|
st X+, r16
|
||||||
adc r19, r22
|
ld r16, X ; byte 3
|
||||||
adc r20, r22
|
adc r16, r18
|
||||||
adc r21, r22
|
st X+, r16
|
||||||
st x, r21
|
|
||||||
st -x, r20
|
|
||||||
st -x, r19
|
|
||||||
st -x, r18
|
|
||||||
pop r22
|
|
||||||
pop r21
|
|
||||||
pop r20
|
|
||||||
pop r19
|
|
||||||
pop r18
|
pop r18
|
||||||
pop xl
|
pop xl
|
||||||
pop xh
|
pop xh
|
||||||
|
|||||||
Reference in New Issue
Block a user