Files
aqhomecontrol/avr/modules/timer/main.asm
2024-09-18 20:24:48 +02:00

278 lines
5.7 KiB
NASM

; ***************************************************************************
; copyright : (C) 2023 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
; ***************************************************************************
; defs
.equ TIMER_FLAGS_IF_ADDR = 1
; ***************************************************************************
; data
.dseg
timerModuleData:
timerModuleTickCounter: .byte 1
timerModuleCounterSecs: .byte 4
timerModuleData_end:
; ***************************************************************************
; code
.cseg
TIMER_BEGIN:
; ---------------------------------------------------------------------------
; @routine Timer_Init
;
; @clobbers r16, r17, x
Timer_Init:
; reset data in SDRAM
ldi xh, HIGH(timerModuleData)
ldi xl, LOW(timerModuleData)
ldi r16, 0
ldi r17, (timerModuleData_end-timerModuleData)
rcall Utils_FillSram
ldi r16, 10 ; every sec
sts timerModuleTickCounter, r16
rcall timerInitTimers
ret
; @end
; ---------------------------------------------------------------------------
; @routine Timer_Fini
;
Timer_Fini:
ret
; @end
; ---------------------------------------------------------------------------
; @routine onSystemTimerTick
;
; @return CFLAG set if something done, cleared otherwise
; @clobbers all
onSystemTimerTick:
lds r16, timerModuleTickCounter
dec r16
breq onSystemTimerTick_SecondElapsed
sts timerModuleTickCounter, r16
rjmp onSystemTimerTick_call
onSystemTimerTick_SecondElapsed:
ldi r16, 10 ; reload counter (10=every sec)
sts timerModuleTickCounter, r16
ldi xl, LOW(timerModuleCounterSecs)
ldi xh, HIGH(timerModuleCounterSecs)
rcall Utils_IncrementCounter32 ; inc uptime counter
; sbi DEBUG_LED_DDR, DEBUG_LED_PINNUM ; out
; sbi DEBUG_LED_PORT_IN, DEBUG_LED_PINNUM ; toggle
onSystemTimerTick_call:
rcall timerRunTimers
rcall onEvery100ms
ret
; @end
; ---------------------------------------------------------------------------
; @routine Timer_SetValue @global
;
; Set timer value.
; Setting a timer to 0 effectively stops the timer.
;
; @param r16 new timer value (low)
; @param r17 new timer value (high)
; @param X pointer to timer value in SRAM
; @clobbers X
Timer_SetValue:
push r15
in r15, SREG
cli
st X+, r16
st X+, r17
out SREG, r15
pop r15
ret
; @end
; ---------------------------------------------------------------------------
; @routine Timer_SetValueTo1s @global
;
; Set timer value to 1s.
;
; @param X pointer to timer value in SRAM
; @clobbers X
Timer_SetValueTo1s:
push r16
push r17
ldi r16, 10
clr r17
rcall Timer_SetValue
pop r17
pop r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine timerInitTimers
;
; Init timers in table.
;
; @clobbers all
timerInitTimers:
ldi zl, LOW(timerList*2)
ldi zh, HIGH(timerList*2)
clr r16 ; run var for pos in time table
clr r17 ; 0 for adc
timerInitTimers_loop:
rcall timerReadTableEntry
mov r18, xl
or r18, xh
breq timerInitTimers_end
mov r18, r20
or r18, r21
breq timerInitTimers_writeInitial
add r20, r16 ; add counter pos in table so that not all timers elapse at the same time
adc r21, r17
timerInitTimers_writeInitial:
st X+, r20
st X, r21
inc r16
inc r16
rjmp timerInitTimers_loop
timerInitTimers_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine timerRunTimers
;
; Run timers in table.
;
; @clobbers all
timerRunTimers:
ldi zl, LOW(timerList*2)
ldi zh, HIGH(timerList*2)
timerRunTimers_loop:
rcall timerReadTableEntry
mov r16, xl
or r16, xh
breq timerRunTimers_end
mov r16, r22
andi r16, TIMER_FLAGS_IF_ADDR
breq timerRunTimers_l1 ; no need to check address
lds r16, com2Address ; check address
tst r16
breq timerRunTimers_loop ; no address, ignore counter
timerRunTimers_l1:
ld r24, X+
ld r25, X
sbiw r25:r24, 1
brcs timerRunTimers_loop ; overflow, so already was zero, ignore entry
breq timerRunTimers_reachedZero ; reached zero
st X, r25
st -X, r24
rjmp timerRunTimers_loop
timerRunTimers_reachedZero:
st X, r21 ; reset initial value
st -X, r20
push zl
push zh
rcall timerCallR19R18
pop zh
pop zl
rjmp timerRunTimers_loop
timerRunTimers_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine timerReadTableEntry
;
; read timer table entry.
;
; @param Z pointer to time list entry (suitable for LPM)
; OUT:
; @return r19:r18 handler routine
; @return X SRAM address for counter
; @return r21:r20 initial value
; @return r22 flags
; @return r23 reserved
timerReadTableEntry:
lpm xl, Z+ ; SRAM address of counter
lpm xh, Z+
lpm r18, Z+ ; routine (low)
lpm r19, Z+ ; routine (high)
lpm r22, Z+ ; flags
lpm r23, Z+ ; reserved
lpm r20, Z+ ; initial value
lpm r21, Z+
ret
; @end
; ---------------------------------------------------------------------------
; @routine timerCallR19R18
; Call route at address r19:r18
timerCallR19R18:
push r18
push r19
ret
; @end
TIMER_END:
.equ MODULE_SIZE_TIMER = TIMER_END-TIMER_BEGIN