From 65e14f5097d1c1b58ae0c94947f4db6db58b78ed Mon Sep 17 00:00:00 2001 From: Chen Jichang Date: Thu, 20 Jun 2024 13:52:52 +0800 Subject: [PATCH] feat(led_strip): Support more pixel orders of 3 colors --- led_strip/idf_component.yml | 2 +- led_strip/include/led_strip_types.h | 12 ++++-- led_strip/src/led_strip_rmt_dev.c | 52 ++++++++++++++++++++++---- led_strip/src/led_strip_rmt_dev_idf4.c | 51 +++++++++++++++++++++---- led_strip/src/led_strip_spi_dev.c | 51 +++++++++++++++++++++---- 5 files changed, 142 insertions(+), 26 deletions(-) diff --git a/led_strip/idf_component.yml b/led_strip/idf_component.yml index deda1bc743..4928449549 100644 --- a/led_strip/idf_component.yml +++ b/led_strip/idf_component.yml @@ -1,4 +1,4 @@ -version: "2.5.4" +version: "2.5.5" description: Driver for Addressable LED Strip (WS2812, etc) url: https://github.com/espressif/idf-extra-components/tree/master/led_strip dependencies: diff --git a/led_strip/include/led_strip_types.h b/led_strip/include/led_strip_types.h index 691f0bc394..2e83ae916f 100644 --- a/led_strip/include/led_strip_types.h +++ b/led_strip/include/led_strip_types.h @@ -15,9 +15,15 @@ extern "C" { * @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_GRB, /*!< Pixel format: GRB */ + LED_PIXEL_FORMAT_GBR, /*!< Pixel format: GBR */ + LED_PIXEL_FORMAT_RGB, /*!< Pixel format: RGB */ + LED_PIXEL_FORMAT_RBG, /*!< Pixel format: RBG */ + LED_PIXEL_FORMAT_BGR, /*!< Pixel format: BGR */ + LED_PIXEL_FORMAT_BRG, /*!< Pixel format: BRG */ + LED_PIXEL_FORMAT_3COLORS_MAX, /*!< Pixel format max of 3 colors */ + LED_PIXEL_FORMAT_GRBW, /*!< Pixel format: GRBW */ + LED_PIXEL_FORMAT_INVALID /*!< Invalid pixel format */ } led_pixel_format_t; /** diff --git a/led_strip/src/led_strip_rmt_dev.c b/led_strip/src/led_strip_rmt_dev.c index 1cbf0e45ae..2d5c4a9683 100644 --- a/led_strip/src/led_strip_rmt_dev.c +++ b/led_strip/src/led_strip_rmt_dev.c @@ -28,6 +28,7 @@ typedef struct { led_strip_t base; rmt_channel_handle_t rmt_chan; rmt_encoder_handle_t strip_encoder; + led_pixel_format_t led_pixel_format; uint32_t strip_len; uint8_t bytes_per_pixel; uint8_t pixel_buf[]; @@ -38,10 +39,45 @@ static esp_err_t led_strip_rmt_set_pixel(led_strip_t *strip, uint32_t index, uin led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base); ESP_RETURN_ON_FALSE(index < rmt_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of maximum number of LEDs"); uint32_t start = index * rmt_strip->bytes_per_pixel; - // In thr order of GRB, as LED strip like WS2812 sends out pixels in this order - rmt_strip->pixel_buf[start + 0] = green & 0xFF; - rmt_strip->pixel_buf[start + 1] = red & 0xFF; - rmt_strip->pixel_buf[start + 2] = blue & 0xFF; + // Support all kinds of pixel order + uint8_t r = 0, b = 0, g = 0; + switch (rmt_strip->led_pixel_format) { + case LED_PIXEL_FORMAT_GRB: + r = 1; + g = 0; + b = 2; + break; + case LED_PIXEL_FORMAT_GBR: + r = 2; + g = 0; + b = 1; + break; + case LED_PIXEL_FORMAT_RGB: + r = 0; + g = 1; + b = 2; + break; + case LED_PIXEL_FORMAT_RBG: + r = 0; + g = 2; + b = 1; + break; + case LED_PIXEL_FORMAT_BGR: + r = 2; + g = 1; + b = 0; + break; + case LED_PIXEL_FORMAT_BRG: + r = 1; + g = 2; + b = 0; + break; + default: + ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_ARG, TAG, "invalid pixel format"); + } + rmt_strip->pixel_buf[start + g] = green & 0xFF; + rmt_strip->pixel_buf[start + r] = red & 0xFF; + rmt_strip->pixel_buf[start + b] = blue & 0xFF; if (rmt_strip->bytes_per_pixel > 3) { rmt_strip->pixel_buf[start + 3] = 0; } @@ -101,10 +137,10 @@ esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const l ESP_GOTO_ON_FALSE(led_config && rmt_config && ret_strip, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); ESP_GOTO_ON_FALSE(led_config->led_pixel_format < LED_PIXEL_FORMAT_INVALID, ESP_ERR_INVALID_ARG, err, TAG, "invalid led_pixel_format"); uint8_t bytes_per_pixel = 3; - if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRBW) { - bytes_per_pixel = 4; - } else if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRB) { + if (led_config->led_pixel_format < LED_PIXEL_FORMAT_3COLORS_MAX) { bytes_per_pixel = 3; + } else if (led_config->led_pixel_format > LED_PIXEL_FORMAT_3COLORS_MAX) { + bytes_per_pixel = 4; } else { assert(false); } @@ -139,7 +175,7 @@ esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const l }; ESP_GOTO_ON_ERROR(rmt_new_led_strip_encoder(&strip_encoder_conf, &rmt_strip->strip_encoder), err, TAG, "create LED strip encoder failed"); - + rmt_strip->led_pixel_format = led_config->led_pixel_format; rmt_strip->bytes_per_pixel = bytes_per_pixel; rmt_strip->strip_len = led_config->max_leds; rmt_strip->base.set_pixel = led_strip_rmt_set_pixel; diff --git a/led_strip/src/led_strip_rmt_dev_idf4.c b/led_strip/src/led_strip_rmt_dev_idf4.c index a1067cd7c4..61aa3b55cb 100644 --- a/led_strip/src/led_strip_rmt_dev_idf4.c +++ b/led_strip/src/led_strip_rmt_dev_idf4.c @@ -41,6 +41,7 @@ static uint32_t led_t1l_ticks = 0; typedef struct { led_strip_t base; rmt_channel_t rmt_channel; + led_pixel_format_t led_pixel_format; uint32_t strip_len; uint8_t bytes_per_pixel; uint8_t buffer[0]; @@ -83,10 +84,45 @@ static esp_err_t led_strip_rmt_set_pixel(led_strip_t *strip, uint32_t index, uin led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base); ESP_RETURN_ON_FALSE(index < rmt_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of the maximum number of leds"); uint32_t start = index * rmt_strip->bytes_per_pixel; - // In thr order of GRB - rmt_strip->buffer[start + 0] = green & 0xFF; - rmt_strip->buffer[start + 1] = red & 0xFF; - rmt_strip->buffer[start + 2] = blue & 0xFF; + // Support all kinds of pixel order + uint8_t r = 0, b = 0, g = 0; + switch (rmt_strip->led_pixel_format) { + case LED_PIXEL_FORMAT_GRB: + r = 1; + g = 0; + b = 2; + break; + case LED_PIXEL_FORMAT_GBR: + r = 2; + g = 0; + b = 1; + break; + case LED_PIXEL_FORMAT_RGB: + r = 0; + g = 1; + b = 2; + break; + case LED_PIXEL_FORMAT_RBG: + r = 0; + g = 2; + b = 1; + break; + case LED_PIXEL_FORMAT_BGR: + r = 2; + g = 1; + b = 0; + break; + case LED_PIXEL_FORMAT_BRG: + r = 1; + g = 2; + b = 0; + break; + default: + ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_ARG, TAG, "invalid pixel format"); + } + rmt_strip->pixel_buf[start + g] = green & 0xFF; + rmt_strip->pixel_buf[start + r] = red & 0xFF; + rmt_strip->pixel_buf[start + b] = blue & 0xFF; if (rmt_strip->bytes_per_pixel > 3) { rmt_strip->buffer[start + 3] = 0; } @@ -127,10 +163,10 @@ esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const l ESP_RETURN_ON_FALSE(dev_config->flags.with_dma == 0, ESP_ERR_NOT_SUPPORTED, TAG, "DMA is not supported"); uint8_t bytes_per_pixel = 3; - if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRBW) { - bytes_per_pixel = 4; - } else if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRB) { + if (led_config->led_pixel_format < LED_PIXEL_FORMAT_3COLORS_MAX) { bytes_per_pixel = 3; + } else if (led_config->led_pixel_format > LED_PIXEL_FORMAT_3COLORS_MAX) { + bytes_per_pixel = 4; } else { assert(false); } @@ -175,6 +211,7 @@ esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const l // adapter to translates the LES strip date frame into RMT symbols rmt_translator_init((rmt_channel_t)dev_config->rmt_channel, ws2812_rmt_adapter); + rmt_strip->led_pixel_format = led_config->led_pixel_format; rmt_strip->bytes_per_pixel = bytes_per_pixel; rmt_strip->rmt_channel = (rmt_channel_t)dev_config->rmt_channel; rmt_strip->strip_len = led_config->max_leds; diff --git a/led_strip/src/led_strip_spi_dev.c b/led_strip/src/led_strip_spi_dev.c index 6c66d7e375..fcf884e45b 100644 --- a/led_strip/src/led_strip_spi_dev.c +++ b/led_strip/src/led_strip_spi_dev.c @@ -26,6 +26,7 @@ typedef struct { led_strip_t base; spi_host_device_t spi_host; spi_device_handle_t spi_device; + led_pixel_format_t led_pixel_format; uint32_t strip_len; uint8_t bytes_per_pixel; uint8_t pixel_buf[]; @@ -51,12 +52,47 @@ static esp_err_t led_strip_spi_set_pixel(led_strip_t *strip, uint32_t index, uin { led_strip_spi_obj *spi_strip = __containerof(strip, led_strip_spi_obj, base); ESP_RETURN_ON_FALSE(index < spi_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of maximum number of LEDs"); - // LED_PIXEL_FORMAT_GRB takes 72bits(9bytes) + // 3 pixels take 72bits(9bytes) + uint8_t r = 0, b = 0, g = 0; + switch (spi_strip->led_pixel_format) { + case LED_PIXEL_FORMAT_GRB: + r = 1; + g = 0; + b = 2; + break; + case LED_PIXEL_FORMAT_GBR: + r = 2; + g = 0; + b = 1; + break; + case LED_PIXEL_FORMAT_RGB: + r = 0; + g = 1; + b = 2; + break; + case LED_PIXEL_FORMAT_RBG: + r = 0; + g = 2; + b = 1; + break; + case LED_PIXEL_FORMAT_BGR: + r = 2; + g = 1; + b = 0; + break; + case LED_PIXEL_FORMAT_BRG: + r = 1; + g = 2; + b = 0; + break; + default: + ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_ARG, TAG, "invalid pixel format"); + } uint32_t start = index * spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE; memset(spi_strip->pixel_buf + start, 0, spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE); - __led_strip_spi_bit(green, &spi_strip->pixel_buf[start]); - __led_strip_spi_bit(red, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE]); - __led_strip_spi_bit(blue, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * 2]); + __led_strip_spi_bit(green, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * g]); + __led_strip_spi_bit(red, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * r]); + __led_strip_spi_bit(blue, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * b]); if (spi_strip->bytes_per_pixel > 3) { __led_strip_spi_bit(0, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * 3]); } @@ -126,10 +162,10 @@ esp_err_t led_strip_new_spi_device(const led_strip_config_t *led_config, const l ESP_GOTO_ON_FALSE(led_config && spi_config && ret_strip, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); ESP_GOTO_ON_FALSE(led_config->led_pixel_format < LED_PIXEL_FORMAT_INVALID, ESP_ERR_INVALID_ARG, err, TAG, "invalid led_pixel_format"); uint8_t bytes_per_pixel = 3; - if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRBW) { - bytes_per_pixel = 4; - } else if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRB) { + if (led_config->led_pixel_format < LED_PIXEL_FORMAT_3COLORS_MAX) { bytes_per_pixel = 3; + } else if (led_config->led_pixel_format > LED_PIXEL_FORMAT_3COLORS_MAX) { + bytes_per_pixel = 4; } else { assert(false); } @@ -187,6 +223,7 @@ esp_err_t led_strip_new_spi_device(const led_strip_config_t *led_config, const l 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, TAG, "unsupported clock resolution:%dKHz", clock_resolution_khz); + spi_strip->led_pixel_format = led_config->led_pixel_format; spi_strip->bytes_per_pixel = bytes_per_pixel; spi_strip->strip_len = led_config->max_leds; spi_strip->base.set_pixel = led_strip_spi_set_pixel;