-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* 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 | ||
|
||
#define LED_PIXEL_FORMAT_3COLORS_MAX LED_PIXEL_FORMAT_RGB | ||
|
||
/** | ||
* @brief Config LED pixel order | ||
* | ||
* @param led_pixel_offset Each pixel's offset | ||
* @param led_pixel_format Input LED strip pixel format | ||
* @return | ||
* - ESP_OK: Config LED pixel order successfully | ||
* - ESP_ERR_INVALID_ARG: Config LED pixel order failed because of invalid argument | ||
* - ESP_FAIL: Config LED pixel order failed because some other error | ||
*/ | ||
esp_err_t led_strip_config_pixel_order(uint8_t *led_pixel_offset, led_pixel_format_t led_pixel_format); | ||
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
#ifdef __cplusplus | ||
} | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#include <stdbool.h> | ||
#include "esp_log.h" | ||
#include "esp_check.h" | ||
#include "esp_private/led_strip_common.h" | ||
|
||
static const char *TAG = "led_strip_common"; | ||
esp_err_t led_strip_config_pixel_order(uint8_t *led_pixel_offset, led_pixel_format_t led_pixel_format) | ||
{ | ||
ESP_RETURN_ON_FALSE(led_pixel_offset, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); | ||
This comment has been minimized.
Sorry, something went wrong.
robertlipe
Contributor
|
||
switch (led_pixel_format) { | ||
case LED_PIXEL_FORMAT_GRB: | ||
led_pixel_offset[0] = 1; | ||
led_pixel_offset[1] = 0; | ||
led_pixel_offset[2] = 2; | ||
break; | ||
case LED_PIXEL_FORMAT_RGB: | ||
led_pixel_offset[0] = 0; | ||
led_pixel_offset[1] = 1; | ||
led_pixel_offset[2] = 2; | ||
break; | ||
case LED_PIXEL_FORMAT_GRBW: | ||
led_pixel_offset[0] = 0; | ||
led_pixel_offset[1] = 2; | ||
led_pixel_offset[2] = 1; | ||
led_pixel_offset[3] = 3; | ||
break; | ||
case LED_PIXEL_FORMAT_RGBW: | ||
led_pixel_offset[0] = 0; | ||
led_pixel_offset[1] = 1; | ||
led_pixel_offset[2] = 2; | ||
led_pixel_offset[3] = 3; | ||
break; | ||
default: | ||
ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_ARG, TAG, "invalid pixel format"); | ||
} | ||
return ESP_OK; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
#include "led_strip.h" | ||
#include "led_strip_interface.h" | ||
#include "led_strip_rmt_encoder.h" | ||
#include "esp_private/led_strip_common.h" | ||
|
||
#define LED_STRIP_RMT_DEFAULT_RESOLUTION 10000000 // 10MHz resolution | ||
#define LED_STRIP_RMT_DEFAULT_TRANS_QUEUE_SIZE 4 | ||
|
@@ -30,6 +31,7 @@ typedef struct { | |
rmt_encoder_handle_t strip_encoder; | ||
uint32_t strip_len; | ||
uint8_t bytes_per_pixel; | ||
uint8_t led_pixel_offset[4]; | ||
uint8_t pixel_buf[]; | ||
} led_strip_rmt_obj; | ||
|
||
|
@@ -38,10 +40,10 @@ 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 | ||
rmt_strip->pixel_buf[start + rmt_strip->led_pixel_offset[0]] = red & 0xFF; | ||
rmt_strip->pixel_buf[start + rmt_strip->led_pixel_offset[1]] = green & 0xFF; | ||
rmt_strip->pixel_buf[start + rmt_strip->led_pixel_offset[2]] = blue & 0xFF; | ||
if (rmt_strip->bytes_per_pixel > 3) { | ||
rmt_strip->pixel_buf[start + 3] = 0; | ||
} | ||
|
@@ -53,12 +55,12 @@ static esp_err_t led_strip_rmt_set_pixel_rgbw(led_strip_t *strip, uint32_t index | |
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"); | ||
ESP_RETURN_ON_FALSE(rmt_strip->bytes_per_pixel == 4, ESP_ERR_INVALID_ARG, TAG, "wrong LED pixel format, expected 4 bytes per pixel"); | ||
uint8_t *buf_start = rmt_strip->pixel_buf + index * 4; | ||
uint32_t start = index * rmt_strip->bytes_per_pixel; | ||
// SK6812 component order is GRBW | ||
*buf_start = green & 0xFF; | ||
*++buf_start = red & 0xFF; | ||
*++buf_start = blue & 0xFF; | ||
*++buf_start = white & 0xFF; | ||
rmt_strip->pixel_buf[start + rmt_strip->led_pixel_offset[0]] = red & 0xFF; | ||
This comment has been minimized.
Sorry, something went wrong.
robertlipe
Contributor
|
||
rmt_strip->pixel_buf[start + rmt_strip->led_pixel_offset[1]] = green & 0xFF; | ||
rmt_strip->pixel_buf[start + rmt_strip->led_pixel_offset[2]] = blue & 0xFF; | ||
rmt_strip->pixel_buf[start + rmt_strip->led_pixel_offset[3]] = white & 0xFF; | ||
return ESP_OK; | ||
} | ||
|
||
|
@@ -100,14 +102,7 @@ esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const l | |
esp_err_t ret = ESP_OK; | ||
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) { | ||
bytes_per_pixel = 3; | ||
} else { | ||
assert(false); | ||
} | ||
uint8_t bytes_per_pixel = led_config->led_pixel_format <= LED_PIXEL_FORMAT_3COLORS_MAX ? 3 : 4; | ||
rmt_strip = calloc(1, sizeof(led_strip_rmt_obj) + led_config->max_leds * bytes_per_pixel); | ||
ESP_GOTO_ON_FALSE(rmt_strip, ESP_ERR_NO_MEM, err, TAG, "no mem for rmt strip"); | ||
uint32_t resolution = rmt_config->resolution_hz ? rmt_config->resolution_hz : LED_STRIP_RMT_DEFAULT_RESOLUTION; | ||
|
@@ -138,7 +133,7 @@ esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const l | |
.led_model = led_config->led_model | ||
}; | ||
ESP_GOTO_ON_ERROR(rmt_new_led_strip_encoder(&strip_encoder_conf, &rmt_strip->strip_encoder), err, TAG, "create LED strip encoder failed"); | ||
|
||
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"); | ||
|
||
rmt_strip->bytes_per_pixel = bytes_per_pixel; | ||
rmt_strip->strip_len = led_config->max_leds; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ | |
#include "driver/rmt.h" | ||
#include "led_strip.h" | ||
#include "led_strip_interface.h" | ||
#include "esp_private/led_strip_common.h" | ||
|
||
static const char *TAG = "led_strip_rmt"; | ||
|
||
|
@@ -43,6 +44,7 @@ typedef struct { | |
rmt_channel_t rmt_channel; | ||
uint32_t strip_len; | ||
uint8_t bytes_per_pixel; | ||
uint8_t led_pixel_offset[4]; | ||
This comment has been minimized.
Sorry, something went wrong.
robertlipe
Contributor
|
||
uint8_t buffer[0]; | ||
} led_strip_rmt_obj; | ||
|
||
|
@@ -83,10 +85,10 @@ 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 | ||
rmt_strip->buffer[start + rmt_strip->led_pixel_offset[0]] = red & 0xFF; | ||
rmt_strip->buffer[start + rmt_strip->led_pixel_offset[1]] = green & 0xFF; | ||
rmt_strip->buffer[start + rmt_strip->led_pixel_offset[2]] = blue & 0xFF; | ||
if (rmt_strip->bytes_per_pixel > 3) { | ||
rmt_strip->buffer[start + 3] = 0; | ||
} | ||
|
@@ -125,16 +127,7 @@ esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const l | |
ESP_RETURN_ON_FALSE(led_config && dev_config && ret_strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); | ||
ESP_RETURN_ON_FALSE(led_config->led_pixel_format < LED_PIXEL_FORMAT_INVALID, ESP_ERR_INVALID_ARG, TAG, "invalid led_pixel_format"); | ||
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) { | ||
bytes_per_pixel = 3; | ||
} else { | ||
assert(false); | ||
} | ||
|
||
uint8_t bytes_per_pixel = led_config->led_pixel_format <= LED_PIXEL_FORMAT_3COLORS_MAX ? 3 : 4; | ||
// allocate memory for led_strip object | ||
rmt_strip = calloc(1, sizeof(led_strip_rmt_obj) + led_config->max_leds * bytes_per_pixel); | ||
ESP_RETURN_ON_FALSE(rmt_strip, ESP_ERR_NO_MEM, TAG, "request memory for les_strip failed"); | ||
|
@@ -174,6 +167,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); | ||
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"); | ||
|
||
rmt_strip->bytes_per_pixel = bytes_per_pixel; | ||
rmt_strip->rmt_channel = (rmt_channel_t)dev_config->rmt_channel; | ||
|
1 comment
on commit ee682b8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Firstly: thank you!
This perfectly captured my feedback. I'm very happy with the result and if I had an "approve" button instead of "comment" button, I'd press it. It's a clear step forward, clean, maintainable. I like it.
With my head around the whole PR, I did see one very small opportunity that may or may not be worth taking, but this should totally be able to saturate the busses so it's unlikely to matter.
Everything I mentioned above is so tiny that I'd respect you no less if you just committed this as-is. It's good. The additional stuff is to help my understanding or possibly make future changes easier. If you'd like me to do it instead (i.e., someone with approval power thinks it's worth doing, but you don't want to do it), I'll pick up any subset of this feedback and submit it in a PR myself. I don't intend to ask for infinite changes in a PR.
I'd be pleased with this incorporated with or without any of the feedback in this round.
Thank you!
This symbol will leak into user namespace. Maybe that's just the norm with C applications and is accepted risk, but now my (totally not contrived :-) program that #includes your public header and has a global bool named "led_strip_config_pixel_order" (to show that I've placed an order for a config pixel, of course... I said I'm reaching) will fail to build.
If you have convention of calling this _espressif_private_led_strip_config_pixel_order() or something, that would be better.
However, I thnk this symbol is long enough that the real world likelihood of conflict is zero. It's absolutely a tiny point.