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 (13)

LED_STRIP_SPI_DEFAULT_SCLK_IO_NUM

GPIO pin number of LED_STRIP_SPI_DEFAULT_HOST_DEVICE’s SCLK (14)

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.

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.

group led_strip_spi

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

  • numLED number, [0:strip.length - 1].

  • color – RGB color

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_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

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_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

[in] stripLED 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)

Set color of a pixel of SK9822 strip.

Parameters
  • [in] stripLED strip descriptor.

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

  • [in] color – The color to set.

Returns

ESP_OK on success.