; *************************************************************************** ; copyright : (C) 2024 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. * ; *************************************************************************** ; *************************************************************************** ; defines .equ SK6812_PATTERN_NUM = 3 .equ SK6812_MODE_OFF = 0 .equ SK6812_MODE_ON = 1 .equ SK6812_MODE_AUTO = 2 .equ SK6812_TYPE_BTF_TYPE1 = 0 ; new BTF stripes .equ SK6812_TYPE_NUM = 1 .equ SK6812_DEFAULT_ONTIME = 300 ; 30secs ; *************************************************************************** ; data .dseg sk6812DataBegin: sk6812NumLeds: .byte 1 sk6812Pattern: .byte 5*SK6812_PATTERN_NUM ; 1 byte num leds, 4 bytes colour (RGBW) sk6812RGBW: .byte 4 ; current RGBW value sk6812Mode: .byte 1 sk6812Type: .byte 1 ; which timing type to use sk6812Timer100ms: .byte 2 ; timer in 100msecs before turning light off sk6812Reload100ms: .byte 2 ; reload value used when triggering light sk6812DataEnd: ; *************************************************************************** ; code .cseg ; --------------------------------------------------------------------------- ; @routine SK6812_Init ; ; @return CFLAG set if okay, clear on error SK6812_Init: ldi xh, HIGH(sk6812DataBegin) ldi xl, LOW(sk6812DataBegin) clr r16 ldi r17, (sk6812DataEnd-sk6812DataBegin) rcall Utils_FillSram ldi r16, SK6812_MODE_AUTO sts sk6812Mode, r16 ldi r16, LOW(SK6812_DEFAULT_ONTIME) sts sk6812Reload100ms, r16 ldi r16, HIGH(SK6812_DEFAULT_ONTIME) sts sk6812Reload100ms+1, r16 sbi SK6812_DDR, SK6812_PINNUM ; set to output cbi SK6812_PORT, SK6812_PINNUM ; set LOW ldi r16, 144 sts sk6812NumLeds, r16 rcall sk6812ReadConfFromEeprom rcall SK6812_Trigger sec ret SK6812_Init_error: clc ret ; @end ; --------------------------------------------------------------------------- ; @routine SK6812_Fini ; ; @return CFLAG set if okay, clear on error ; USED: SK6812_Fini: clr r16 sts sk6812Reload100ms, r16 sts sk6812Reload100ms+1, r16 clr r18 ; turn light off rcall sk6812SetState ; (r16, r17, r18, r19, r20, r21, r23, r24, r25) sec ret ; @end ; --------------------------------------------------------------------------- ; @routine SK6812_EverySecond SK6812_Every100ms: lds r16, sk6812Mode cpi r16, SK6812_MODE_AUTO brne SK6812_Every100ms_ret lds r24, sk6812Timer100ms lds r25, sk6812Timer100ms+1 mov r16, r24 or r16, r25 breq SK6812_Every100ms_ret sbiw r25:r24, 1 sts sk6812Timer100ms, r24 sts sk6812Timer100ms+1, r25 brne SK6812_Every100ms_ret ; timer elapsed, turn off light clr r18 rcall sk6812SetState SK6812_Every100ms_ret: ret ; @end ; --------------------------------------------------------------------------- ; @routine SK6812_SetAutoTimerReload @global ; ; @param r19:r18 value ; @clobbers none SK6812_SetAutoTimerReload: sts sk6812Reload100ms, r18 sts sk6812Reload100ms+1, r19 ret ; @end ; --------------------------------------------------------------------------- ; @routine SK6812_GetAutoTimerReload @global ; ; @return r19:r18 reload value in secs ; @clobbers none SK6812_GetAutoTimerReload: lds r18, sk6812Reload100ms lds r19, sk6812Reload100ms+1 ret ; @end ; --------------------------------------------------------------------------- ; @routine SK6812_Trigger ; ; Restart on-timer, turn light on if it is off ; @clobbers r16, r17, r18, r19, r20, r21, r23, r24, r25 SK6812_Trigger: lds r16, sk6812Mode cpi r16, SK6812_MODE_AUTO brne SK6812_Trigger_ret lds r16, sk6812Timer100ms lds r17, sk6812Timer100ms+1 or r16, r17 lds r17, sk6812Reload100ms sts sk6812Timer100ms, r17 lds r17, sk6812Reload100ms+1 sts sk6812Timer100ms+1, r17 tst r16 brne SK6812_Trigger_ret ldi r18, 1 rcall sk6812SetState ; (r16, r17, r18, r19, r20, r21, r23, r24, r25) SK6812_Trigger_ret: ret ; @end ; --------------------------------------------------------------------------- ; @routine SK6812_SetState @global ; ; Set all LEDs to same colour according to state. ; ; @param r18 0: all LEDs off, otherwise all LEDs color stored in sk6812RGBW ; @clobbers r18, r19, r20, r21, (r16, r17, r23, r24, r25) SK6812_SetState: lds r16, sk6812Mode cpi r16, SK6812_MODE_AUTO brne SK6812_SetState_end rjmp sk6812SetState SK6812_SetState_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine SK6812_SetMode @global ; ; @param r18 mode (SK6812_MODE_OFF, SK6812_MODE_ON, SK6812_MODE_AUTO) ; @clobbers r18, (r16, r17, r19, r20, r21, r23, r24, r25) SK6812_SetMode: sts sk6812Mode, r18 cpi r18, SK6812_MODE_OFF breq SK6812_SetState_off ; cpi r18, SK6812_MODE_ON ; breq SK6812_SetState_on rjmp SK6812_SetState_on ret SK6812_SetState_off: clr r18 rjmp sk6812SetState ; (r16, r17, r18, r19, r20, r21, r23, r24, r25) SK6812_SetState_on: ldi r18, 1 rjmp sk6812SetState ; (r16, r17, r18, r19, r20, r21, r23, r24, r25) ; @end ; --------------------------------------------------------------------------- ; @routine SK6812_SetRGBW @global ; ; Store new color for all LEDs. ; ; @param r18 red value ; @param r19 green value ; @param r20 blue color ; @param r21 white color ; @clobbers (r16, r17, r18, r19, r20, r21, r23, r24, r25, X) SK6812_SetRGBW: push r15 in r15, SREG cli sts sk6812RGBW, r18 sts sk6812RGBW+1, r19 sts sk6812RGBW+2, r20 sts sk6812RGBW+3, r21 rcall sk6812WriteConfToEeprom ; (R16, R17, X) ; no longer set state ; ldi r18, 1 ; ON ; rcall SK6812_SetState ; (r16, r17, r18, r19, r20, r21, r23, r24, r25) out SREG, r15 pop r15 ret ; @end ; --------------------------------------------------------------------------- ; @routine sk6812SetState ; ; Set all LEDs to same colour according to state. ; ; @param r18 0: all LEDs off, otherwise all LEDs color stored in sk6812RGBW ; @clobbers R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, X sk6812SetState: tst r18 breq sk6812SetState_off lds r18, sk6812RGBW lds r19, sk6812RGBW+1 lds r20, sk6812RGBW+2 lds r21, sk6812RGBW+3 rcall sk6812SetAllColor ; (r16, r17, r23, r24, r25) ldi r18, 1 rjmp sk6812ReportState sk6812SetState_off: clr r18 clr r19 clr r20 clr r21 rcall sk6812SetAllColor ; (r16, r17, r23, r24, r25) ldi r18, 0 rjmp sk6812ReportState ; (R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, X) ; @end #if 0 ; --------------------------------------------------------------------------- ; @routine sk6812SendPattern ; ; Send given pattern to LEDs. ; ; @param R22 number of 5-byte subpatterns ; @param X pointer to pattern (numleds, R, G, B, W)*SK6812_PATTERN_NUM ; @clobbers R18, R19, R20, R21, R22, R23, X (R16, R17) sk6812SendPattern: sk6812SendPattern_loop1: ld r23, X+ ; num leds tst r23 brne sk6812SendPattern_readandset ret ; no leds, done sk6812SendPattern_readandset: ld r18, X+ ; R ld r19, X+ ; G ld r20, X+ ; B ld r21, X+ ; W sk6812SendPattern_loop2: rcall sk6812SendQuadruple ; (r16, r17) dec r23 brne sk6812SendPattern_loop2 dec r22 brne sk6812SendPattern_loop1 ret ; @end #endif ; --------------------------------------------------------------------------- ; @routine sk6812SetAllColor ; ; Set all LEDs to same colour. ; ; @param r18 red value ; @param r19 green value ; @param r20 blue value ; @param r21 white value ; @clobbers r23 (r16) sk6812SetAllColor: push zl push zh rcall sk6812GetJumpTableEntryForCurrentType brcc sk6812SetAllColor_done icall sk6812SetAllColor_done: pop zh pop zl ret ; @end ; @clobbers r24 sk6812GetJumpTableEntryForCurrentType: ldi zl, LOW(sk6812JumpTableSendByte) ldi zh, HIGH(sk6812JumpTableSendByte) lds r24, sk6812Type cpi r24, SK6812_TYPE_NUM brcc sk6812GetJumpTableEntryForCurrentType_ret add zl, r24 adc zh, r24 sub zh, r24 sec sk6812GetJumpTableEntryForCurrentType_ret: ret ; @end ; --------------------------------------------------------------------------- ; @routine sk6812WriteConfToEeprom ; ; @clobbers r16, r17, X sk6812WriteConfToEeprom: push r15 in r15, SREG cli ldi xl, LOW(EEPROM_OFFS_SK6812_RGBW) ldi xh, HIGH(EEPROM_OFFS_SK6812_RGBW) lds r16, sk6812RGBW rcall Eeprom_WriteByteIfChanged ; (R17) adiw xh:xl, 1 lds r16, sk6812RGBW+1 rcall Eeprom_WriteByteIfChanged ; (R17) adiw xh:xl, 1 lds r16, sk6812RGBW+2 rcall Eeprom_WriteByteIfChanged ; (R17) adiw xh:xl, 1 lds r16, sk6812RGBW+3 rcall Eeprom_WriteByteIfChanged ; (R17) adiw xh:xl, 1 lds r16, sk6812Type rcall Eeprom_WriteByteIfChanged ; (R17) out SREG, r15 pop r15 ret ; @end ; --------------------------------------------------------------------------- ; @routine sk6812ReadConfFromEeprom ; ; @clobbers r16, r17, X sk6812ReadConfFromEeprom: push r15 in r15, SREG cli ldi xl, LOW(EEPROM_OFFS_SK6812_RGBW) ldi xh, HIGH(EEPROM_OFFS_SK6812_RGBW) rcall Eeprom_ReadByte brcc sk6812ReadConfFromEeprom_default mov r18, r16 adiw xh:xl, 1 rcall Eeprom_ReadByte brcc sk6812ReadConfFromEeprom_default mov r19, r16 adiw xh:xl, 1 rcall Eeprom_ReadByte brcc sk6812ReadConfFromEeprom_default mov r20, r16 adiw xh:xl, 1 rcall Eeprom_ReadByte brcc sk6812ReadConfFromEeprom_default mov r21, r16 adiw xh:xl, 1 ; read type rcall Eeprom_ReadByte brcc sk6812ReadConfFromEeprom_default cpi r16, SK6812_TYPE_NUM brcc sk6812ReadConfFromEeprom_checkColor sts sk6812Type, r16 sk6812ReadConfFromEeprom_checkColor: mov r16, r18 and r16, r19 and r16, r20 and r16, r21 inc r16 brne sk6812ReadConfFromEeprom_storeColor ; fall through if value from EEPROM is 0xffffffff sk6812ReadConfFromEeprom_default: ldi r18, 128 ; R ldi r19, 69 ; G ldi r20, 0 ; B ldi r21, 0 ; W sk6812ReadConfFromEeprom_storeColor: sts sk6812RGBW, r18 sts sk6812RGBW+1, r19 sts sk6812RGBW+2, r20 sts sk6812RGBW+3, r21 sk6812ReadConfFromEeprom_end: out SREG, r15 pop r15 ret ; @end