; *************************************************************************** ; 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 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 ; *************************************************************************** ; data .dseg ledA3Sram: .byte LED_SRAM_SIZE ; *************************************************************************** ; code .cseg LED_BEGIN: ; --------------------------------------------------------------------------- ; 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 LED_END: .equ MODULE_SIZE_LED = LED_END-LED_BEGIN