Skip to content

Commit

Permalink
Merge pull request #344 from Kainarx/feat/led_strip_support_more_byte…
Browse files Browse the repository at this point in the history
…s_orders

feat(led_strip): Support more pixel orders of 3 colors (IEC-126)
  • Loading branch information
suda-morris authored Oct 25, 2024
2 parents 6c23b9c + 31585c8 commit 4769e0a
Show file tree
Hide file tree
Showing 18 changed files with 303 additions and 366 deletions.
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

0 comments on commit 4769e0a

Please sign in to comment.