- sending and receiving now basically works again, but too often the read buffer is in use when trying to receive a message.
286 lines
6.1 KiB
NASM
286 lines
6.1 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
|
|
timerTicksSinceLastRun: .byte 2
|
|
timerModuleCounterSecs: .byte 4
|
|
timerInterrupts: .byte 2
|
|
timerModuleData_end:
|
|
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; code
|
|
|
|
.cseg
|
|
|
|
TIMER_BEGIN:
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Timer_Init
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - nothing
|
|
; USED: r16, r17, x
|
|
|
|
Timer_Init: ; setup timer for IRQ every 100ms
|
|
; reset data in SDRAM
|
|
ldi xh, HIGH(timerModuleData)
|
|
ldi xl, LOW(timerModuleData)
|
|
ldi r16, 0
|
|
ldi r17, (timerModuleData_end-timerModuleData)
|
|
rcall Utils_FillSram
|
|
|
|
; CTC mode (WGM2:0=2, OCR0A=value, OCF0A Flag =1, -> IRQ_OC0A
|
|
|
|
; CMP-A interrupt about every 100ms
|
|
ldi r16, (1<<CS02) | (1<<CS00) ; Prescaler 1024
|
|
out TCCR0B, r16
|
|
|
|
ldi r16, (1<<WGM01) ; CTC mode
|
|
out TCCR0A, r16
|
|
|
|
ldi r16, 98-1 ; (1,000,000/1024)/10 = 97.65625
|
|
out OCR0A, r16
|
|
|
|
ldi r16, (1<<OCF0A) ; clear pending interrupts
|
|
out TIFR0, r16
|
|
|
|
ldi r16, (1<<OCIE0A)
|
|
out TIMSK0, r16
|
|
|
|
rcall timerInitTimers
|
|
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Timer_Fini
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - nothing
|
|
; USED:
|
|
|
|
Timer_Fini:
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Timer_Run
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CFLAG: set if something done, cleared otherwise
|
|
; USED: r15, r16, r24, r25 (more depending on called routines)
|
|
|
|
Timer_Run:
|
|
in r15, SREG
|
|
cli
|
|
lds r24, timerTicksSinceLastRun
|
|
lds r25, timerTicksSinceLastRun+1
|
|
clr r16 ; replace with 0 for next IRQ
|
|
sts timerTicksSinceLastRun, r16
|
|
sts timerTicksSinceLastRun+1, r16
|
|
out SREG, r15 ; restore global IRQ flag
|
|
sbiw r25:r24, 0
|
|
clc ; flag "nothing done"
|
|
breq Timer_Run_End
|
|
Timer_Run_loop: ; for every occurred 100ms irq
|
|
push r24
|
|
push r25
|
|
rcall onEvery100ms
|
|
pop r25
|
|
pop r24
|
|
lds r16, timerModuleTickCounter
|
|
inc r16
|
|
cpi r16, 10
|
|
brcc Timer_Run_SecondElapsed
|
|
sts timerModuleTickCounter, r16
|
|
rjmp Timer_Run_loop_end
|
|
Timer_Run_SecondElapsed:
|
|
clr r16
|
|
sts timerModuleTickCounter, r16
|
|
push r24
|
|
push r25
|
|
rcall timerRunTimers
|
|
pop r25
|
|
pop r24
|
|
Timer_Run_loop_end:
|
|
sbiw r25:r24, 1
|
|
brne Timer_Run_loop
|
|
sec
|
|
Timer_Run_End:
|
|
ret
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
timerRunTimers:
|
|
ldi xl, LOW(timerModuleCounterSecs)
|
|
ldi xh, HIGH(timerModuleCounterSecs)
|
|
rcall Utils_IncrementCounter32
|
|
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
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; read time table entry.
|
|
;
|
|
; IN:
|
|
; - Z : pointer to time list entry (suitable for LPM)
|
|
; OUT:
|
|
; - r19:r18: handler routine
|
|
; - X : SRAM address for counter
|
|
; - r21:r20: initial value
|
|
; - r22 : flags
|
|
; - 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
|
|
|
|
|
|
|
|
timerCallR19R18:
|
|
push r18
|
|
push r19
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; OC0A interrupt handler
|
|
;
|
|
; Called every 100 milliseconds, increments timerTicksSinceLastRun. The rest is done outside ISR
|
|
; in Timer_Run.
|
|
|
|
timerIrqOC0A:
|
|
push r15
|
|
in r15, SREG
|
|
|
|
push r24
|
|
push r25
|
|
lds r24, timerTicksSinceLastRun
|
|
lds r25, timerTicksSinceLastRun+1
|
|
adiw r25:r24, 1
|
|
sts timerTicksSinceLastRun, r24
|
|
sts timerTicksSinceLastRun+1, r25
|
|
|
|
lds r24, timerInterrupts
|
|
lds r25, timerInterrupts+1
|
|
adiw r25:r24, 1
|
|
sts timerInterrupts, r24
|
|
sts timerInterrupts+1, r25
|
|
|
|
pop r25
|
|
pop r24
|
|
out SREG, r15
|
|
pop r15
|
|
reti
|
|
|
|
|
|
|
|
TIMER_END:
|
|
.equ MODULE_SIZE_TIMER = TIMER_END-TIMER_BEGIN
|
|
|
|
|
|
|