3.7 KiB
SPI-based LED Strip Driver Analysis
Overview
This driver emulates RMT (Remote Control) signals for WS2812B/SK6812 LED strips using SPI peripheral. It works by encoding each data bit into multiple SPI bits to achieve the required timing characteristics.
Clock Configuration
- SPI Clock Frequency: 2.5 MHz (
LED_STRIP_SPI_DEFAULT_RESOLUTION) - SPI Bit Period: 1/2.5MHz = 400 nanoseconds
- Tolerance: ±300 KHz (2.2 MHz to 2.8 MHz accepted)
Bit Encoding Scheme
Each 1 RMT data bit is encoded as 3 SPI bits, giving a total symbol period of 1.2 μs.
Encoding Patterns
| Data Bit | SPI Pattern (MSB first) | High Time | Low Time | Total Time |
|---|---|---|---|---|
| 0 | 100 (binary) |
400 ns | 800 ns | 1200 ns |
| 1 | 110 (binary) |
800 ns | 400 ns | 1200 ns |
WS2812B Timing Compatibility
The encoding matches WS2812B specifications:
- T0H (0 high time): ~400ns (spec: 350±150ns)
- T0L (0 low time): ~800ns (spec: 800±150ns)
- T1H (1 high time): ~800ns (spec: 700±150ns)
- T1L (1 low time): ~400ns (spec: 600±150ns)
Why 3 Bits per Symbol?
The choice of 3 SPI bits per data bit is driven by timing requirements:
- Duty Cycle Ratio: WS2812B needs approximately 1:2 or 2:1 high/low ratios
- Granularity:
- 2 bits would only give 50/50 split (insufficient)
- 3 bits provides 33/66% or 66/33% ratios (optimal)
- 4+ bits would make the period too long (>1.6μs)
- Clock Frequency: At 2.5 MHz, 3 bits = 1.2μs matches the ~1.25μs WS2812B bit period
Memory Usage
Each LED color component requires:
- 1 byte of actual data
- 3 bytes of SPI transmission data (3:1 expansion)
For RGB LEDs:
- 3 bytes per pixel → 9 bytes SPI data per pixel
For RGBW LEDs:
- 4 bytes per pixel → 12 bytes SPI data per pixel
Defined as: SPI_BYTES_PER_COLOR_BYTE = 3
Bit Mapping Function
The __led_strip_spi_bit() function expands each 8-bit color value into 24 SPI bits (3 bytes):
static void __led_strip_spi_bit(uint8_t data, uint8_t *buf)
Input: 1 byte of color data (8 bits)
Output: 3 bytes written to buffer (24 SPI bits = 8 RMT symbols)
Bit Order
The function processes bits from LSB to MSB and maps them across 3 bytes:
- Bit 0 (LSB) → buf[2] bits 2:1
- Bit 1 → buf[2] bits 5:4, plus bit 7
- Bit 2 → buf[2] bit 7, buf[1] bit 0
- Bit 3 → buf[1] bits 3:2
- Bit 4 → buf[1] bits 6:5
- Bit 5 → buf[0] bits 1:0
- Bit 6 → buf[0] bits 4:3
- Bit 7 (MSB) → buf[0] bits 7:6
Each data bit becomes a 3-bit pattern:
0→100(binary)1→110(binary)
Data Transmission
The led_strip_spi_refresh() function handles transmission with chunking:
- Total data size:
strip_len × bytes_per_pixel × 3 - Max transfer size: Limited by SPI bus configuration (
max_transfer_sz) - Chunked transfers: Data sent in chunks if it exceeds max transfer size
- Transmission mode:
spi_device_polling_transmit()used for blocking transfer
Advantages of SPI Emulation
- No RMT peripheral needed: Frees up RMT channels for other uses
- DMA support: Can use DMA for efficient transfers
- Precise timing: Hardware SPI ensures consistent bit timing
- Scalability: Can drive long LED strips with proper DMA buffer sizing
Limitations
- 3x memory overhead: Requires 3× the buffer space vs. RMT
- Fixed clock: Requires SPI clock source with ~2.5 MHz capability
- No flexibility: Cannot easily adjust timing for non-WS2812B LEDs
- SPI bus exclusive: Ties up an entire SPI peripheral
Date
Analysis performed: 2025年11月10日