Implementation
Timing
WS2812B Neopixel
|
|
WS2812B |
SK6812 |
T0H |
0 code, high voltage time |
0.4 us ±150 ns |
0.3 us ±150 ns |
T1H |
1 code, high voltage time |
0.8 us ±150 ns |
0.6 us ±150 ns |
T0L |
0 code, low voltage time |
0.85 us ±150 ns |
0.9 us ±150 ns |
T1L |
1 code, low voltage time |
0.45 us ±150 ns |
0.6 us ±150 ns |
RES |
low voltage time |
Above 50 us |
80 us |
- 1 bit takes 1.25 us (800 kHz), 24 bit take 30 us
- Timer resolution 0.25 us
- MSB first
- GRB
- 3 cycles for a wait loop
lsls r3, r3, #1 // set carry bit
ittee cs
movwcs r5, #T1H
movtcs r5, #T1L
movwcc r5, #T0H
movtcc r5, #T0L
6 cycles.
HTML Color 0xRRGGBB
F405
https://github.com/spyren/Mecrisp-Cube/blob/F405/Forth/cube/wings.s
Cycle = 1 / 168 MHz = 6 ns
0.4 us / 6 ns = 66.7 -> max. 66 cycles
.equ T0H, 16 // 0.3 us
.equ T1H, 40 // 0.8 us
.equ T0L, 36 // 0.8 us
.equ T1L, 12 // 0.3 us
WB55
Cycle = 1 / 32 MHz = 31.25 ns
0.4 us / 31.25 ns = 12.8 -> max 12 cycles
.equ T0H, 4 // 0.4 us / (3 * 31.25 ns) = 4.27 -> 4
.equ T1H, 8 // 0.8 us / (3 * 31.25 ns) = 8.53 -> 8
.equ T0L, 5 // 0.85 us / (3 * 31.25 ns) = 9.07 -> 5 (4 turns less)
.equ T1L, 1 // 0.45 us / (3 * 31.25 ns) = 4.53 -> 1 (4 turns less)
.equ RESTIME, 533 // 50 us / (3 * 31.25 ns) = 533
// Registers
.equ GPIO_BSRR, 0x18 // GPIOx->BSRR bit set/reset
.global BSP_neopixelDataTx
BSP_neopixelDataTx:
push {r4-r6, lr}
lsl r2, r2, #8 // r2 = rrggbb00
mov r3, r2 // r3 = rrggbb00
bfc r3, #16, #16 // r3 = 0000bb00
rev16 r2, r2 // r2 = ggrr00bb
bfc r2, #0, #16 // r2 = ggrr0000
add r2, r2, r3 // r2 = ggrrbb00
lsl r3, r1, #16 // clear port pin for BSRR
mov r6, #24 // 24 bits
// set DOUT pin low and wait reset time
str r3, [r0, #GPIO_BSRR]
ldr r4, =RESTIME
1: subs r4, r4, #1 1
bne 1b
cycles
bit_loop:
lsls r2, r2, #1 // get the next bit -> set the carry bit 1
ittee cs 1
movcs r4, #T1H 1
movcs r5, #T1L 1
movcc r4, #T0H 1
movcc r5, #T0L 1
// set DOUT pin high
str r1, [r0, #GPIO_BSRR] 2
1: subs r4, r4, #1 1
bne 1b 1 (2)
// set DOUT pin low
str r3, [r0, #GPIO_BSRR] 2
2: subs r5, r5, #1 1
bne 2b 1 (2)
subs r6, r6, #1 1
bne bit_loop 2
pop {r4-r6, pc}
Set/Reset Portpin
GPIO port bit set/reset register GPIOx_BSRR
- Address offset: 0x18, x = A..K, D8 = PC0
- bit0 .. bit15 bit set
- bit16 .. bit31 bit reset
#define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800UL)
#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL)
#define PERIPH_BASE 0x40000000UL /*!< Peripheral base address in the alias region */
GPIOC->BSRR