Skip to content

Commit a77d1c5

Browse files
committed
feat(led_strip): Support RGB pixel order
1 parent d9b31d9 commit a77d1c5

File tree

8 files changed

+134
-56
lines changed

8 files changed

+134
-56
lines changed

led_strip/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
include($ENV{IDF_PATH}/tools/cmake/version.cmake)
22

3-
set(srcs "src/led_strip_api.c")
3+
set(srcs "src/led_strip_api.c" "src/led_strip_common.c")
44

55
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.0")
66
if(CONFIG_SOC_RMT_SUPPORTED)

led_strip/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: "2.5.4"
1+
version: "2.5.5"
22
description: Driver for Addressable LED Strip (WS2812, etc)
33
url: https://github.com/espressif/idf-extra-components/tree/master/led_strip
44
dependencies:
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
#pragma once
7+
8+
#include <stdint.h>
9+
#include "esp_err.h"
10+
#include "led_strip_types.h"
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
#define LED_PIXEL_FORMAT_3COLORS_MAX LED_PIXEL_FORMAT_RGB
17+
18+
/**
19+
* @brief LED strip pixel order index
20+
*/
21+
typedef enum {
22+
LED_PIXEL_INDEX_RED, /*!< Red pixel index */
23+
LED_PIXEL_INDEX_GREEN, /*!< Green pixel index */
24+
LED_PIXEL_INDEX_BLUE, /*!< Blue pixel index */
25+
LED_PIXEL_INDEX_WHITE, /*!< White pixel index */
26+
LED_PIXEL_INDEX_MAX /*!< Max pixel index */
27+
} led_pixel_order_index_t;
28+
29+
/**
30+
* @brief Config LED pixel order
31+
*
32+
* @param led_pixel_offset Each pixel's offset
33+
* @param led_pixel_format Input LED strip pixel format
34+
* @return
35+
* - ESP_OK: Config LED pixel order successfully
36+
* - ESP_ERR_INVALID_ARG: Config LED pixel order failed because of invalid argument
37+
* - ESP_FAIL: Config LED pixel order failed because some other error
38+
*/
39+
esp_err_t led_strip_config_pixel_order(uint8_t *led_pixel_offset, led_pixel_format_t led_pixel_format);
40+
41+
#ifdef __cplusplus
42+
}
43+
#endif

led_strip/include/led_strip_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ extern "C" {
1616
*/
1717
typedef enum {
1818
LED_PIXEL_FORMAT_GRB, /*!< Pixel format: GRB */
19+
LED_PIXEL_FORMAT_RGB, /*!< Pixel format: RGB */
1920
LED_PIXEL_FORMAT_GRBW, /*!< Pixel format: GRBW */
21+
LED_PIXEL_FORMAT_RGBW, /*!< Pixel format: RGBW */
2022
LED_PIXEL_FORMAT_INVALID /*!< Invalid pixel format */
2123
} led_pixel_format_t;
2224

led_strip/src/led_strip_common.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include <stdbool.h>
2+
#include "esp_log.h"
3+
#include "esp_check.h"
4+
#include "esp_private/led_strip_common.h"
5+
6+
static const char *TAG = "led_strip_common";
7+
esp_err_t led_strip_config_pixel_order(uint8_t *led_pixel_offset, led_pixel_format_t led_pixel_format)
8+
{
9+
ESP_RETURN_ON_FALSE(led_pixel_offset, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
10+
switch (led_pixel_format) {
11+
case LED_PIXEL_FORMAT_GRB:
12+
led_pixel_offset[0] = 1;
13+
led_pixel_offset[1] = 0;
14+
led_pixel_offset[2] = 2;
15+
break;
16+
case LED_PIXEL_FORMAT_RGB:
17+
led_pixel_offset[0] = 0;
18+
led_pixel_offset[1] = 1;
19+
led_pixel_offset[2] = 2;
20+
break;
21+
case LED_PIXEL_FORMAT_GRBW:
22+
led_pixel_offset[0] = 0;
23+
led_pixel_offset[1] = 2;
24+
led_pixel_offset[2] = 1;
25+
led_pixel_offset[3] = 3;
26+
break;
27+
case LED_PIXEL_FORMAT_RGBW:
28+
led_pixel_offset[0] = 0;
29+
led_pixel_offset[1] = 1;
30+
led_pixel_offset[2] = 2;
31+
led_pixel_offset[3] = 3;
32+
break;
33+
default:
34+
ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_ARG, TAG, "invalid pixel format");
35+
}
36+
return ESP_OK;
37+
}

led_strip/src/led_strip_rmt_dev.c

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "led_strip.h"
1313
#include "led_strip_interface.h"
1414
#include "led_strip_rmt_encoder.h"
15+
#include "esp_private/led_strip_common.h"
1516

1617
#define LED_STRIP_RMT_DEFAULT_RESOLUTION 10000000 // 10MHz resolution
1718
#define LED_STRIP_RMT_DEFAULT_TRANS_QUEUE_SIZE 4
@@ -30,6 +31,7 @@ typedef struct {
3031
rmt_encoder_handle_t strip_encoder;
3132
uint32_t strip_len;
3233
uint8_t bytes_per_pixel;
34+
uint8_t led_pixel_offset[LED_PIXEL_INDEX_MAX];
3335
uint8_t pixel_buf[];
3436
} led_strip_rmt_obj;
3537

@@ -38,12 +40,15 @@ static esp_err_t led_strip_rmt_set_pixel(led_strip_t *strip, uint32_t index, uin
3840
led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base);
3941
ESP_RETURN_ON_FALSE(index < rmt_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of maximum number of LEDs");
4042
uint32_t start = index * rmt_strip->bytes_per_pixel;
41-
// In thr order of GRB, as LED strip like WS2812 sends out pixels in this order
42-
rmt_strip->pixel_buf[start + 0] = green & 0xFF;
43-
rmt_strip->pixel_buf[start + 1] = red & 0xFF;
44-
rmt_strip->pixel_buf[start + 2] = blue & 0xFF;
43+
uint8_t *pixel_buf = rmt_strip->pixel_buf;
44+
uint8_t *offset = rmt_strip->led_pixel_offset;
45+
// Support all kinds of pixel order
46+
pixel_buf[start + offset[LED_PIXEL_INDEX_RED]] = red & 0xFF;
47+
pixel_buf[start + offset[LED_PIXEL_INDEX_GREEN]] = green & 0xFF;
48+
pixel_buf[start + offset[LED_PIXEL_INDEX_BLUE]] = blue & 0xFF;
49+
4550
if (rmt_strip->bytes_per_pixel > 3) {
46-
rmt_strip->pixel_buf[start + 3] = 0;
51+
pixel_buf[start + offset[LED_PIXEL_INDEX_WHITE]] = 0;
4752
}
4853
return ESP_OK;
4954
}
@@ -53,12 +58,14 @@ static esp_err_t led_strip_rmt_set_pixel_rgbw(led_strip_t *strip, uint32_t index
5358
led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base);
5459
ESP_RETURN_ON_FALSE(index < rmt_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of maximum number of LEDs");
5560
ESP_RETURN_ON_FALSE(rmt_strip->bytes_per_pixel == 4, ESP_ERR_INVALID_ARG, TAG, "wrong LED pixel format, expected 4 bytes per pixel");
56-
uint8_t *buf_start = rmt_strip->pixel_buf + index * 4;
61+
uint32_t start = index * rmt_strip->bytes_per_pixel;
62+
uint8_t *pixel_buf = rmt_strip->pixel_buf;
63+
uint8_t *offset = rmt_strip->led_pixel_offset;
5764
// SK6812 component order is GRBW
58-
*buf_start = green & 0xFF;
59-
*++buf_start = red & 0xFF;
60-
*++buf_start = blue & 0xFF;
61-
*++buf_start = white & 0xFF;
65+
pixel_buf[start + offset[LED_PIXEL_INDEX_RED]] = red & 0xFF;
66+
pixel_buf[start + offset[LED_PIXEL_INDEX_GREEN]] = green & 0xFF;
67+
pixel_buf[start + offset[LED_PIXEL_INDEX_BLUE]] = blue & 0xFF;
68+
pixel_buf[start + offset[LED_PIXEL_INDEX_WHITE]] = white & 0xFF;
6269
return ESP_OK;
6370
}
6471

@@ -100,14 +107,7 @@ esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const l
100107
esp_err_t ret = ESP_OK;
101108
ESP_GOTO_ON_FALSE(led_config && rmt_config && ret_strip, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
102109
ESP_GOTO_ON_FALSE(led_config->led_pixel_format < LED_PIXEL_FORMAT_INVALID, ESP_ERR_INVALID_ARG, err, TAG, "invalid led_pixel_format");
103-
uint8_t bytes_per_pixel = 3;
104-
if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRBW) {
105-
bytes_per_pixel = 4;
106-
} else if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRB) {
107-
bytes_per_pixel = 3;
108-
} else {
109-
assert(false);
110-
}
110+
uint8_t bytes_per_pixel = led_config->led_pixel_format <= LED_PIXEL_FORMAT_3COLORS_MAX ? 3 : 4;
111111
rmt_strip = calloc(1, sizeof(led_strip_rmt_obj) + led_config->max_leds * bytes_per_pixel);
112112
ESP_GOTO_ON_FALSE(rmt_strip, ESP_ERR_NO_MEM, err, TAG, "no mem for rmt strip");
113113
uint32_t resolution = rmt_config->resolution_hz ? rmt_config->resolution_hz : LED_STRIP_RMT_DEFAULT_RESOLUTION;
@@ -138,7 +138,7 @@ esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const l
138138
.led_model = led_config->led_model
139139
};
140140
ESP_GOTO_ON_ERROR(rmt_new_led_strip_encoder(&strip_encoder_conf, &rmt_strip->strip_encoder), err, TAG, "create LED strip encoder failed");
141-
141+
ESP_GOTO_ON_ERROR(led_strip_config_pixel_order(rmt_strip->led_pixel_offset, led_config->led_pixel_format), err, TAG, "config pixel order failed");
142142

143143
rmt_strip->bytes_per_pixel = bytes_per_pixel;
144144
rmt_strip->strip_len = led_config->max_leds;

led_strip/src/led_strip_rmt_dev_idf4.c

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "driver/rmt.h"
1212
#include "led_strip.h"
1313
#include "led_strip_interface.h"
14+
#include "esp_private/led_strip_common.h"
1415

1516
static const char *TAG = "led_strip_rmt";
1617

@@ -43,6 +44,7 @@ typedef struct {
4344
rmt_channel_t rmt_channel;
4445
uint32_t strip_len;
4546
uint8_t bytes_per_pixel;
47+
uint8_t led_pixel_offset[LED_PIXEL_INDEX_MAX];
4648
uint8_t buffer[0];
4749
} led_strip_rmt_obj;
4850

@@ -83,12 +85,14 @@ static esp_err_t led_strip_rmt_set_pixel(led_strip_t *strip, uint32_t index, uin
8385
led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base);
8486
ESP_RETURN_ON_FALSE(index < rmt_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of the maximum number of leds");
8587
uint32_t start = index * rmt_strip->bytes_per_pixel;
86-
// In thr order of GRB
87-
rmt_strip->buffer[start + 0] = green & 0xFF;
88-
rmt_strip->buffer[start + 1] = red & 0xFF;
89-
rmt_strip->buffer[start + 2] = blue & 0xFF;
88+
uint8_t *pixel_buf = rmt_strip->buffer;
89+
uint8_t *offset = rmt_strip->led_pixel_offset;
90+
// Support all kinds of pixel order
91+
pixel_buf[start + offset[LED_PIXEL_INDEX_RED]] = red & 0xFF;
92+
pixel_buf[start + offset[LED_PIXEL_INDEX_GREEN]] = green & 0xFF;
93+
pixel_buf[start + offset[LED_PIXEL_INDEX_BLUE]] = blue & 0xFF;
9094
if (rmt_strip->bytes_per_pixel > 3) {
91-
rmt_strip->buffer[start + 3] = 0;
95+
rmt_strip->buffer[start + offset[LED_PIXEL_INDEX_WHITE]] = 0;
9296
}
9397
return ESP_OK;
9498
}
@@ -125,16 +129,7 @@ esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const l
125129
ESP_RETURN_ON_FALSE(led_config && dev_config && ret_strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
126130
ESP_RETURN_ON_FALSE(led_config->led_pixel_format < LED_PIXEL_FORMAT_INVALID, ESP_ERR_INVALID_ARG, TAG, "invalid led_pixel_format");
127131
ESP_RETURN_ON_FALSE(dev_config->flags.with_dma == 0, ESP_ERR_NOT_SUPPORTED, TAG, "DMA is not supported");
128-
129-
uint8_t bytes_per_pixel = 3;
130-
if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRBW) {
131-
bytes_per_pixel = 4;
132-
} else if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRB) {
133-
bytes_per_pixel = 3;
134-
} else {
135-
assert(false);
136-
}
137-
132+
uint8_t bytes_per_pixel = led_config->led_pixel_format <= LED_PIXEL_FORMAT_3COLORS_MAX ? 3 : 4;
138133
// allocate memory for led_strip object
139134
rmt_strip = calloc(1, sizeof(led_strip_rmt_obj) + led_config->max_leds * bytes_per_pixel);
140135
ESP_RETURN_ON_FALSE(rmt_strip, ESP_ERR_NO_MEM, TAG, "request memory for les_strip failed");
@@ -174,6 +169,7 @@ esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const l
174169

175170
// adapter to translates the LES strip date frame into RMT symbols
176171
rmt_translator_init((rmt_channel_t)dev_config->rmt_channel, ws2812_rmt_adapter);
172+
ESP_GOTO_ON_ERROR(led_strip_config_pixel_order(rmt_strip->led_pixel_offset, led_config->led_pixel_format), err, TAG, "config pixel order failed");
177173

178174
rmt_strip->bytes_per_pixel = bytes_per_pixel;
179175
rmt_strip->rmt_channel = (rmt_channel_t)dev_config->rmt_channel;

led_strip/src/led_strip_spi_dev.c

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
#include "esp_check.h"
1111
#include "esp_rom_gpio.h"
1212
#include "soc/spi_periph.h"
13+
#include "hal/spi_hal.h"
1314
#include "led_strip.h"
1415
#include "led_strip_interface.h"
15-
#include "hal/spi_hal.h"
16+
#include "esp_private/led_strip_common.h"
1617

1718
#define LED_STRIP_SPI_DEFAULT_RESOLUTION (2.5 * 1000 * 1000) // 2.5MHz resolution
1819
#define LED_STRIP_SPI_DEFAULT_TRANS_QUEUE_SIZE 4
@@ -28,6 +29,7 @@ typedef struct {
2829
spi_device_handle_t spi_device;
2930
uint32_t strip_len;
3031
uint8_t bytes_per_pixel;
32+
uint8_t led_pixel_offset[LED_PIXEL_INDEX_MAX];
3133
uint8_t pixel_buf[];
3234
} led_strip_spi_obj;
3335

@@ -51,14 +53,16 @@ static esp_err_t led_strip_spi_set_pixel(led_strip_t *strip, uint32_t index, uin
5153
{
5254
led_strip_spi_obj *spi_strip = __containerof(strip, led_strip_spi_obj, base);
5355
ESP_RETURN_ON_FALSE(index < spi_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of maximum number of LEDs");
54-
// LED_PIXEL_FORMAT_GRB takes 72bits(9bytes)
56+
// 3 pixels take 72bits(9bytes)
5557
uint32_t start = index * spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE;
56-
memset(spi_strip->pixel_buf + start, 0, spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE);
57-
__led_strip_spi_bit(green, &spi_strip->pixel_buf[start]);
58-
__led_strip_spi_bit(red, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE]);
59-
__led_strip_spi_bit(blue, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * 2]);
58+
uint8_t *pixel_buf = spi_strip->pixel_buf;
59+
uint8_t *offset = spi_strip->led_pixel_offset;
60+
memset(pixel_buf + start, 0, spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE);
61+
__led_strip_spi_bit(red, &pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * offset[LED_PIXEL_INDEX_RED]]);
62+
__led_strip_spi_bit(green, &pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * offset[LED_PIXEL_INDEX_GREEN]]);
63+
__led_strip_spi_bit(blue, &pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * offset[LED_PIXEL_INDEX_BLUE]]);
6064
if (spi_strip->bytes_per_pixel > 3) {
61-
__led_strip_spi_bit(0, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * 3]);
65+
__led_strip_spi_bit(0, &pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * LED_PIXEL_INDEX_WHITE]);
6266
}
6367
return ESP_OK;
6468
}
@@ -70,12 +74,14 @@ static esp_err_t led_strip_spi_set_pixel_rgbw(led_strip_t *strip, uint32_t index
7074
ESP_RETURN_ON_FALSE(spi_strip->bytes_per_pixel == 4, ESP_ERR_INVALID_ARG, TAG, "wrong LED pixel format, expected 4 bytes per pixel");
7175
// LED_PIXEL_FORMAT_GRBW takes 96bits(12bytes)
7276
uint32_t start = index * spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE;
77+
uint8_t *pixel_buf = spi_strip->pixel_buf;
78+
uint8_t *offset = spi_strip->led_pixel_offset;
7379
// SK6812 component order is GRBW
74-
memset(spi_strip->pixel_buf + start, 0, spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE);
75-
__led_strip_spi_bit(green, &spi_strip->pixel_buf[start]);
76-
__led_strip_spi_bit(red, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE]);
77-
__led_strip_spi_bit(blue, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * 2]);
78-
__led_strip_spi_bit(white, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * 3]);
80+
memset(pixel_buf + start, 0, spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE);
81+
__led_strip_spi_bit(red, &pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * offset[LED_PIXEL_INDEX_RED]]);
82+
__led_strip_spi_bit(green, &pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * offset[LED_PIXEL_INDEX_GREEN]]);
83+
__led_strip_spi_bit(blue, &pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * offset[LED_PIXEL_INDEX_BLUE]]);
84+
__led_strip_spi_bit(white, &pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * offset[LED_PIXEL_INDEX_WHITE]]);
7985

8086
return ESP_OK;
8187
}
@@ -125,14 +131,7 @@ esp_err_t led_strip_new_spi_device(const led_strip_config_t *led_config, const l
125131
esp_err_t ret = ESP_OK;
126132
ESP_GOTO_ON_FALSE(led_config && spi_config && ret_strip, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
127133
ESP_GOTO_ON_FALSE(led_config->led_pixel_format < LED_PIXEL_FORMAT_INVALID, ESP_ERR_INVALID_ARG, err, TAG, "invalid led_pixel_format");
128-
uint8_t bytes_per_pixel = 3;
129-
if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRBW) {
130-
bytes_per_pixel = 4;
131-
} else if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRB) {
132-
bytes_per_pixel = 3;
133-
} else {
134-
assert(false);
135-
}
134+
uint8_t bytes_per_pixel = led_config->led_pixel_format <= LED_PIXEL_FORMAT_3COLORS_MAX ? 3 : 4;
136135
uint32_t mem_caps = MALLOC_CAP_DEFAULT;
137136
if (spi_config->flags.with_dma) {
138137
// DMA buffer must be placed in internal SRAM
@@ -186,6 +185,7 @@ esp_err_t led_strip_new_spi_device(const led_strip_config_t *led_config, const l
186185
// clock_resolution between 2.2MHz to 2.8MHz is supported
187186
ESP_GOTO_ON_FALSE((clock_resolution_khz < LED_STRIP_SPI_DEFAULT_RESOLUTION / 1000 + 300) && (clock_resolution_khz > LED_STRIP_SPI_DEFAULT_RESOLUTION / 1000 - 300), ESP_ERR_NOT_SUPPORTED, err,
188187
TAG, "unsupported clock resolution:%dKHz", clock_resolution_khz);
188+
ESP_GOTO_ON_ERROR(led_strip_config_pixel_order(spi_strip->led_pixel_offset, led_config->led_pixel_format), err, TAG, "config pixel order failed");
189189

190190
spi_strip->bytes_per_pixel = bytes_per_pixel;
191191
spi_strip->strip_len = led_config->max_leds;

0 commit comments

Comments
 (0)