Fix RGBW handling in TasmotaLED and xlgt_01_ws2812_esp32 for correct pixel order and channel positioning (#24172)

- In TasmotaLED: fixes for `_w_before` to use correct bitmask and for Show() to build 4 byte buffer correctly
- In xlgt_01_ws2812_esp32: fixes to set white value in Ws2812SetColor(), use correct bitmasks, and determine `light_type` based on PixelType if set
This commit is contained in:
Allen Schober 2025-11-29 09:32:23 -05:00 committed by GitHub
parent 77c751c4a8
commit 0a89191e9d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 26 additions and 14 deletions

View File

@ -112,7 +112,7 @@ TasmotaLED::~TasmotaLED() {
void TasmotaLED::_adjustSubType(void) {
_pixel_order = (_type >> 4) & 0x07;
_pixel_matrix = &TASMOTALED_CHANNEL_ORDERS[_pixel_order];
_w_before = _type & 0x08;
_w_before = _type & 0x80; // bit 7 sets the position for W channel
}
void TasmotaLED::SetPixelCount(uint16_t num_leds) {
@ -192,12 +192,18 @@ void TasmotaLED::Show(void) {
}
} else if (_pixel_size == 4) {
for (uint32_t i = 0; i < _pixel_count; i++) {
if (_w_before) { *buf_to++ = buf_from[3]; }
buf_to[(*_pixel_matrix)[0]] = buf_from[0]; // R
buf_to[(*_pixel_matrix)[1]] = buf_from[1]; // G
buf_to[(*_pixel_matrix)[2]] = buf_from[2]; // B
if (!_w_before) { *buf_to++ = buf_from[3]; }
buf_to += 4; // one increment already happened
if (_w_before) {
buf_to[0] = buf_from[0]; // W
buf_to[1 + (*_pixel_matrix)[0]] = buf_from[1]; // R
buf_to[1 + (*_pixel_matrix)[1]] = buf_from[2]; // G
buf_to[1 + (*_pixel_matrix)[2]] = buf_from[3]; // B
} else {
buf_to[(*_pixel_matrix)[0]] = buf_from[1]; // R
buf_to[(*_pixel_matrix)[1]] = buf_from[2]; // G
buf_to[(*_pixel_matrix)[2]] = buf_from[3]; // B
buf_to[3] = buf_from[0]; // W
}
buf_to += 4;
buf_from += pixel_incr;
}
}

View File

@ -504,6 +504,7 @@ void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint
lcolor.R = red;
lcolor.G = green;
lcolor.B = blue;
lcolor.W = white;
if (led) {
strip->SetPixelColor(led -1, lcolor.C); // Led 1 is strip Led 0 -> substract offset 1
} else {
@ -615,8 +616,8 @@ uint16_t Ws2812SettingsToLedType(void) {
uint16_t led_type = kTasLed_Type; // default value from compile options
if (Settings->mbflag2.light_pixels_order != 0) {
led_type = (led_type & 0xFF00) | (Settings->mbflag2.light_pixels_order << 4)
| (Settings->mbflag2.light_pixels_w_first ? TasmotaLed_Wxxx : 0)
| (Settings->mbflag2.light_pixels_rgbw ? TasmotaLed_4_WRGB : TasmotaLed_3_RGB);
| (Settings->mbflag2.light_pixels_rgbw ? TasmotaLed_4_WRGB : TasmotaLed_3_RGB)
| (Settings->mbflag2.light_pixels_w_first ? TasmotaLed_Wxxx : 0);
}
return led_type;
}
@ -683,11 +684,16 @@ void Ws2812ModuleSelected(void)
Light.max_scheme++;
#endif
// If PixelType setting set, use it to determine RGBW. Otherwise use compile-time default.
if (Settings->mbflag2.light_pixels_order != 0) {
TasmotaGlobal.light_type = Settings->mbflag2.light_pixels_rgbw ? LT_RGBW : LT_RGB;
} else {
#if (USE_WS2812_CTYPE > NEO_3LED)
TasmotaGlobal.light_type = LT_RGBW;
#else
TasmotaGlobal.light_type = LT_RGB;
#endif
}
TasmotaGlobal.light_driver = XLGT_01;
}
}
@ -849,8 +855,8 @@ void CmndPixelType(void)
// +8 = 4 channels RGBW strip - default is 3 channels RGB
// +16 = W channel is sent first - default W channel is sent last
uint32_t pixels_order = XdrvMailbox.payload & 0x07;
uint32_t pixels_w_first = (XdrvMailbox.payload & 0x08) ? 1 : 0;
uint32_t pixels_rgbw = (XdrvMailbox.payload & 0x10) ? 1 : 0;
uint32_t pixels_rgbw = (XdrvMailbox.payload & 0x08) ? 1 : 0;
uint32_t pixels_w_first = (XdrvMailbox.payload & 0x10) ? 1 : 0;
// changing number of channels requires a reboot
bool reboot = pixels_rgbw != Settings->mbflag2.light_pixels_rgbw;
if (reboot) {
@ -858,14 +864,14 @@ void CmndPixelType(void)
}
Settings->mbflag2.light_pixels_order = pixels_order;
Settings->mbflag2.light_pixels_rgbw = pixels_rgbw;
Settings->mbflag2.light_pixels_w_first = pixels_w_first;
Settings->mbflag2.light_pixels_rgbw = (XdrvMailbox.payload & 0x10) ? 1 : 0;
Ws2812ChangePixelType(reboot);
}
uint32_t pixel_type = 0;
if (Settings->mbflag2.light_pixels_order != 0) {
pixel_type = Settings->mbflag2.light_pixels_order | (Settings->mbflag2.light_pixels_w_first ? 0x08 : 0)
| (Settings->mbflag2.light_pixels_rgbw ? 0x10 : 0);
pixel_type = Settings->mbflag2.light_pixels_order | (Settings->mbflag2.light_pixels_rgbw ? 0x08 : 0)
| (Settings->mbflag2.light_pixels_w_first ? 0x10 : 0);
}
ResponseCmndNumber(pixel_type);
}