1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-17 13:25:30 +03:00

Add ledstrip_grb_rgb setting (GRB or RGB) to handle WS2811 or WS2812 … (#5255)

* Add ledstrip_grb_rgb setting (GRB or RGB) to handle WS2811 or WS2812 LED drivers

* Rename setting lookup table to lookupLedStripPackingOrder

* Fix call to ws2811UpdateStrip

* Fix unit test

* Use ledStripFormatRGB_e enumeration for RGB packing format

* Fix unit test

* Whoops. Make ledStripFormatRGB_e match lookupLedStripFormatRGB

* Applied review feedback

* Add documentation of ledstrip_grb_rgb
This commit is contained in:
SteveCEvans 2018-03-05 20:39:14 +00:00 committed by Michael Keller
parent 94f06e1e05
commit 0430fcb67d
8 changed files with 77 additions and 13 deletions

View file

@ -38,6 +38,26 @@ It could be possible to be able to specify the timings required via CLI if users
* [Adafruit NeoPixel Stick](https://www.adafruit.com/products/1426) (works well)
* Measured current consumption in all white mode ~ 350 mA.
### WS2811 vs WS2812
The [WS2811](https://cdn-shop.adafruit.com/datasheets/WS2811.pdf) is a LED driver IC which is connected to an RGB LED. It accepts data in the form of 8 bits each of Red-Green-Blue.
The [WS2812](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) is integrated into the package of a 50:50 LED rather than as a separate device.. It accepts data in the form of 8 bits each of Green-Red-Blue.
It is thus possible, depending on the LED board/strip being used that either Red-Green-Blue or Green-Red-Blue encoding may be required. This may be controlled by setting the following.
```
set ledstrip_grb_rgb = RGB
```
or
```
set ledstrip_grb_rgb = GRB
```
The confirm the required setting simply set an LED to be green. If it lights up red, you have the wrong setting.
## Connections
WS2812 LED strips generally require a single data line, 5V and GND.

View file

@ -95,7 +95,8 @@ void ws2811LedStripInit(ioTag_t ioTag)
const hsvColor_t hsv_white = { 0, 255, 255 };
setStripColor(&hsv_white);
ws2811UpdateStrip();
// RGB or GRB ordering doesn't matter for white
ws2811UpdateStrip(LED_RGB);
}
bool isWS2811LedStripReady(void)
@ -109,12 +110,23 @@ static int16_t ledIndex;
#define USE_FAST_DMA_BUFFER_IMPL
#ifdef USE_FAST_DMA_BUFFER_IMPL
STATIC_UNIT_TESTED void fastUpdateLEDDMABuffer(rgbColor24bpp_t *color)
STATIC_UNIT_TESTED void fastUpdateLEDDMABuffer(ledStripFormatRGB_e ledFormat, rgbColor24bpp_t *color)
{
uint32_t grb = (color->rgb.g << 16) | (color->rgb.r << 8) | (color->rgb.b);
uint32_t packed_colour;
switch (ledFormat) {
case LED_RGB: // WS2811 drivers use RGB format
packed_colour = (color->rgb.r << 16) | (color->rgb.g << 8) | (color->rgb.b);
break;
case LED_GRB: // WS2812 drivers use GRB format
default:
packed_colour = (color->rgb.g << 16) | (color->rgb.r << 8) | (color->rgb.b);
break;
}
for (int8_t index = 23; index >= 0; index--) {
ledStripDMABuffer[dmaBufferOffset++] = (grb & (1 << index)) ? BIT_COMPARE_1 : BIT_COMPARE_0;
ledStripDMABuffer[dmaBufferOffset++] = (packed_colour & (1 << index)) ? BIT_COMPARE_1 : BIT_COMPARE_0;
}
}
#else
@ -141,7 +153,7 @@ STATIC_UNIT_TESTED void updateLEDDMABuffer(uint8_t componentValue)
* This method is non-blocking unless an existing LED update is in progress.
* it does not wait until all the LEDs have been updated, that happens in the background.
*/
void ws2811UpdateStrip(void)
void ws2811UpdateStrip(ledStripFormatRGB_e ledFormat)
{
static rgbColor24bpp_t *rgb24;
@ -160,10 +172,21 @@ void ws2811UpdateStrip(void)
rgb24 = hsvToRgb24(&ledColorBuffer[ledIndex]);
#ifdef USE_FAST_DMA_BUFFER_IMPL
fastUpdateLEDDMABuffer(rgb24);
fastUpdateLEDDMABuffer(ledFormat, rgb24);
#else
switch (ledFormat) {
case LED_RGB: // WS2811 drivers use RGB format
updateLEDDMABuffer(rgb24->rgb.r);
updateLEDDMABuffer(rgb24->rgb.g);
break;
case LED_GRB: // WS2812 drivers use GRB format
default:
updateLEDDMABuffer(rgb24->rgb.g);
updateLEDDMABuffer(rgb24->rgb.r);
break;
}
updateLEDDMABuffer(rgb24->rgb.b);
#endif

View file

@ -18,6 +18,7 @@
#pragma once
#include "drivers/io_types.h"
#include "io/ledstrip.h"
#define WS2811_LED_STRIP_LENGTH 32
#define WS2811_BITS_PER_LED 24
@ -36,7 +37,7 @@ void ws2811LedStripInit(ioTag_t ioTag);
void ws2811LedStripHardwareInit(ioTag_t ioTag);
void ws2811LedStripDMAEnable(void);
void ws2811UpdateStrip(void);
void ws2811UpdateStrip(ledStripFormatRGB_e ledFormat);
void setLedHsv(uint16_t index, const hsvColor_t *color);
void getLedHsv(uint16_t index, hsvColor_t *color);

View file

@ -293,6 +293,12 @@ static const char * const lookupOverclock[] = {
};
#endif
#ifdef USE_LED_STRIP
static const char * const lookupLedStripFormatRGB[] = {
"GRB", "RGB"
};
#endif
const lookupTableEntry_t lookupTables[] = {
{ lookupTableOffOn, sizeof(lookupTableOffOn) / sizeof(char *) },
{ lookupTableUnit, sizeof(lookupTableUnit) / sizeof(char *) },
@ -348,6 +354,9 @@ const lookupTableEntry_t lookupTables[] = {
#ifdef USE_OVERCLOCK
{ lookupOverclock, sizeof(lookupOverclock) / sizeof(char *) },
#endif
#ifdef USE_LED_STRIP
{ lookupLedStripFormatRGB, sizeof(lookupLedStripFormatRGB) / sizeof(char *) },
#endif
#ifdef USE_DUAL_GYRO
{ lookupTableGyro, sizeof(lookupTableGyro) / sizeof(char *) },
#endif
@ -730,6 +739,7 @@ const clivalue_t valueTable[] = {
// PG_LED_STRIP_CONFIG
#ifdef USE_LED_STRIP
{ "ledstrip_visual_beeper", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_LED_STRIP_CONFIG, offsetof(ledStripConfig_t, ledstrip_visual_beeper) },
{ "ledstrip_grb_rgb", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_RGB_GRB }, PG_LED_STRIP_CONFIG, offsetof(ledStripConfig_t, ledstrip_grb_rgb) },
#endif
// PG_SDCARD_CONFIG

View file

@ -77,6 +77,9 @@ typedef enum {
#ifdef USE_OVERCLOCK
TABLE_OVERCLOCK,
#endif
#ifdef USE_LED_STRIP
TABLE_RGB_GRB,
#endif
#ifdef USE_DUAL_GYRO
TABLE_GYRO,
#endif

View file

@ -1115,7 +1115,7 @@ void ledStripUpdate(timeUs_t currentTimeUs)
bool updateNow = timActive & (1 << timId);
(*layerTable[timId])(updateNow, timer);
}
ws2811UpdateStrip();
ws2811UpdateStrip((ledStripFormatRGB_e)ledStripConfig()->ledstrip_grb_rgb);
}
bool parseColor(int index, const char *colorConfig)
@ -1210,6 +1210,6 @@ static void ledStripDisable(void)
{
setStripColor(&HSV(BLACK));
ws2811UpdateStrip();
ws2811UpdateStrip((ledStripFormatRGB_e)ledStripConfig()->ledstrip_grb_rgb);
}
#endif

View file

@ -121,6 +121,12 @@ typedef enum {
LED_OVERLAY_WARNING
} ledOverlayId_e;
// Enumeration to match the string options defined in lookupLedStripFormatRGB in settings.c
typedef enum {
LED_GRB,
LED_RGB
} ledStripFormatRGB_e;
typedef struct modeColorIndexes_s {
uint8_t color[LED_DIRECTION_COUNT];
} modeColorIndexes_t;
@ -146,6 +152,7 @@ typedef struct ledStripConfig_s {
uint8_t ledstrip_visual_beeper; // suppress LEDLOW mode if beeper is on
uint8_t ledstrip_aux_channel;
ioTag_t ioTag;
ledStripFormatRGB_e ledstrip_grb_rgb;
} ledStripConfig_t;
PG_DECLARE(ledStripConfig_t, ledStripConfig);

View file

@ -308,7 +308,7 @@ void ws2811LedStripInit(ioTag_t ioTag) {
UNUSED(ioTag);
}
void ws2811UpdateStrip(void) {}
void ws2811UpdateStrip(ledStripFormatRGB_e) {}
void setLedValue(uint16_t index, const uint8_t value) {
UNUSED(index);