Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(led_strip): Support more pixel orders of 3 colors (IEC-126) #344

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions led_strip/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 3.0.0

- Discontinued support for ESP-IDF v4.x
- Added configuration for user-defined color component format

## 2.5.5

- Simplified the led_strip component dependency, the time of full build with ESP-IDF v5.3 can now be shorter.
Expand Down
9 changes: 2 additions & 7 deletions led_strip/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,8 @@ include($ENV{IDF_PATH}/tools/cmake/version.cmake)
set(srcs "src/led_strip_api.c")
set(public_requires)

# Starting from esp-idf v5.x, the RMT driver is rewritten
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.0")
if(CONFIG_SOC_RMT_SUPPORTED)
list(APPEND srcs "src/led_strip_rmt_dev.c" "src/led_strip_rmt_encoder.c")
endif()
else()
list(APPEND srcs "src/led_strip_rmt_dev_idf4.c")
if(CONFIG_SOC_RMT_SUPPORTED)
list(APPEND srcs "src/led_strip_rmt_dev.c" "src/led_strip_rmt_encoder.c")
endif()

# the SPI backend driver relies on some feature that was available in IDF 5.1
Expand Down
59 changes: 34 additions & 25 deletions led_strip/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,29 @@ This is the most economical way to drive the LEDs because it only consumes one R
```c
#define BLINK_GPIO 0

led_strip_handle_t led_strip;

/* LED strip initialization with the GPIO and pixels number*/
/// LED strip common configuration
led_strip_config_t strip_config = {
.strip_gpio_num = BLINK_GPIO, // The GPIO that connected to the LED strip's data line
.max_leds = 1, // The number of LEDs in the strip,
.led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip
.led_model = LED_MODEL_WS2812, // LED strip model
.flags.invert_out = false, // whether to invert the output signal (useful when your hardware has a level inverter)
.strip_gpio_num = BLINK_GPIO, // The GPIO that connected to the LED strip's data line
.max_leds = 1, // The number of LEDs in the strip,
.led_model = LED_MODEL_WS2812, // LED strip model, it determines the bit timing
.color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRB, // The color component format is G-R-B
.flags = {
.invert_out = false, // don't invert the output signal
}
};

/// RMT backend specific configuration
led_strip_rmt_config_t rmt_config = {
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
.rmt_channel = 0,
#else
.clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
.resolution_hz = 10 * 1000 * 1000, // 10MHz
.flags.with_dma = false, // whether to enable the DMA feature
#endif
.clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
.resolution_hz = 10 * 1000 * 1000, // RMT counter clock frequency: 10MHz
.mem_block_symbols = 64, // the memory size of each RMT channel, in words (4 bytes)
.flags = {
.with_dma = false, // DMA feature is available on chips like ESP32-S3/P4
}
};

/// Create the LED strip object
led_strip_handle_t led_strip;
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
```

Expand All @@ -51,22 +54,28 @@ Please note, the SPI backend has a dependency of **ESP-IDF >= 5.1**
```c
#define BLINK_GPIO 0

led_strip_handle_t led_strip;

/* LED strip initialization with the GPIO and pixels number*/
/// LED strip common configuration
led_strip_config_t strip_config = {
.strip_gpio_num = BLINK_GPIO, // The GPIO that connected to the LED strip's data line
.max_leds = 1, // The number of LEDs in the strip,
.led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip
.led_model = LED_MODEL_WS2812, // LED strip model
.flags.invert_out = false, // whether to invert the output signal (useful when your hardware has a level inverter)
.strip_gpio_num = BLINK_GPIO, // The GPIO that connected to the LED strip's data line
.max_leds = 1, // The number of LEDs in the strip,
.led_model = LED_MODEL_WS2812, // LED strip model, it determines the bit timing
.color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRB, // The color component format is G-R-B
.flags = {
.invert_out = false, // don't invert the output signal
}
};

/// SPI backend specific configuration
led_strip_spi_config_t spi_config = {
.clk_src = SPI_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
.flags.with_dma = true, // Using DMA can improve performance and help drive more LEDs
.spi_bus = SPI2_HOST, // SPI bus ID
.spi_bus = SPI2_HOST, // SPI bus ID
.flags = {
.with_dma = true, // Using DMA can improve performance and help drive more LEDs
}
};

/// Create the LED strip object
led_strip_handle_t led_strip;
ESP_ERROR_CHECK(led_strip_new_spi_device(&strip_config, &spi_config, &led_strip));
```

Expand Down
120 changes: 93 additions & 27 deletions led_strip/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ Also see `led_strip_set_pixel` if you only want to specify the RGB part of the c
| Type | Name |
| ---: | :--- |
| struct | [**led\_strip\_rmt\_config\_t**](#struct-led_strip_rmt_config_t) <br>_LED Strip RMT specific configuration._ |
| struct | [**led\_strip\_rmt\_extra\_config**](#struct-led_strip_rmt_config_tled_strip_rmt_extra_config) <br> |

## Functions

Expand All @@ -202,12 +203,16 @@ Variables:

- rmt\_clock\_source\_t clk_src <br>RMT clock source

- struct led\_strip\_rmt\_config\_t::@0 flags <br>Extra driver flags
- struct [**led\_strip\_rmt\_config\_t::led\_strip\_rmt\_extra\_config**](#struct-led_strip_rmt_config_tled_strip_rmt_extra_config) flags <br>Extra driver flags

- size\_t mem_block_symbols <br>How many RMT symbols can one RMT channel hold at one time. Set to 0 will fallback to use the default size.
- size\_t mem_block_symbols <br>How many RMT symbols can one RMT channel hold at one time. Set to 0 will fallback to use the default size. Extra RMT specific driver flags

- uint32\_t resolution_hz <br>RMT tick resolution, if set to zero, a default resolution (10MHz) will be applied

### struct `led_strip_rmt_config_t::led_strip_rmt_extra_config`

Variables:

- uint32\_t with_dma <br>Use DMA to transmit data

## Functions Documentation
Expand Down Expand Up @@ -261,7 +266,7 @@ Variables:

- spi\_clock\_source\_t clk_src <br>SPI clock source

- struct led\_strip\_spi\_config\_t::@1 flags <br>Extra driver flags
- struct [**led\_strip\_spi\_config\_t**](#struct-led_strip_spi_config_t) flags <br>Extra driver flags

- spi\_host\_device\_t spi_bus <br>SPI bus ID. Which buses are available depends on the specific chip

Expand Down Expand Up @@ -305,13 +310,54 @@ Although only the MOSI line is used for generating the signal, the whole SPI bus

| Type | Name |
| ---: | :--- |
| union | [**led\_color\_component\_format\_t**](#union-led_color_component_format_t) <br>_LED color component format._ |
| struct | [**format\_layout**](#struct-led_color_component_format_tformat_layout) <br> |
| enum | [**led\_model\_t**](#enum-led_model_t) <br>_LED strip model._ |
| enum | [**led\_pixel\_format\_t**](#enum-led_pixel_format_t) <br>_LED strip pixel format._ |
| struct | [**led\_strip\_config\_t**](#struct-led_strip_config_t) <br>_LED Strip Configuration._ |
| typedef struct [**led\_strip\_t**](#struct-led_strip_t) \* | [**led\_strip\_handle\_t**](#typedef-led_strip_handle_t) <br>_LED strip handle._ |
| struct | [**led\_strip\_config\_t**](#struct-led_strip_config_t) <br>_LED Strip common configurations The common configurations are not specific to any backend peripheral._ |
| struct | [**led\_strip\_extra\_flags**](#struct-led_strip_config_tled_strip_extra_flags) <br> |
| typedef struct [**led\_strip\_t**](#struct-led_strip_t) \* | [**led\_strip\_handle\_t**](#typedef-led_strip_handle_t) <br>_Type of LED strip handle._ |

## Macros

| Type | Name |
| ---: | :--- |
| define | [**LED\_STRIP\_COLOR\_COMPONENT\_FMT\_GRB**](#define-led_strip_color_component_fmt_grb) ([**led\_color\_component\_format\_t**](#union-led_color_component_format_t)){.format = {.r\_pos = 1, .g\_pos = 0, .b\_pos = 2, .w\_pos = 3, .reserved = 0, .num\_components = 3}}<br>_Helper macros to set the color component format._ |
| define | [**LED\_STRIP\_COLOR\_COMPONENT\_FMT\_GRBW**](#define-led_strip_color_component_fmt_grbw) ([**led\_color\_component\_format\_t**](#union-led_color_component_format_t)){.format = {.r\_pos = 1, .g\_pos = 0, .b\_pos = 2, .w\_pos = 3, .reserved = 0, .num\_components = 4}}<br> |
| define | [**LED\_STRIP\_COLOR\_COMPONENT\_FMT\_RGB**](#define-led_strip_color_component_fmt_rgb) ([**led\_color\_component\_format\_t**](#union-led_color_component_format_t)){.format = {.r\_pos = 0, .g\_pos = 1, .b\_pos = 2, .w\_pos = 3, .reserved = 0, .num\_components = 3}}<br> |
| define | [**LED\_STRIP\_COLOR\_COMPONENT\_FMT\_RGBW**](#define-led_strip_color_component_fmt_rgbw) ([**led\_color\_component\_format\_t**](#union-led_color_component_format_t)){.format = {.r\_pos = 0, .g\_pos = 1, .b\_pos = 2, .w\_pos = 3, .reserved = 0, .num\_components = 4}}<br> |

## Structures and Types Documentation

### union `led_color_component_format_t`

_LED color component format._

**Note:**

The format is used to specify the order of color components in each pixel, also the number of color components.

Variables:

- struct [**led\_color\_component\_format\_t::format\_layout**](#struct-led_color_component_format_tformat_layout) format <br>Format layout

- uint32\_t format_id <br>Format ID

### struct `led_color_component_format_t::format_layout`

Variables:

- uint32\_t b_pos <br>Position of the blue channel in the color order: 0~3

- uint32\_t g_pos <br>Position of the green channel in the color order: 0~3

- uint32\_t num_components <br>Number of color components per pixel: 3 or 4. If set to 0, it will fallback to 3

- uint32\_t r_pos <br>Position of the red channel in the color order: 0~3

- uint32\_t reserved <br>Reserved

- uint32\_t w_pos <br>Position of the white channel in the color order: 0~3

### enum `led_model_t`

_LED strip model._
Expand All @@ -328,52 +374,72 @@ enum led_model_t {

Different led model may have different timing parameters, so we need to distinguish them.

### enum `led_pixel_format_t`

_LED strip pixel format._

```c
enum led_pixel_format_t {
LED_PIXEL_FORMAT_GRB,
LED_PIXEL_FORMAT_GRBW,
LED_PIXEL_FORMAT_INVALID
};
```

### struct `led_strip_config_t`

_LED Strip Configuration._
_LED Strip common configurations The common configurations are not specific to any backend peripheral._

Variables:

- struct led\_strip\_config\_t::@2 flags <br>Extra driver flags
- [**led\_color\_component\_format\_t**](#union-led_color_component_format_t) color_component_format <br>Specifies the order of color components in each pixel. Use helper macros like `LED_STRIP_COLOR_COMPONENT_FMT_GRB` to set the format LED strip extra driver flags

- uint32\_t invert_out <br>Invert output signal
- struct [**led\_strip\_config\_t::led\_strip\_extra\_flags**](#struct-led_strip_config_tled_strip_extra_flags) flags <br>Extra driver flags

- [**led\_model\_t**](#enum-led_model_t) led_model <br>LED model
- [**led\_model\_t**](#enum-led_model_t) led_model <br>Specifies the LED strip model (e.g., WS2812, SK6812)

- [**led\_pixel\_format\_t**](#enum-led_pixel_format_t) led_pixel_format <br>LED pixel format

- uint32\_t max_leds <br>Maximum LEDs in a single strip
- uint32\_t max_leds <br>Maximum number of LEDs that can be controlled in a single strip

- int strip_gpio_num <br>GPIO number that used by LED strip

### struct `led_strip_config_t::led_strip_extra_flags`

Variables:

- uint32\_t invert_out <br>Invert output signal

### typedef `led_strip_handle_t`

_LED strip handle._
_Type of LED strip handle._

```c
typedef struct led_strip_t* led_strip_handle_t;
```

## Macros Documentation

### define `LED_STRIP_COLOR_COMPONENT_FMT_GRB`

_Helper macros to set the color component format._

```c
#define LED_STRIP_COLOR_COMPONENT_FMT_GRB ( led_color_component_format_t ){.format = {.r_pos = 1, .g_pos = 0, .b_pos = 2, .w_pos = 3, .reserved = 0, .num_components = 3}}
```

### define `LED_STRIP_COLOR_COMPONENT_FMT_GRBW`

```c
#define LED_STRIP_COLOR_COMPONENT_FMT_GRBW ( led_color_component_format_t ){.format = {.r_pos = 1, .g_pos = 0, .b_pos = 2, .w_pos = 3, .reserved = 0, .num_components = 4}}
```

### define `LED_STRIP_COLOR_COMPONENT_FMT_RGB`

```c
#define LED_STRIP_COLOR_COMPONENT_FMT_RGB ( led_color_component_format_t ){.format = {.r_pos = 0, .g_pos = 1, .b_pos = 2, .w_pos = 3, .reserved = 0, .num_components = 3}}
```

### define `LED_STRIP_COLOR_COMPONENT_FMT_RGBW`

```c
#define LED_STRIP_COLOR_COMPONENT_FMT_RGBW ( led_color_component_format_t ){.format = {.r_pos = 0, .g_pos = 1, .b_pos = 2, .w_pos = 3, .reserved = 0, .num_components = 4}}
```

## File interface/led_strip_interface.h

## Structures and Types

| Type | Name |
| ---: | :--- |
| struct | [**led\_strip\_t**](#struct-led_strip_t) <br>_LED strip interface definition._ |
| typedef struct [**led\_strip\_t**](#struct-led_strip_t) | [**led\_strip\_t**](#typedef-led_strip_t) <br> |
| typedef struct led\_strip\_t | [**led\_strip\_t**](#typedef-led_strip_t) <br> |

## Structures and Types Documentation

Expand Down
6 changes: 2 additions & 4 deletions led_strip/examples/led_strip_rmt_ws2812/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)

set(COMPONENTS main)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(led_strip_rmt_ws2812)
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## IDF Component Manager Manifest File
dependencies:
espressif/led_strip:
version: '^2'
version: '^3'
override_path: '../../../'
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
Expand All @@ -11,9 +11,9 @@
#include "esp_err.h"

// GPIO assignment
#define LED_STRIP_BLINK_GPIO 2
#define LED_STRIP_GPIO_PIN 2
// Numbers of the LED in the strip
#define LED_STRIP_LED_NUMBERS 24
#define LED_STRIP_LED_COUNT 24
// 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution)
#define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000)

Expand All @@ -23,22 +23,23 @@ led_strip_handle_t configure_led(void)
{
// LED strip general initialization, according to your led board design
led_strip_config_t strip_config = {
.strip_gpio_num = LED_STRIP_BLINK_GPIO, // The GPIO that connected to the LED strip's data line
.max_leds = LED_STRIP_LED_NUMBERS, // The number of LEDs in the strip,
.led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip
.led_model = LED_MODEL_WS2812, // LED strip model
.flags.invert_out = false, // whether to invert the output signal
.strip_gpio_num = LED_STRIP_GPIO_PIN, // The GPIO that connected to the LED strip's data line
.max_leds = LED_STRIP_LED_COUNT, // The number of LEDs in the strip,
.led_model = LED_MODEL_WS2812, // LED strip model
.color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRB, // The color order of the strip: GRB
.flags = {
.invert_out = false, // don't invert the output signal
}
};

// LED strip backend configuration: RMT
led_strip_rmt_config_t rmt_config = {
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
.rmt_channel = 0,
#else
.clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
.resolution_hz = LED_STRIP_RMT_RES_HZ, // RMT counter clock frequency
.flags.with_dma = false, // DMA feature is available on ESP target like ESP32-S3
#endif
.mem_block_symbols = 64, // the memory size of each RMT channel, in words (4 bytes)
.flags = {
.with_dma = false, // DMA feature is available on chips like ESP32-S3/P4
}
};

// LED Strip object handle
Expand All @@ -57,7 +58,7 @@ void app_main(void)
while (1) {
if (led_on_off) {
/* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */
for (int i = 0; i < LED_STRIP_LED_NUMBERS; i++) {
for (int i = 0; i < LED_STRIP_LED_COUNT; i++) {
ESP_ERROR_CHECK(led_strip_set_pixel(led_strip, i, 5, 5, 5));
}
/* Refresh the strip to send data */
Expand Down
6 changes: 2 additions & 4 deletions led_strip/examples/led_strip_spi_ws2812/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)

set(COMPONENTS main)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(led_strip_spi_ws2812)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## IDF Component Manager Manifest File
dependencies:
espressif/led_strip:
version: '^2.4'
version: '^3'
override_path: '../../../'
idf: ">=5.1"
Loading
Loading