avr: improved timer module.

- simplified timer handling. still using cascading counters but in an
  extendable way
- added onEvery5m while on it
- renamed everyMinute to every1m (unifies routine names)
- send network stats every 5m, not every minute
This commit is contained in:
Martin Preuss
2023-04-08 02:22:23 +02:00
parent 7eb462173c
commit 5175ca7dfd
3 changed files with 129 additions and 166 deletions

View File

@@ -23,18 +23,11 @@
.dseg
timerModuleData:
timerModuleTickCounter: .byte 1 ; only low byte used
timerModuleTickCounter: .byte 1
timerModuleFlags: .byte 1
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
timerModuleDerivedCounters: .byte 9 ; must correspond to entries in timer table!
timerModuleData_end:
@@ -47,8 +40,22 @@ timerModuleData_end:
.cseg
; number of entries here must be equal to bytes in timerModuleDerivedCounters!
timerTable:
.db 10, 0, LOW(onEvery10s), HIGH(onEvery10s) ; 10s: overflow after 10*1s (1)
.db 3, 0, LOW(onEvery30s), HIGH(onEvery30s) ; 30s: overflow after 3*10s (2)
.db 2, 0, LOW(onEvery1m), HIGH(onEvery1m) ; 1m : overflow after 2*30s (3)
.db 5, 0, LOW(onEvery5m), HIGH(onEvery5m) ; 5m : overflow after 5*1m (4)
.db 3, 0, LOW(onEvery15m), HIGH(onEvery15m) ; 15m: overflow after 3*5m (5)
.db 2, 0, LOW(onEvery30m), HIGH(onEvery30m) ; 30m: overflow after 2*15m (6)
.db 2, 0, LOW(onEvery1h), HIGH(onEvery1h) ; 1h: overflow after 2*30m (7)
.db 12, 0, LOW(onEvery12h), HIGH(onEvery12h) ; 12h: overflow after 12*1h (8)
.db 2, 0, LOW(onEvery1d), HIGH(onEvery1d) ; 1d: overflow after 2*12h (9)
.db 0, 0
; ***************************************************************************
; ---------------------------------------------------------------------------
; Timer_Init
;
; IN:
@@ -131,177 +138,114 @@ Timer_Run_100ms_passed:
sec
ret
Timer_Run_1s_passed:
clr r19 ; flags for additional callbacks to be called
rcall Timer_IncrementCounters ; 1s passed, handle depending counters, sample callback flags
rcall timerIncrementCounters ; 1s passed, handle cascading counters, get number of callable handlers
out SREG, r15 ; restore global IRQ flag
mov r16, r19
rcall Timer_CallOnEveryHandlers
rcall timerCallFirstOnEveryHandlers
sec
ret
; ---------------------------------------------------------------------------
; Call "onEvery*" handlers according to given flags.
;
; Increment cascading timer counters.
;
; This routine starts with the first cascaded counter and increments it.
; If that counter value does not overflow (according to timer table entry) then
; handling the timer table is stopped.
; Otherwise the return value is incremented and the next counter entry is inspected
; until the full table is handled.
;
; The result value has to be interpreted as the number of entries started at the first
; which have overflowed.
;
; Example: A return value of 1 means that the first entry overflowed, meaning that 10s have
; elapsed.
; A return value of 2 means that the first entry overflowed (i.e. 10s elapsed) and also the nex
; entry overflowed (i.e. also 30s elapsed).
;
; IN:
; - R16: flags
; - nothing
; OUT:
; - R16: number of timer table entries which caused an overflow
; REGS: R16, R17, R18, X, Z
timerIncrementCounters:
ldi xl, LOW(timerModuleDerivedCounters) ; points to first counter: timerModuleCounterFor10s
ldi xh, HIGH(timerModuleDerivedCounters)
ldi zl, LOW(timerTable*2)
ldi zh, HIGH(timerTable*2)
clr r18
timerIncrementCounters_loop:
lpm r17, Z ; overflow value
tst r17
breq timerIncrementCounters_done ; end of list
ld r16, X ; get current counter value
inc r16
cp r16, r17 ; compare against overflow value
brcs timerIncrementCounters_counterSmaller
clr r16 ; overflow occurred
st X+, r16
; next
inc r18
adiw zh:zl, 4
rjmp timerIncrementCounters_loop
timerIncrementCounters_counterSmaller:
st X, r16
timerIncrementCounters_done:
mov r16, r18
ret
; ---------------------------------------------------------------------------
; Call first N handlers from the timer table.
;
; IN:
; - R16: number of handlers to call (returned by timerIncrementCounters)
; OUT:
; - nothing
; REGS: depending on called routines, expect clobbering of all registers
; REGS: depening on handler called (expect all registers to be clobbered)
Timer_CallOnEveryHandlers:
timerCallFirstOnEveryHandlers:
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
tst r16
breq timerCallFirstOnEveryHandlers_done
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 zl, LOW(timerTable*2)
ldi zh, HIGH(timerTable*2)
ldi r17, 2 ; overflow after 2*30s
ldi r18, TIMER_CALLBACK_1M
rcall timerInc8CheckVar
brcc Timer_IncrementCounters_done
timerCallFirstOnEveryHandlers_loop:
lpm r17, Z ; overflow value
tst r17 ; 0?
breq timerCallFirstOnEveryHandlers_done ; yes: end of list
adiw zh:zl, 2 ; skip to handler address
lpm r20, Z+ ; read handler address
lpm r21, Z+
push r16 ; call handler
push zl
push zh
rcall timerCallR21R20
pop zh
pop zl
pop r16
dec r16
brne timerCallFirstOnEveryHandlers_loop
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:
timerCallFirstOnEveryHandlers_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
timerCallR21R20:
push r20
push r21
ret
timerInc8CheckVar_stillSmaller:
st X+, r16
clc
ret