Files
aqhomecontrol/avr/led.asm
2023-01-17 20:56:04 +01:00

308 lines
6.2 KiB
NASM

; ***************************************************************************
; defs
.equ LED_DATA_OFFS_ADDRDDR = 0
.equ LED_DATA_OFFS_ADDRPORT = 1
.equ LED_DATA_OFFS_ADDRPIN = 2
.equ LED_DATA_OFFS_PINMASK = 3
.equ LED_SRAM_OFFS_PATTERNADDR = 0
.equ LED_SRAM_OFFS_COUNTER = 2
.equ LED_SRAM_OFFS_POS = 3
.equ LED_SRAM_SIZE = 4
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; Led_Init
;
; IN:
; - Y: pointer to SRAM data
; - Z: pointer to FLASH data
; OUT:
; - CFLAG: set if okay, clear on error
; USED: R1, R2, R3, R4, R16, R17, X
Led_Init:
mov xh, yh
mov xl, yl
clr r16
ldi r17, LED_SRAM_SIZE
rcall Utils_FillSram
rcall ledGetFlashDataIntoRegs
brcc Led_Init_end
; set bit in DDR register (-> output)
mov xl, r1 ; DDR register address
clr xh
ld r16, x
or r16, r4 ; output
st x, r16
; turn off led
rcall ledOff
sec
Led_Init_end:
ret
; ---------------------------------------------------------------------------
; Led_SetPattern
;
; IN:
; - X: pointer to led pattern in flash
; - Y: pointer to SRAM data
; - Z: pointer to FLASH data
; OUT:
; - CFLAG: set if okay, clear on error
; USED: R1, R2, R3, R4, R16, R17, Z
Led_SetPattern:
rcall ledGetFlashDataIntoRegs
brcc Led_SetPattern_l2
std y+LED_SRAM_OFFS_PATTERNADDR, xl ; param 1
std y+LED_SRAM_OFFS_PATTERNADDR+1, xh ; param 2
; reset pos in pattern
clr r19
std y+LED_SRAM_OFFS_POS, r19
; store counter for current pattern element
mov zl, xl
mov zh, xh
lsl zl ; multiplay Z by 2
rol zh
lpm r19, z ; read current pattern counter
std y+LED_SRAM_OFFS_COUNTER, r19
; each pattern starts with LED on
rcall ledOn
Led_SetPattern_l2:
ret
; ---------------------------------------------------------------------------
; Led_Tick
;
; IN:
; - Y: pointer to SRAM data
; - Z: pointer to FLASH data
; OUT:
; - CFLAG: set if something done, reset otherwise
; USED:
Led_Tick:
rcall ledGetFlashDataIntoRegs
brcs Led_Tick_l1
ret
Led_Tick_l1:
ldd zl, y+LED_SRAM_OFFS_PATTERNADDR
ldd zh, y+LED_SRAM_OFFS_PATTERNADDR+1
ldd r18, y+LED_SRAM_OFFS_POS
ldd r19, y+LED_SRAM_OFFS_COUNTER
; test NULL ptr
mov r16, zl;
or r16, zh
breq Led_Tick_end ; no current pattern, end
cpi r19, 2 ; current counter less than 2?
brcs Led_Tick_nextPhase
dec r19
std y+LED_SRAM_OFFS_COUNTER, r19
ret
Led_Tick_nextPhase:
lsl zl ; multiplay Z by 2
rol zh
inc r18 ; next pos
rcall Led_Tick_getPattern
cpi r16, 0xff
breq Led_Tick_restart
cpi r16, 0
breq Led_Tick_stop
std y+LED_SRAM_OFFS_POS, r18
std y+LED_SRAM_OFFS_COUNTER, r16
mov r17, r18
andi r17, 1 ; even?
breq Led_Tick_switchOn
rjmp ledOff
Led_Tick_switchOn:
; turn on led
rjmp ledOn
Led_Tick_stop:
clr r16
std y+LED_SRAM_OFFS_PATTERNADDR, r16
std y+LED_SRAM_OFFS_PATTERNADDR+1, r16
std y+LED_SRAM_OFFS_COUNTER, r16
std y+LED_SRAM_OFFS_POS, r16
; LED off
rcall ledOff
Led_Tick_restart:
ldi r18, 0
rcall Led_Tick_getPattern
cpi r16, 0xff
breq Led_Tick_stop ; stop, because restart as first pattern is invalid
cpi r16, 0
breq Led_Tick_stop
std y+LED_SRAM_OFFS_POS, r18 ; incremented pos in pattern
std y+LED_SRAM_OFFS_COUNTER, r16 ; new counter value
rcall ledOn
ret
Led_Tick_getPattern: ; r18=pos
ldd zl, y+LED_SRAM_OFFS_PATTERNADDR
ldd zh, y+LED_SRAM_OFFS_PATTERNADDR+1
lsl zl ; multiplay Z by 2
rol zh
ldi r16, 0
add zl, r18
adc zh, r16
lpm r16, z
ret
Led_Tick_end:
ret
; ---------------------------------------------------------------------------
; ledGetFlashDataIntoRegs
;
; IN:
; - R28/ZL: pointer to data in flash (low)
; - R29/ZH: pointer to data in flash (hi)
; OUT:
; - CARRY flag set if okay, clear on error
; - R1: memory address of DDR register
; - R2: memory address of PORT register
; - R3: memory address of PIN register
; - R4: mask for used pin
; USED: R16
ledGetFlashDataIntoRegs:
push zh
push zl
mov r16, zl
or r16, zh
breq ledGetFlashDataIntoRegs_error
lsl zl
rol zh
lpm r1, z+ ; DDR
lpm r2, z+ ; PORTR
lpm r3, z+ ; PINR
lpm r4, z ; pin mask
pop zl
pop zh
sec
ret
ledGetFlashDataIntoRegs_error:
pop zl
pop zh
clc
ret
; ---------------------------------------------------------------------------
; ledOff
;
; IN:
; - R2: port register address (low part only)
; - R4: bit mask for pin to use
; OUT:
; - nothing
; MODIFIED REGS: none
; CYCLES: 26 (if R2 and R4 valid)
ledOff:
tst r2 ; 1
breq ledOff_end ; 1 if not taken
tst r4 ; 1
breq ledOff_end ; 1 if not taken
push xh ; 2
push xl ; 2
push r16 ; 2
mov xl, r2 ; 1 PORT register address
clr xh ; 1
ld r16, x ; 1
or r16, r4 ; 1
st x, r16 ; 2
pop r16 ; 2
pop xl ; 2
pop xh ; 2
ledOff_end:
ret ; 4
; ---------------------------------------------------------------------------
; ledOn
;
; IN:
; - R2: port register address (low part only)
; - R4: bit mask for pin to use
; OUT:
; - nothing
; MODIFIED REGS: none
; CYCLES: 28
ledOn: ; clock cycles
tst r2 ; 1
breq ledOn_end ; 1 if not taken
tst r4 ; 1
breq ledOn_end ; 1 if not taken
push xh ; 2
push xl ; 2
push r16 ; 2
mov xl, r2 ; 1 PORT register address
clr xh ; 1
ld r16, x ; 1
com r4 ; 1 invert bit mask for following AND
and r16, r4 ; 1
com r4 ; 1 undo inversion
st x, r16 ; 2
pop r16 ; 2
pop xl ; 2
pop xh ; 2
ledOn_end:
ret ; 4