mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-18 22:05:17 +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:
parent
94f06e1e05
commit
0430fcb67d
8 changed files with 77 additions and 13 deletions
|
@ -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)
|
* [Adafruit NeoPixel Stick](https://www.adafruit.com/products/1426) (works well)
|
||||||
* Measured current consumption in all white mode ~ 350 mA.
|
* 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
|
## Connections
|
||||||
|
|
||||||
WS2812 LED strips generally require a single data line, 5V and GND.
|
WS2812 LED strips generally require a single data line, 5V and GND.
|
||||||
|
|
|
@ -95,7 +95,8 @@ void ws2811LedStripInit(ioTag_t ioTag)
|
||||||
|
|
||||||
const hsvColor_t hsv_white = { 0, 255, 255 };
|
const hsvColor_t hsv_white = { 0, 255, 255 };
|
||||||
setStripColor(&hsv_white);
|
setStripColor(&hsv_white);
|
||||||
ws2811UpdateStrip();
|
// RGB or GRB ordering doesn't matter for white
|
||||||
|
ws2811UpdateStrip(LED_RGB);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isWS2811LedStripReady(void)
|
bool isWS2811LedStripReady(void)
|
||||||
|
@ -109,12 +110,23 @@ static int16_t ledIndex;
|
||||||
#define USE_FAST_DMA_BUFFER_IMPL
|
#define USE_FAST_DMA_BUFFER_IMPL
|
||||||
#ifdef 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--) {
|
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
|
#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.
|
* 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.
|
* 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;
|
static rgbColor24bpp_t *rgb24;
|
||||||
|
|
||||||
|
@ -160,10 +172,21 @@ void ws2811UpdateStrip(void)
|
||||||
rgb24 = hsvToRgb24(&ledColorBuffer[ledIndex]);
|
rgb24 = hsvToRgb24(&ledColorBuffer[ledIndex]);
|
||||||
|
|
||||||
#ifdef USE_FAST_DMA_BUFFER_IMPL
|
#ifdef USE_FAST_DMA_BUFFER_IMPL
|
||||||
fastUpdateLEDDMABuffer(rgb24);
|
fastUpdateLEDDMABuffer(ledFormat, rgb24);
|
||||||
#else
|
#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.g);
|
||||||
updateLEDDMABuffer(rgb24->rgb.r);
|
updateLEDDMABuffer(rgb24->rgb.r);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
updateLEDDMABuffer(rgb24->rgb.b);
|
updateLEDDMABuffer(rgb24->rgb.b);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "drivers/io_types.h"
|
#include "drivers/io_types.h"
|
||||||
|
#include "io/ledstrip.h"
|
||||||
|
|
||||||
#define WS2811_LED_STRIP_LENGTH 32
|
#define WS2811_LED_STRIP_LENGTH 32
|
||||||
#define WS2811_BITS_PER_LED 24
|
#define WS2811_BITS_PER_LED 24
|
||||||
|
@ -36,7 +37,7 @@ void ws2811LedStripInit(ioTag_t ioTag);
|
||||||
void ws2811LedStripHardwareInit(ioTag_t ioTag);
|
void ws2811LedStripHardwareInit(ioTag_t ioTag);
|
||||||
void ws2811LedStripDMAEnable(void);
|
void ws2811LedStripDMAEnable(void);
|
||||||
|
|
||||||
void ws2811UpdateStrip(void);
|
void ws2811UpdateStrip(ledStripFormatRGB_e ledFormat);
|
||||||
|
|
||||||
void setLedHsv(uint16_t index, const hsvColor_t *color);
|
void setLedHsv(uint16_t index, const hsvColor_t *color);
|
||||||
void getLedHsv(uint16_t index, hsvColor_t *color);
|
void getLedHsv(uint16_t index, hsvColor_t *color);
|
||||||
|
|
|
@ -293,6 +293,12 @@ static const char * const lookupOverclock[] = {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_LED_STRIP
|
||||||
|
static const char * const lookupLedStripFormatRGB[] = {
|
||||||
|
"GRB", "RGB"
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
const lookupTableEntry_t lookupTables[] = {
|
const lookupTableEntry_t lookupTables[] = {
|
||||||
{ lookupTableOffOn, sizeof(lookupTableOffOn) / sizeof(char *) },
|
{ lookupTableOffOn, sizeof(lookupTableOffOn) / sizeof(char *) },
|
||||||
{ lookupTableUnit, sizeof(lookupTableUnit) / sizeof(char *) },
|
{ lookupTableUnit, sizeof(lookupTableUnit) / sizeof(char *) },
|
||||||
|
@ -348,6 +354,9 @@ const lookupTableEntry_t lookupTables[] = {
|
||||||
#ifdef USE_OVERCLOCK
|
#ifdef USE_OVERCLOCK
|
||||||
{ lookupOverclock, sizeof(lookupOverclock) / sizeof(char *) },
|
{ lookupOverclock, sizeof(lookupOverclock) / sizeof(char *) },
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_LED_STRIP
|
||||||
|
{ lookupLedStripFormatRGB, sizeof(lookupLedStripFormatRGB) / sizeof(char *) },
|
||||||
|
#endif
|
||||||
#ifdef USE_DUAL_GYRO
|
#ifdef USE_DUAL_GYRO
|
||||||
{ lookupTableGyro, sizeof(lookupTableGyro) / sizeof(char *) },
|
{ lookupTableGyro, sizeof(lookupTableGyro) / sizeof(char *) },
|
||||||
#endif
|
#endif
|
||||||
|
@ -730,6 +739,7 @@ const clivalue_t valueTable[] = {
|
||||||
// PG_LED_STRIP_CONFIG
|
// PG_LED_STRIP_CONFIG
|
||||||
#ifdef USE_LED_STRIP
|
#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_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
|
#endif
|
||||||
|
|
||||||
// PG_SDCARD_CONFIG
|
// PG_SDCARD_CONFIG
|
||||||
|
|
|
@ -77,6 +77,9 @@ typedef enum {
|
||||||
#ifdef USE_OVERCLOCK
|
#ifdef USE_OVERCLOCK
|
||||||
TABLE_OVERCLOCK,
|
TABLE_OVERCLOCK,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_LED_STRIP
|
||||||
|
TABLE_RGB_GRB,
|
||||||
|
#endif
|
||||||
#ifdef USE_DUAL_GYRO
|
#ifdef USE_DUAL_GYRO
|
||||||
TABLE_GYRO,
|
TABLE_GYRO,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1115,7 +1115,7 @@ void ledStripUpdate(timeUs_t currentTimeUs)
|
||||||
bool updateNow = timActive & (1 << timId);
|
bool updateNow = timActive & (1 << timId);
|
||||||
(*layerTable[timId])(updateNow, timer);
|
(*layerTable[timId])(updateNow, timer);
|
||||||
}
|
}
|
||||||
ws2811UpdateStrip();
|
ws2811UpdateStrip((ledStripFormatRGB_e)ledStripConfig()->ledstrip_grb_rgb);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseColor(int index, const char *colorConfig)
|
bool parseColor(int index, const char *colorConfig)
|
||||||
|
@ -1210,6 +1210,6 @@ static void ledStripDisable(void)
|
||||||
{
|
{
|
||||||
setStripColor(&HSV(BLACK));
|
setStripColor(&HSV(BLACK));
|
||||||
|
|
||||||
ws2811UpdateStrip();
|
ws2811UpdateStrip((ledStripFormatRGB_e)ledStripConfig()->ledstrip_grb_rgb);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -121,6 +121,12 @@ typedef enum {
|
||||||
LED_OVERLAY_WARNING
|
LED_OVERLAY_WARNING
|
||||||
} ledOverlayId_e;
|
} 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 {
|
typedef struct modeColorIndexes_s {
|
||||||
uint8_t color[LED_DIRECTION_COUNT];
|
uint8_t color[LED_DIRECTION_COUNT];
|
||||||
} modeColorIndexes_t;
|
} 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_visual_beeper; // suppress LEDLOW mode if beeper is on
|
||||||
uint8_t ledstrip_aux_channel;
|
uint8_t ledstrip_aux_channel;
|
||||||
ioTag_t ioTag;
|
ioTag_t ioTag;
|
||||||
|
ledStripFormatRGB_e ledstrip_grb_rgb;
|
||||||
} ledStripConfig_t;
|
} ledStripConfig_t;
|
||||||
|
|
||||||
PG_DECLARE(ledStripConfig_t, ledStripConfig);
|
PG_DECLARE(ledStripConfig_t, ledStripConfig);
|
||||||
|
|
|
@ -308,7 +308,7 @@ void ws2811LedStripInit(ioTag_t ioTag) {
|
||||||
UNUSED(ioTag);
|
UNUSED(ioTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws2811UpdateStrip(void) {}
|
void ws2811UpdateStrip(ledStripFormatRGB_e) {}
|
||||||
|
|
||||||
void setLedValue(uint16_t index, const uint8_t value) {
|
void setLedValue(uint16_t index, const uint8_t value) {
|
||||||
UNUSED(index);
|
UNUSED(index);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue