Files
espressif__led_strip/NOTE_SPI.md

3.7 KiB
Raw Blame History

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:

  1. Duty Cycle Ratio: WS2812B needs approximately 1:2 or 2:1 high/low ratios
  2. 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)
  3. 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:

  • 0100 (binary)
  • 1110 (binary)

Data Transmission

The led_strip_spi_refresh() function handles transmission with chunking:

  1. Total data size: strip_len × bytes_per_pixel × 3
  2. Max transfer size: Limited by SPI bus configuration (max_transfer_sz)
  3. Chunked transfers: Data sent in chunks if it exceeds max transfer size
  4. Transmission mode: spi_device_polling_transmit() used for blocking transfer

Advantages of SPI Emulation

  1. No RMT peripheral needed: Frees up RMT channels for other uses
  2. DMA support: Can use DMA for efficient transfers
  3. Precise timing: Hardware SPI ensures consistent bit timing
  4. Scalability: Can drive long LED strips with proper DMA buffer sizing

Limitations

  1. 3x memory overhead: Requires 3× the buffer space vs. RMT
  2. Fixed clock: Requires SPI clock source with ~2.5 MHz capability
  3. No flexibility: Cannot easily adjust timing for non-WS2812B LEDs
  4. SPI bus exclusive: Ties up an entire SPI peripheral

Date

Analysis performed: 2025年11月10日