Merge pull request #10762 from g3gg0/add_SK6812_RGBW
add SK6812 RGBW 4-channel LEDs
This commit is contained in:
commit
ac7774cc73
|
@ -89,6 +89,8 @@ It could be possible to be able to specify the timings required via CLI if users
|
|||
* Fits well under motors on mini 250 quads.
|
||||
* [Adafruit NeoPixel Stick](https://www.adafruit.com/products/1426) (works well)
|
||||
* Measured current consumption in all white mode ~ 350 mA.
|
||||
* [Aliexpress SK6812 RBGWW strip](https://www.aliexpress.com/wholesale?SearchText=rgbw+sk6812) (works well)
|
||||
* Alternative [Adafruit NeoPixel Stick RGBW](https://www.adafruit.com/product/2869)
|
||||
|
||||
|
||||
### WS2811 vs WS2812
|
||||
|
@ -97,6 +99,8 @@ The [WS2811](https://cdn-shop.adafruit.com/datasheets/WS2811.pdf) is a LED drive
|
|||
|
||||
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.
|
||||
|
||||
With the [SK6812](https://cdn-shop.adafruit.com/product-files/1138/SK6812+LED+datasheet+.pdf) also GRBW variants are supported, which have a fourth (white) channel and such provide a much cleaner white color.
|
||||
|
||||
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.
|
||||
|
||||
```
|
||||
|
@ -107,8 +111,14 @@ or
|
|||
```
|
||||
set ledstrip_grb_rgb = GRB
|
||||
```
|
||||
or
|
||||
|
||||
```
|
||||
set ledstrip_grb_rgb = GRBW
|
||||
```
|
||||
|
||||
Then confirm the required setting by simply setting an LED to be green. If it lights up red, you have the wrong setting.
|
||||
Afterwards check if the second LED also lights up red - if not, you might have 4-color SK6812 LEDs and would have to select GRBW.
|
||||
|
||||
## Connections
|
||||
|
||||
|
|
|
@ -366,7 +366,7 @@ static const char * const lookupOverclock[] = {
|
|||
|
||||
#ifdef USE_LED_STRIP
|
||||
static const char * const lookupLedStripFormatRGB[] = {
|
||||
"GRB", "RGB"
|
||||
"GRB", "RGB", "GRBW"
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "platform.h"
|
||||
#include "common/maths.h"
|
||||
|
||||
#ifdef USE_LED_STRIP
|
||||
|
||||
|
@ -139,8 +140,8 @@ void ws2811LedStripEnable(void)
|
|||
|
||||
const hsvColor_t hsv_black = { 0, 0, 0 };
|
||||
setStripColor(&hsv_black);
|
||||
// RGB or GRB ordering doesn't matter for black
|
||||
ws2811UpdateStrip(LED_RGB, 100);
|
||||
// RGB or GRB ordering doesn't matter for black, use 4-channel LED configuraton to make sure all channels are zero
|
||||
ws2811UpdateStrip(LED_GRBW, 100);
|
||||
|
||||
ws2811Initialised = true;
|
||||
}
|
||||
|
@ -153,23 +154,34 @@ bool isWS2811LedStripReady(void)
|
|||
|
||||
STATIC_UNIT_TESTED void updateLEDDMABuffer(ledStripFormatRGB_e ledFormat, rgbColor24bpp_t *color, unsigned ledIndex)
|
||||
{
|
||||
|
||||
uint32_t bits_per_led;
|
||||
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);
|
||||
bits_per_led = 24;
|
||||
break;
|
||||
|
||||
case LED_GRBW: // SK6812 drivers use this
|
||||
{
|
||||
/* reconstruct white channel from RGB, making the intensity a bit nonlinear, but thats fine for this use case */
|
||||
uint8_t white = MIN(MIN(color->rgb.r, color->rgb.g), color->rgb.b);
|
||||
packed_colour = (color->rgb.g << 24) | (color->rgb.r << 16) | (color->rgb.b << 8) | (white);
|
||||
bits_per_led = 32;
|
||||
break;
|
||||
}
|
||||
|
||||
case LED_GRB: // WS2812 drivers use GRB format
|
||||
default:
|
||||
packed_colour = (color->rgb.g << 16) | (color->rgb.r << 8) | (color->rgb.b);
|
||||
bits_per_led = 24;
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned dmaBufferOffset = 0;
|
||||
for (int index = 23; index >= 0; index--) {
|
||||
ledStripDMABuffer[ledIndex * WS2811_BITS_PER_LED + dmaBufferOffset++] = (packed_colour & (1 << index)) ? BIT_COMPARE_1 : BIT_COMPARE_0;
|
||||
for (int index = bits_per_led-1; index >= 0; index--) {
|
||||
ledStripDMABuffer[ledIndex * bits_per_led + dmaBufferOffset++] = (packed_colour & (1 << index)) ? BIT_COMPARE_1 : BIT_COMPARE_0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,11 +26,11 @@
|
|||
|
||||
#define WS2811_LED_STRIP_LENGTH 32
|
||||
|
||||
#define WS2811_BITS_PER_LED 24
|
||||
#define WS2811_BITS_PER_LED_MAX 32
|
||||
|
||||
#if defined(USE_WS2811_SINGLE_COLOUR)
|
||||
#define WS2811_DATA_BUFFER_SIZE 1
|
||||
#define WS2811_DMA_BUFFER_SIZE (WS2811_DATA_BUFFER_SIZE * WS2811_BITS_PER_LED)
|
||||
#define WS2811_DMA_BUFFER_SIZE (WS2811_DATA_BUFFER_SIZE * WS2811_BITS_PER_LED_MAX)
|
||||
// Do 2 extra iterations of the DMA transfer with the output set to low to generate the > 50us delay.
|
||||
#define WS2811_DELAY_ITERATIONS 2
|
||||
#else
|
||||
|
@ -38,7 +38,7 @@
|
|||
// for 50us delay
|
||||
#define WS2811_DELAY_BUFFER_LENGTH 42
|
||||
// number of bytes needed is #LEDs * 24 bytes + 42 trailing bytes)
|
||||
#define WS2811_DMA_BUFFER_SIZE (WS2811_DATA_BUFFER_SIZE * WS2811_BITS_PER_LED + WS2811_DELAY_BUFFER_LENGTH)
|
||||
#define WS2811_DMA_BUFFER_SIZE (WS2811_DATA_BUFFER_SIZE * WS2811_BITS_PER_LED_MAX + WS2811_DELAY_BUFFER_LENGTH)
|
||||
#endif
|
||||
|
||||
#ifdef USE_LEDSTRIP_CACHE_MGMT
|
||||
|
@ -64,7 +64,8 @@ extern uint32_t ledStripDMABuffer[WS2811_DMA_BUFFER_SIZE];
|
|||
// Enumeration to match the string options defined in lookupLedStripFormatRGB in settings.c
|
||||
typedef enum {
|
||||
LED_GRB,
|
||||
LED_RGB
|
||||
LED_RGB,
|
||||
LED_GRBW
|
||||
} ledStripFormatRGB_e;
|
||||
|
||||
void ws2811LedStripInit(ioTag_t ioTag);
|
||||
|
|
Loading…
Reference in New Issue