From 5175ca7dfdae3deb7309ebfedd7007264a40a852 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Sat, 8 Apr 2023 02:22:23 +0200 Subject: [PATCH] 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 --- avr/att84_base.asm | 10 +- avr/att84_temp1.asm | 25 +++-- avr/timer.asm | 260 +++++++++++++++++--------------------------- 3 files changed, 129 insertions(+), 166 deletions(-) diff --git a/avr/att84_base.asm b/avr/att84_base.asm index 0a02933..a7f3973 100644 --- a/avr/att84_base.asm +++ b/avr/att84_base.asm @@ -279,7 +279,15 @@ onEvery30s: ; --------------------------------------------------------------------------- ; Called every minute. Add your routine calls here. No arguments, no results. -onEveryMinute: +onEvery1m: + ret + + + +; --------------------------------------------------------------------------- +; Called every 5 minutes. Add your routine calls here. No arguments, no results. + +onEvery5m: ret diff --git a/avr/att84_temp1.asm b/avr/att84_temp1.asm index 0bcb955..3bbd18f 100644 --- a/avr/att84_temp1.asm +++ b/avr/att84_temp1.asm @@ -326,28 +326,39 @@ onEvery30s: ; --------------------------------------------------------------------------- ; Called every minute. Add your routine calls here. No arguments, no results. -onEveryMinute: +onEvery1m: #ifdef MODULES_COM lds r16, comAddress ; do we have an address assigned? tst r16 - breq onEveryMinute_l1 ; no, do nothing + breq onEvery1m_l1 ; no, do nothing -; will later send this only every hour or so + ; will later send this only every hour or so + ldi r16, 0xff ; send device info to everybody + rcall CPRO_EnqueueDevice +onEvery1m_l1: +#endif + ret + + +; --------------------------------------------------------------------------- +; Called every 5 minutes. Add your routine calls here. No arguments, no results. + +onEvery5m: + +#ifdef MODULES_COM + ; will later send these only every hour or so ldi r16, 0xff ; send stats to everybody rcall CPRO_EnqueueComSendStats ldi r16, 0xff ; send recv to everybody rcall CPRO_EnqueueComRecvStats - - ldi r16, 0xff ; send device info to everybody - rcall CPRO_EnqueueDevice -onEveryMinute_l1: #endif ret + ; --------------------------------------------------------------------------- ; Called every 15 minutes. Add your routine calls here. No arguments, no results. diff --git a/avr/timer.asm b/avr/timer.asm index 679fbe0..1b379f4 100644 --- a/avr/timer.asm +++ b/avr/timer.asm @@ -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 -