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