sk6812: prepare use of multiple timing types.

timing is very tight so we need an extra routine per timing type for
sending a byte to the led strip.
This commit is contained in:
Martin Preuss
2026-03-21 00:40:03 +01:00
parent c5df904fc4
commit 2878d3aaa2
3 changed files with 187 additions and 146 deletions

View File

@@ -228,6 +228,7 @@
#ifdef MODULES_SK6812
.include "modules/sk6812/main.asm"
.include "modules/sk6812/io.asm"
#ifdef MODULES_NETWORK
.include "modules/sk6812/recv.asm"
.include "devices/all/handlevaluemsg.asm"

131
avr/modules/sk6812/io.asm Normal file
View File

@@ -0,0 +1,131 @@
; ***************************************************************************
; copyright : (C) 2026 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. *
; ***************************************************************************
sk6812JumpTableSendByte:
rjmp sk6812SendByte0
rjmp sk6812SendByte1
; ***************************************************************************
; type 0
.macro SK6812_SENDBIT0
sk6812SendBit: ; 0 1
rol r16 ; +1 +1
brcs sk6812SendBit_send1 ; +1 +2
; send 0
nop ; +1
sbi SK6812_PORT, SK6812_PINNUM ; +2
nop ; +1
nop ; +1
cbi SK6812_PORT, SK6812_PINNUM ; +2
; nop ; +1
nop ; +1
rjmp sk6812SendBit_end ; +2
sk6812SendBit_send1:
; send 1
sbi SK6812_PORT, SK6812_PINNUM ; +2
nop ; +1
nop ; +1
nop ; +1
cbi SK6812_PORT, SK6812_PINNUM ; +2
nop ; +1
nop ; +1
nop ; +1
sk6812SendBit_end: ; 13 13
.endmacro
; ---------------------------------------------------------------------------
; @routine sk6812SendByte0
;
; Sends a byte to the LED strip
; @param r16 byte
; @clobbers r16 (r24, r25)
sk6812SendByte0:
SK6812_SENDBIT0
SK6812_SENDBIT0
SK6812_SENDBIT0
SK6812_SENDBIT0
SK6812_SENDBIT0
SK6812_SENDBIT0
SK6812_SENDBIT0
SK6812_SENDBIT0
ret
; @end
; ***************************************************************************
; type 1
.macro SK6812_SENDBIT1
lsl r16 ; +1
brcs l_sendOne ; +1 if false, +2 if branch taken
; send ZERO
nop ; +1
out SK6812_PORT, r25 ; +1 HIGH
nop ; +1
nop ; +1
nop
out SK6812_PORT, r24 ; +1
nop ; +1
rjmp l_end ; +2
l_sendOne:
out SK6812_PORT, r25 ; +1 HIGH
nop ; +1
nop ; +1
nop ; +1
nop ; +1
nop ; +1
out SK6812_PORT, r24 ; +1
nop ; +1
l_end:
.endmacro
; ---------------------------------------------------------------------------
; @routine sk6812SendByte1
;
; Sends a byte to the LED strip
; @param r16 byte
; @clobbers r16, r24, r25
sk6812SendByte1:
ldi r24, 0
ldi r25, (1<<SK6812_PINNUM)
SK6812_SENDBIT1
SK6812_SENDBIT1
SK6812_SENDBIT1
SK6812_SENDBIT1
SK6812_SENDBIT1
SK6812_SENDBIT1
SK6812_SENDBIT1
SK6812_SENDBIT1
ret
; @end

View File

@@ -19,6 +19,10 @@
.equ SK6812_MODE_AUTO = 2
.equ SK6812_TYPE_BTF_NEW = 0
.equ SK6812_TYPE_NUM = 1
; ***************************************************************************
; data
@@ -30,6 +34,7 @@ sk6812DataBegin:
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
sk6812DataEnd:
@@ -231,17 +236,21 @@ sk6812SendPattern_loop2:
; @clobbers r23 (r16, r17, r24, r25)
sk6812SetAllColor:
push zl
push zh
rcall sk6812GetJumpTableEntryForCurrentType
brcc sk6812SetAllColor_done
sbi SK6812_DDR, SK6812_PINNUM ; set to output
cbi SK6812_PORT, SK6812_PINNUM
push r15
in r15, SREG
cli
; Utils_WaitNanoSecs 80000, 0, r22 ; wait for 80us
; Utils_WaitNanoSecs 80000, 0, r22 ; wait for 80us
nop
nop
lds r23, sk6812NumLeds
sk6812SetAllColor_loop:
rcall sk6812SendQuadruple ; (r16, r17, r24, r25)
rcall sk6812SendQuadruple ; (r16, r17, r24, r25, Z)
dec r23
brne sk6812SetAllColor_loop
@@ -249,10 +258,31 @@ sk6812SetAllColor_loop:
cbi SK6812_PORT, SK6812_PINNUM
Utils_WaitNanoSecs 80000, 0, r22 ; wait for 80us
; sbi SK6812_PORT, SK6812_PINNUM
; sbi SK6812_PORT, SK6812_PINNUM
out SREG, r15
pop r15
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
@@ -266,151 +296,30 @@ sk6812SetAllColor_loop:
; @param r19 green value
; @param r20 blue value
; @param r21 white value
; @param Z pointer to jumptable entry for SendByte function (called by ijmp)
; @clobbers r16 (r17, r24, r25)
sk6812SendQuadruple:
mov r16, r19 ; G
rcall sk6812SendByte4 ; (r16, r17, r24, r25)
rcall sk6812SendByte ; (r16, r17, r24, r25)
mov r16, r18 ; R
rcall sk6812SendByte4 ; (r16, r17, r24, r25)
rcall sk6812SendByte ; (r16, r17, r24, r25)
mov r16, r20 ; B
rcall sk6812SendByte4 ; (r16, r17, r24, r25)
rcall sk6812SendByte ; (r16, r17, r24, r25)
mov r16, r21 ; W
rcall sk6812SendByte4 ; (r16, r17, r24, r25)
rcall sk6812SendByte ; (r16, r17, r24, r25)
ret
; @end
; ---------------------------------------------------------------------------
; @macro M_SK6812_HANDLEBIT
.macro M_SK6812_HANDLEBIT
lsl r16 ; +1
brcs l_sendOne ; +1 if false, +2 if branch taken
; send ZERO
nop ; +1
out SK6812_PORT, r25 ; +1 HIGH
nop ; +1
nop ; +1
nop
out SK6812_PORT, r24 ; +1
nop ; +1
rjmp l_end ; +2
l_sendOne:
out SK6812_PORT, r25 ; +1 HIGH
nop ; +1
nop ; +1
nop ; +1
nop ; +1
nop ; +1
out SK6812_PORT, r24 ; +1
nop ; +1
l_end:
.endmacro
; @end
.macro SK6812_SENDBIT1
sk6812SendBit: ; 1 0 1 0
rol r16 ; +1 +1 125 125
sbi SK6812_PORT, SK6812_PINNUM ; +2 +2 375 375
brcs sk6812SendBit_l1 ; +2 +1 625 500
cbi SK6812_PORT, SK6812_PINNUM ; +2 875
sk6812SendBit_l1:
nop ; +1 +1 1000 625
nop ; +1 +1 1125 750
brcc sk6812SendBit_l2 ; +1 +2 1250 1000
cbi SK6812_PORT, SK6812_PINNUM ; +2 1250
sk6812SendBit_l2: ; 10 10 1250 1250
.endmacro
.macro SK6812_SENDBIT
sk6812SendBit: ; 0 1
rol r16 ; +1 +1
brcs sk6812SendBit_send1 ; +1 +2
; send 0
nop ; +1
sbi SK6812_PORT, SK6812_PINNUM ; +2
nop ; +1
nop ; +1
cbi SK6812_PORT, SK6812_PINNUM ; +2
; nop ; +1
nop ; +1
rjmp sk6812SendBit_end ; +2
sk6812SendBit_send1:
; send 1
sbi SK6812_PORT, SK6812_PINNUM ; +2
nop ; +1
nop ; +1
nop ; +1
cbi SK6812_PORT, SK6812_PINNUM ; +2
nop ; +1
nop ; +1
nop ; +1
sk6812SendBit_end: ; 13 13
.endmacro
sk6812SendByte4:
SK6812_SENDBIT
SK6812_SENDBIT
SK6812_SENDBIT
SK6812_SENDBIT
SK6812_SENDBIT
SK6812_SENDBIT
SK6812_SENDBIT
SK6812_SENDBIT
sk6812SendByte:
ijmp
ret
; @end
#if 0
; ---------------------------------------------------------------------------
; @routine sk6812SendByte4
;
; reset: 80microsecs
; 0: 500ns high, 750ns low (+/- 150ns)
; 1: 750ns high, 500ns low (+/- 150ns)
;
; @param r16 value
; @clobbers r16, r17, r24, r25
sk6812SendByte4:
rcall sk6812SendBit
rcall sk6812SendBit
rcall sk6812SendBit
rcall sk6812SendBit
rcall sk6812SendBit
rcall sk6812SendBit
rcall sk6812SendBit
rcall sk6812SendBit
ret
; @end
; @param: r16=current value
sk6812SendBit: ; 1 0
rol r16 ; +1 +1
sbi SK6812_PORT, SK6812_PINNUM ; +2
brcs sk6812SendBit_l1 ; +2 +1
cbi SK6812_PORT, SK6812_PINNUM ; +2
sk6812SendBit_l1:
nop ; +1 +1
nop ; +1 +1
brcc sk6812SendBit_l2 ; +1 +2
cbi SK6812_PORT, SK6812_PINNUM ; +2
sk6812SendBit_l2:
ret
; @end
#endif
; ---------------------------------------------------------------------------
; @routine sk6812WriteConfToEeprom