TIMER: improved module, added some callbacks.

This commit is contained in:
Martin Preuss
2023-02-20 23:47:56 +01:00
parent 8119cba750
commit 1726796b68

View File

@@ -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
push r20
push r21
push r22
ldi xh, HIGH(timerModuleCounterSecs) ldi xh, HIGH(timerModuleCounterSecs)
ldi xl, LOW(timerModuleCounterSecs) ldi xl, LOW(timerModuleCounterSecs)
ld r18, x+ ldi r18, 1
ld r19, x+ ld r16, X ; byte 0
ld r20, x+ adc r16, r18 ; inc by 1
ld r21, x dec r18 ; doesn't affect carry flag! (r18 becomes 0 for following ADC)
ldi r22, 1 st X+, r16
add r18, r22 ld r16, X ; byte 1
dec r22 adc r16, r18
adc r19, r22 st X+, r16
adc r20, r22 ld r16, X ; byte 2
adc r21, r22 adc r16, r18
st x, r21 st X+, r16
st -x, r20 ld r16, X ; byte 3
st -x, r19 adc r16, r18
st -x, r18 st X+, r16
pop r22
pop r21
pop r20
pop r19
pop r18 pop r18
pop xl pop xl
pop xh pop xh