led_strip_spi - SPI-based driver for SK9822/APA102

Supported LEDs

The driver supports the following LEDs.

  • SK9822

  • APA102

Warning

The driver should work with APA102, but not tested.

Supported targets

The driver supports the following targets.

  • ESP32-family, including ESP32S2

  • ESP8266

Because the SPI driver in esp-idf differs from the one in ESP8266 RTOS SDK, the members of led_strip_spi_t — a descriptor to configure and manage LED strip — are different.

Note

If you have better ideas to unify the two structures, I would love to hear.

Usage

Call led_strip_spi_install().

#include <led_strip_spi.h>

ESP_ERROR_CHECK(led_strip_spi_install());

Create led_strip_spi_t and initialize it with LED_STRIP_SPI_DEFAULT().

led_strip_spi_t strip = LED_STRIP_SPI_DEFAULT();

Configure the LED strip descriptor. First, set length.

strip.length = N_PIXEL;

led_strip_spi_t is an alias of either led_strip_spi_esp32_t or led_strip_spi_esp8266_t.

For ESP32, provide spi_device_handle_t, and set max_transfer_sz to the maximum size of the SPI data to transfer. LED_STRIP_SPI_BUFFER_SIZE() macro is provided to calculate the size from the number of pixels. Optionally, set SPI bus clock speed.

#if HELPER_TARGET_IS_ESP32
spi_device_handle_t device_handle;
strip.device_handle = device_handle;
strip.max_transfer_sz = LED_STRIP_SPI_BUFFER_SIZE(N_PIXEL);
strip.clock_speed_hz = 1000000 * 10;
#endif

Then, call led_strip_spi_init().

led_strip_spi_init(&strip);

The strip is now ready. Use led_strip_spi_set_pixel() and other functions to modify the buffer. The buffer is sent to the bus when calling led_strip_spi_flush(). See the example provided.

SPI signals and GPIO pins

The driver uses hardware SPI to drive LED strip. While ESP32-family chips can route SPI signals to GPIOs using GPIO matrix, ESP8266 cannot.

SPI clock speed

On ESP32, dedicated IO_MUX pins can clock faster (80Mhz) than GPIO pins through GPIO matrix (40Mhz), but the maximum clock frequency of SK9822 is 30Mhz, which is below the maximum clock frequency of GPIO matrix. As such, IO_MUX has no practical benefits here.

Known issues

SK9822 has bits to control global brightness, but the driver does not support it yet.

group led_strip_spi_esp32

Defines

LED_STRIP_SPI_DEFAULT_HOST_DEVICE

Default is SPI2_HOST (HSPI_HOST if esp-idf version is v3.x).

LED_STRIP_SPI_DEFAULT_MOSI_IO_NUM

GPIO pin number of LED_STRIP_SPI_DEFAULT_HOST_DEVICE’s MOSI (default is 13 for ESP32, 7 for ESP32C3)

LED_STRIP_SPI_DEFAULT_SCLK_IO_NUM

GPIO pin number of LED_STRIP_SPI_DEFAULT_HOST_DEVICE’s SCLK (default is 14 for ESP32, 6 for ESP32C3)

LED_STRIP_SPI_DEFAULT_DMA_CHAN

Default DMA channel to use.

Default is SPI_DMA_CH_AUTO for ESP-IDF v4.3 and newer, 1 for older versions.

LED_STRIP_SPI_DEFAULT_ESP32()

Macro to initialize led_strip_spi_esp32_t.

buf: NULL, length: 1, host_device: LED_STRIP_SPI_DEFAULT_HOST_DEVICE, mosi_io_num: LED_STRIP_SPI_DEFAULT_MOSI_IO_NUM, max_transfer_sz: 0, clock_speed_hz: 1000000, queue_size: 1, device_handle: NULL, dma_chan: 1

struct led_strip_spi_esp32_t
#include <led_strip_spi_esp32.h>

LED strip descriptor for ESP32-family.

Public Members

int mosi_io_num

GPIO number of SPI MOSI.

int sclk_io_num

GPIO number of SPI SCLK.

int max_transfer_sz

Maximum transfer size in bytes. Defaults to 4094 if 0.

int clock_speed_hz

Clock speed in Hz.

int queue_size

Queue size used by spi_device_queue_trans().

spi_device_handle_t device_handle

Device handle assigned by the driver. The caller must provdie this.

int dma_chan

DMA channed to use. Either 1 or 2.

spi_transaction_t transaction

SPI transaction used internally by the driver.

group led_strip_spi_esp8266

Defines

LED_STRIP_SPI_DEFAULT_ESP8266()

A macro to initialize led_strip_spi_esp8266_t.

length: 1 clk_div: SPI_2MHz_DIV

struct led_strip_spi_esp8266_t
#include <led_strip_spi_esp8266.h>

LED strip descriptor for ESP8266.

Public Members

void *buf

Pointer to the buffer.

size_t length

Number of pixels.

spi_clk_div_t clk_div

Value of clk_div, such as SPI_2MHz_DIV. See available values in ${IDF_PATH}/components/esp8266/include/driver/spi.h.

group led_strip_spi

Defines

LED_STRIP_SPI_MAX_BRIGHTNESS

Maximum brightness value for a pixel.

Functions

esp_err_t led_strip_spi_install()

Setup the driver.

This method must be called before any other led_strip_spi methods

Returns:

ESP_OK on success

esp_err_t led_strip_spi_init(led_strip_spi_t *strip)

Initialize LED strip and allocate buffer memory.

Parameters:

strip – Descriptor of LED strip

Returns:

ESP_OK on success

esp_err_t led_strip_spi_free(led_strip_spi_t *strip)

Free LED strip.

Parameters:

strip – Descriptor of LED strip

Returns:

ESP_OK on success

esp_err_t led_strip_spi_flush(led_strip_spi_t *strip)

Send strip buffer to LEDs.

Parameters:

strip – Descriptor of LED strip

Returns:

ESP_OK on success

esp_err_t led_strip_spi_set_pixel(led_strip_spi_t *strip, const int num, const rgb_t color)

Set color of single LED in strip.

This function does not actually change colors of the LEDs. Call led_strip_spi_flush() to send buffer to the LEDs.

Parameters:
  • strip – Descriptor of LED strip

  • num – LED number, [0:strip.length - 1].

  • color – RGB color

Returns:

ESP_OK on success

esp_err_t led_strip_spi_set_pixel_brightness(led_strip_spi_t *strip, const int num, const rgb_t color, const uint8_t brightness)

Set color of single LED in strip.

This function does not actually change colors of the LEDs. Call led_strip_spi_flush() to send buffer to the LEDs.

Parameters:
  • strip – Descriptor of LED strip

  • num – LED number, [0:strip.length - 1].

  • color – RGB color

  • brightness – Brightness of the LED, [0:100].

Returns:

ESP_OK on success

esp_err_t led_strip_spi_set_pixels(led_strip_spi_t *strip, const int start, size_t len, const rgb_t data)

Set colors of multiple LEDs.

This function does not actually change colors of the LEDs. Call led_strip_spi_flush() to send buffer to the LEDs.

Parameters:
  • strip – Descriptor of LED strip

  • start – First LED index, 0-based

  • len – Number of LEDs

  • data – Pointer to RGB data

Returns:

ESP_OK on success

esp_err_t led_strip_spi_set_pixels_brightness(led_strip_spi_t *strip, const int start, size_t len, const rgb_t data, const uint8_t brightness)

Set colors of multiple LEDs.

This function does not actually change colors of the LEDs. Call led_strip_spi_flush() to send buffer to the LEDs.

Parameters:
  • strip – Descriptor of LED strip

  • start – First LED index, 0-based

  • len – Number of LEDs

  • data – Pointer to RGB data

  • brightness – Brightness of the LED, [0:100].

Returns:

ESP_OK on success

esp_err_t led_strip_spi_fill(led_strip_spi_t *strip, size_t start, size_t len, rgb_t color)

Set multiple LEDs to the one color.

This function does not actually change colors of the LEDs. Call led_strip_spi_flush() to send buffer to the LEDs.

Parameters:
  • strip – Descriptor of LED strip

  • start – First LED index, 0-based

  • len – Number of LEDs

  • color – RGB color

Returns:

ESP_OK on success

esp_err_t led_strip_spi_fill_brightness(led_strip_spi_t *strip, size_t start, size_t len, rgb_t color, const uint8_t brightness)

Set multiple LEDs to the one color.

This function does not actually change colors of the LEDs. Call led_strip_spi_flush() to send buffer to the LEDs.

Parameters:
  • strip – Descriptor of LED strip

  • start – First LED index, 0-based

  • len – Number of LEDs

  • color – RGB color

  • brightness – Brightness of the LEDs, [0:100].

Returns:

ESP_OK on success

group led_strip_spi_sk9822

Functions and macros for SK9822 LED strips.

SPI data frame consists of:

  • A start frame of 32 zero bits (<0x00> <0x00> <0x00> <0x00>).

  • 32 bit LED frames for each LED in the string (<0xE0+brightness> <blue> <green> <red>).

  • A SK9822 reset frame of 32 zero bits (<0x00> <0x00> <0x00> <0x00>).

  • An end frame consisting of at least (n/2) bits of 1, where n is the number of LEDs in the string.

For the details, see SK9822 – a clone of the APA102? and Understanding the APA102 “Superled”.

Defines

LED_STRIP_SPI_FRAME_SK9822_START_SIZE

The size in bytes of start frame.

LED_STRIP_SPI_FRAME_SK9822_LED_SIZE

The size in bytes of each LED frame.

LED_STRIP_SPI_FRAME_SK9822_LEDS_SIZE(N_PIXEL)

Total size in bytes of all LED frames in a strip. N_PIXEL is the number of pixels in the strip.

LED_STRIP_SPI_FRAME_SK9822_RESET_SIZE

The size in bytes of reset frame.

LED_STRIP_SPI_FRAME_SK9822_END_SIZE(N_PIXEL)

The size in bytes of the last frame. N_PIXEL is the number of pixels in the strip.

LED_STRIP_SPI_FRAME_SK9822_LED_MSB3

A magic number of [31:29] in LED frames. The bits must be 1 (APA102, SK9822)

LED_STRIP_SPI_FRAME_SK9822_LED_BRIGHTNESS_BITS

Number of bits used to describe the brightness of the LED.

LED_STRIP_SPI_BUFFER_SIZE(N_PIXEL)

A macro to caliculate required size of buffer. N_PIXEL is the number of pixels in the strip.

Functions

esp_err_t led_strip_spi_sk9822_buf_init(led_strip_spi_t *strip)

Initialize the buffer of SK9822 strip.

Parameters:

strip[in] LED strip descriptor to initialize

Returns:

ESP_OK on success

esp_err_t led_strip_spi_set_pixel_sk9822(led_strip_spi_t *strip, size_t num, rgb_t color, uint8_t brightness)

Set color of a pixel of SK9822 strip.

Parameters:
  • strip[in] LED strip descriptor.

  • num[in] Index of the LED pixel (zero-based).

  • color[in] The color to set.

  • brightness[in] The brightness to set, [0:100].

Returns:

ESP_OK on success.