Skip to content

Commit

Permalink
feat(led_strip): Support configure pixel orders
Browse files Browse the repository at this point in the history
  • Loading branch information
Kainarx committed Oct 23, 2024
1 parent 60c1426 commit 743e8aa
Show file tree
Hide file tree
Showing 13 changed files with 242 additions and 108 deletions.
4 changes: 4 additions & 0 deletions led_strip/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.6.0

- Add pixel order configuration to support user-defined pixel order.

## 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
2 changes: 1 addition & 1 deletion led_strip/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
include($ENV{IDF_PATH}/tools/cmake/version.cmake)

set(srcs "src/led_strip_api.c")
set(srcs "src/led_strip_api.c" "src/led_strip_common.c")
set(public_requires)

# Starting from esp-idf v5.x, the RMT driver is rewritten
Expand Down
67 changes: 51 additions & 16 deletions led_strip/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
| esp\_err\_t | [**led\_strip\_set\_pixel\_hsv**](#function-led_strip_set_pixel_hsv) ([**led\_strip\_handle\_t**](#typedef-led_strip_handle_t) strip, uint32\_t index, uint16\_t hue, uint8\_t saturation, uint8\_t value) <br>_Set HSV for a specific pixel._ |
| esp\_err\_t | [**led\_strip\_set\_pixel\_rgbw**](#function-led_strip_set_pixel_rgbw) ([**led\_strip\_handle\_t**](#typedef-led_strip_handle_t) strip, uint32\_t index, uint32\_t red, uint32\_t green, uint32\_t blue, uint32\_t white) <br>_Set RGBW for a specific pixel._ |

## Macros

| Type | Name |
| ---: | :--- |
| define | [**LED\_STRIP\_SET\_RGBW\_ORDER**](#define-led_strip_set_rgbw_order) (R, G, B, W) (R &lt;&lt; 0 \| G &lt;&lt; 2 \| B &lt;&lt; 4 \| W &lt;&lt; 6)<br>_Help macro to set pixel RGBW color order The default order of the four-color LED strips is GRBW. If you have a different order, you can use the macro to set_ `pixel_order`_in_[_**led\_strip\_config\_t**_](#struct-led_strip_config_t)_. The positions are counted from the least significant bit (LSB)._ |
| define | [**LED\_STRIP\_SET\_RGB\_ORDER**](#define-led_strip_set_rgb_order) (R, G, B) (R &lt;&lt; 0 \| G &lt;&lt; 2 \| B &lt;&lt; 4)<br>_Help macro to set pixel RGB color order The default order of the three-color LED strips is GRB. If you have a different order, you can use the macro to set_ `pixel_order`_in_[_**led\_strip\_config\_t**_](#struct-led_strip_config_t)_. The positions are counted from the least significant bit (LSB)._ |

## Functions Documentation

### function `led_strip_clear`
Expand Down Expand Up @@ -178,6 +185,45 @@ Also see `led_strip_set_pixel` if you only want to specify the RGB part of the c
- ESP\_ERR\_INVALID\_ARG: Set RGBW color for a specific pixel failed because of an invalid argument
- ESP\_FAIL: Set RGBW color for a specific pixel failed because other error occurred

## Macros Documentation

### define `LED_STRIP_SET_RGBW_ORDER`

_Help macro to set pixel RGBW color order The default order of the four-color LED strips is GRBW. If you have a different order, you can use the macro to set_ `pixel_order`_in_[_**led\_strip\_config\_t**_](#struct-led_strip_config_t)_. The positions are counted from the least significant bit (LSB)._

```c
#define LED_STRIP_SET_RGBW_ORDER (R, G, B, W) (R << 0 | G << 2 | B << 4 | W << 6)
```
**Parameters:**
- `R` The position of the red channel in the color order.
- `G` The position of the green channel in the color order.
- `B` The position of the blue channel in the color order.
- `W` The position of the white channel in the color order.
**Note:**
The order starts from 0. And the user needs to make sure that all the numbers appear exactly once and are all less than the number of colors per pixel.
### define `LED_STRIP_SET_RGB_ORDER`
_Help macro to set pixel RGB color order The default order of the three-color LED strips is GRB. If you have a different order, you can use the macro to set_ `pixel_order`_in_[_**led\_strip\_config\_t**_](#struct-led_strip_config_t)_. The positions are counted from the least significant bit (LSB)._
```c
#define LED_STRIP_SET_RGB_ORDER (R, G, B) (R << 0 | G << 2 | B << 4)
```

**Parameters:**

- `R` The position of the red channel in the color order.
- `G` The position of the green channel in the color order.
- `B` The position of the blue channel in the color order.

**Note:**

The order starts from 0. And the user needs to make sure that all the numbers appear exactly once and are all less than the number of colors per pixel.

## File include/led_strip_rmt.h

## Structures and Types
Expand Down Expand Up @@ -306,7 +352,6 @@ Although only the MOSI line is used for generating the signal, the whole SPI bus
| Type | Name |
| ---: | :--- |
| 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._ |

Expand All @@ -328,34 +373,24 @@ 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._

Variables:

- struct led\_strip\_config\_t::@2 flags <br>Extra driver flags
- uint8\_t bytes_per_pixel <br>bytes per LED pixel. Should be 3 or 4

- struct led\_strip\_config\_t::@2 flags <br>The order of the pixel color. Use help macro LED\_STRIP\_SET\_RGB\_ORDER or LED\_STRIP\_SET\_RGBW\_ORDER to set. Not set or set to 0 if the default order is used. Extra driver flags

- uint32\_t invert_out <br>Invert output signal

- [**led\_model\_t**](#enum-led_model_t) led_model <br>LED model

- [**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

- uint8\_t pixel_order

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

### typedef `led_strip_handle_t`
Expand Down
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,11 +23,13 @@ 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,
.bytes_per_pixel = 3, // 3 bytes per pixel of the LED strip
.led_model = LED_MODEL_WS2812, // LED strip model
.flags.invert_out = false, // whether to invert the output signal
.pixel_order = LED_STRIP_SET_RGB_ORDER(1, 0, 2), /* The order of the pixel color. Not set or set to 0 if the default order is used.
Here set to the default GRB order to demonstrate usage */
};

// LED strip backend configuration: RMT
Expand Down Expand Up @@ -57,7 +59,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
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,21 +11,23 @@
#include "esp_err.h"

// GPIO assignment
#define LED_STRIP_BLINK_GPIO 2
#define LED_STRIP_GPIO_PIN 27
// Numbers of the LED in the strip
#define LED_STRIP_LED_NUMBERS 24
#define LED_STRIP_LED_COUNT 1

static const char *TAG = "example";

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,
.bytes_per_pixel = 3, // 3 bytes per pixel of the LED strip
.led_model = LED_MODEL_WS2812, // LED strip model
.flags.invert_out = false, // whether to invert the output signal
.pixel_order = LED_STRIP_SET_RGB_ORDER(1, 0, 2), /* The order of the pixel color. Not set or set to 0 if the default order is used.
Here set to the default GRB order to demonstrate usage */
};

// LED strip backend configuration: SPI
Expand All @@ -51,7 +53,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
2 changes: 1 addition & 1 deletion led_strip/idf_component.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: "2.5.5"
version: "2.5.6"
description: Driver for Addressable LED Strip (WS2812, etc)
url: https://github.com/espressif/idf-extra-components/tree/master/led_strip
dependencies:
Expand Down
25 changes: 24 additions & 1 deletion led_strip/include/led_strip.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -18,6 +18,29 @@
extern "C" {
#endif

/**
* @brief Help macro to set pixel RGB color order
* The default order of the three-color LED strips is GRB. If you have a different order, you can use the macro to set `pixel_order` in led_strip_config_t.
* The positions are counted from the least significant bit (LSB).
* @param R The position of the red channel in the color order.
* @param G The position of the green channel in the color order.
* @param B The position of the blue channel in the color order.
* @note The order starts from 0. And the user needs to make sure that all the numbers appear exactly once and are all less than the number of colors per pixel.
*/
#define LED_STRIP_SET_RGB_ORDER(R, G, B) (R << 0 | G << 2 | B << 4)

/**
* @brief Help macro to set pixel RGBW color order
* The default order of the four-color LED strips is GRBW. If you have a different order, you can use the macro to set `pixel_order` in led_strip_config_t.
* The positions are counted from the least significant bit (LSB).
* @param R The position of the red channel in the color order.
* @param G The position of the green channel in the color order.
* @param B The position of the blue channel in the color order.
* @param W The position of the white channel in the color order.
* @note The order starts from 0. And the user needs to make sure that all the numbers appear exactly once and are all less than the number of colors per pixel.
*/
#define LED_STRIP_SET_RGBW_ORDER(R, G, B, W) (R << 0 | G << 2 | B << 4 | W << 6)

/**
* @brief Set RGB for a specific pixel
*
Expand Down
17 changes: 5 additions & 12 deletions led_strip/include/led_strip_types.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -11,15 +11,6 @@
extern "C" {
#endif

/**
* @brief LED strip pixel format
*/
typedef enum {
LED_PIXEL_FORMAT_GRB, /*!< Pixel format: GRB */
LED_PIXEL_FORMAT_GRBW, /*!< Pixel format: GRBW */
LED_PIXEL_FORMAT_INVALID /*!< Invalid pixel format */
} led_pixel_format_t;

/**
* @brief LED strip model
* @note Different led model may have different timing parameters, so we need to distinguish them.
Expand All @@ -41,9 +32,11 @@ typedef struct led_strip_t *led_strip_handle_t;
typedef struct {
int strip_gpio_num; /*!< GPIO number that used by LED strip */
uint32_t max_leds; /*!< Maximum LEDs in a single strip */
led_pixel_format_t led_pixel_format; /*!< LED pixel format */
uint8_t bytes_per_pixel; /*!< bytes per LED pixel. Should be 3 or 4 */
led_model_t led_model; /*!< LED model */

uint8_t pixel_order; /*! The order of the pixel color.
Use help macro LED_STRIP_SET_RGB_ORDER or LED_STRIP_SET_RGBW_ORDER to set.
Not set or set to 0 if the default order is used. */
struct {
uint32_t invert_out: 1; /*!< Invert output signal */
} flags; /*!< Extra driver flags */
Expand Down
37 changes: 37 additions & 0 deletions led_strip/src/led_strip_common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include "esp_log.h"
#include "esp_check.h"
#include "esp_bit_defs.h"
#include "led_strip_common.h"

static const char *TAG = "led_strip_common";

esp_err_t led_strip_set_color_order(uint8_t *led_pixel_offset, const uint8_t pixel_order, const uint8_t bytes_per_pixel)
{
if (pixel_order) {
uint8_t r_order = (pixel_order >> 0) & 0x03;
uint8_t g_order = (pixel_order >> 2) & 0x03;
uint8_t b_order = (pixel_order >> 4) & 0x03;
uint8_t w_order = (pixel_order >> 6) & 0x03;
uint8_t mask = bytes_per_pixel == 3 ? BIT(r_order) | BIT(g_order) | BIT(b_order) : BIT(r_order) | BIT(g_order) | BIT(b_order) | BIT(w_order);
// Check for invalid values
ESP_RETURN_ON_FALSE(__builtin_popcount(mask) == bytes_per_pixel && r_order < bytes_per_pixel && g_order < bytes_per_pixel && b_order < bytes_per_pixel && w_order < bytes_per_pixel,
ESP_ERR_INVALID_ARG, TAG, "invalid order argument");
led_pixel_offset[LED_PIXEL_INDEX_RED] = r_order;
led_pixel_offset[LED_PIXEL_INDEX_GREEN] = g_order;
led_pixel_offset[LED_PIXEL_INDEX_BLUE] = b_order;
led_pixel_offset[LED_PIXEL_INDEX_WHITE] = w_order;
} else {
// If pixel_order is not set, set default GRB(GRBW) order as fallback path
led_pixel_offset[LED_PIXEL_INDEX_RED] = 1;
led_pixel_offset[LED_PIXEL_INDEX_GREEN] = 0;
led_pixel_offset[LED_PIXEL_INDEX_BLUE] = 2;
led_pixel_offset[LED_PIXEL_INDEX_WHITE] = 3;
}
return ESP_OK;
}
41 changes: 41 additions & 0 deletions led_strip/src/led_strip_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

#include <stdint.h>
#include "esp_err.h"
#include "led_strip_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief LED strip pixel order index
*/
typedef enum {
LED_PIXEL_INDEX_RED, /*!< Red pixel index */
LED_PIXEL_INDEX_GREEN, /*!< Green pixel index */
LED_PIXEL_INDEX_BLUE, /*!< Blue pixel index */
LED_PIXEL_INDEX_WHITE, /*!< White pixel index */
LED_PIXEL_INDEX_MAX /*!< Max pixel index */
} led_pixel_order_index_t;

/**
* @brief Set LED color order
*
* @param led_pixel_offset Each pixel's offset
* @param pixel_order `pixel_order` parameter in LED strip configuration
* @param bytes_per_pixel bytes per pixel
* @return
* - ESP_OK: Set LED color order successfully
* - ESP_ERR_INVALID_ARG: Set LED color order failed because of invalid argument
*/
esp_err_t led_strip_set_color_order(uint8_t *led_pixel_offset, const uint8_t pixel_order, const uint8_t bytes_per_pixel);

#ifdef __cplusplus
}
#endif
Loading

0 comments on commit 743e8aa

Please sign in to comment.