diff --git a/platformio.ini b/platformio.ini index 6306595a2..40dceabc5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -143,7 +143,7 @@ lib_compat_mode = strict lib_deps = fastled/FastLED @ 3.6.0 IRremoteESP8266 @ 2.8.2 - makuna/NeoPixelBus @ 2.7.5 + makuna/NeoPixelBus @ 2.7.8 https://github.com/Aircoookie/ESPAsyncWebServer.git @ ^2.1.0 # for I2C interface ;Wire diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index dd88bf34f..35538a78a 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -280,6 +280,7 @@ void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) { if (!_valid) return; if (Bus::hasWhite(_type)) c = autoWhiteCalc(c); if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT + if (_type == TYPE_FW1906) calculateCCT(c, PolyBus::cctWW, PolyBus::cctCW); // FW1906 ignores W component in c if (_data) { // use _buffering this causes ~20% FPS drop size_t channels = Bus::hasWhite(_type) + 3*Bus::hasRGB(_type); size_t offset = pix*channels; @@ -645,13 +646,13 @@ uint32_t BusManager::memUsage(BusConfig &bc) { uint16_t multiplier = 1; if (IS_DIGITAL(bc.type)) { // digital types if (IS_16BIT(bc.type)) len *= 2; // 16-bit LEDs - #ifdef ESP8266 if (bc.type > 28) channels = 4; //RGBW + if (bc.type == TYPE_FW1906) channels = 5; //GRBCW + #ifdef ESP8266 if (bc.pins[0] == 3) { //8266 DMA uses 5x the mem multiplier = 5; } #else //ESP32 RMT uses double buffer, I2S uses 5x buffer - if (bc.type > 28) channels = 4; //RGBW multiplier = 2; #endif } diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index d0d40f4f1..6b8e9d7eb 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -157,7 +157,7 @@ class Bus { } virtual bool hasWhite(void) { return Bus::hasWhite(_type); } static bool hasWhite(uint8_t type) { - if ((type >= TYPE_WS2812_1CH && type <= TYPE_WS2812_WWA) || type == TYPE_SK6812_RGBW || type == TYPE_TM1814 || type == TYPE_UCS8904) return true; // digital types with white channel + if ((type >= TYPE_WS2812_1CH && type <= TYPE_WS2812_WWA) || type == TYPE_SK6812_RGBW || type == TYPE_TM1814 || type == TYPE_UCS8904 || type == TYPE_FW1906) return true; // digital types with white channel if (type > TYPE_ONOFF && type <= TYPE_ANALOG_5CH && type != TYPE_ANALOG_3CH) return true; // analog types with white channel if (type == TYPE_NET_DDP_RGBW) return true; // network types with white channel return false; @@ -165,7 +165,7 @@ class Bus { virtual bool hasCCT(void) { return Bus::hasCCT(_type); } static bool hasCCT(uint8_t type) { if (type == TYPE_WS2812_2CH_X3 || type == TYPE_WS2812_WWA || - type == TYPE_ANALOG_2CH || type == TYPE_ANALOG_5CH) return true; + type == TYPE_ANALOG_2CH || type == TYPE_ANALOG_5CH || type == TYPE_FW1906) return true; return false; } static void setCCT(uint16_t cct) { diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index c63e055a8..e329246f1 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -2,6 +2,7 @@ #define BusWrapper_h #include "NeoPixelBusLg.h" +#include "bus_manager.h" // temporary - these defines should actually be set in platformio.ini // C3: I2S0 and I2S1 methods not supported (has one I2S bus) @@ -63,6 +64,11 @@ #define I_8266_U1_UCS_4 54 #define I_8266_DM_UCS_4 55 #define I_8266_BB_UCS_4 56 +//FW1906 GRBCW +#define I_8266_U0_FW6_5 66 +#define I_8266_U1_FW6_5 67 +#define I_8266_DM_FW6_5 68 +#define I_8266_BB_FW6_5 69 //ESP8266 APA106 #define I_8266_U0_APA106_3 81 #define I_8266_U1_APA106_3 82 @@ -104,12 +110,17 @@ #define I_32_RN_UCS_4 60 #define I_32_I0_UCS_4 61 #define I_32_I1_UCS_4 62 +//FW1906 GRBCW +#define I_32_RN_FW6_5 63 +#define I_32_I0_FW6_5 64 +#define I_32_I1_FW6_5 65 //Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S) #define I_32_RN_APA106_3 85 #define I_32_I0_APA106_3 86 #define I_32_I1_APA106_3 87 #define I_32_BB_APA106_3 88 // bitbangging on ESP32 not recommended + //APA102 #define I_HS_DOT_3 39 //hardware SPI #define I_SS_DOT_3 40 //soft SPI @@ -176,6 +187,11 @@ #define B_8266_U1_APA106_3 NeoPixelBusLg //3 chan, esp8266, gpio2 #define B_8266_DM_APA106_3 NeoPixelBusLg //3 chan, esp8266, gpio3 #define B_8266_BB_APA106_3 NeoPixelBusLg //3 chan, esp8266, bb (any pin but 16) +//FW1906 GRBCW +#define B_8266_U0_FW6_5 NeoPixelBusLg //esp8266, gpio1 +#define B_8266_U1_FW6_5 NeoPixelBusLg //esp8266, gpio2 +#define B_8266_DM_FW6_5 NeoPixelBusLg //esp8266, gpio3 +#define B_8266_BB_FW6_5 NeoPixelBusLg //esp8266, bb #endif /*** ESP32 Neopixel methods ***/ @@ -251,6 +267,14 @@ #define B_32_I1_APA106_3 NeoPixelBusLg #endif //#define B_32_BB_APA106_3 NeoPixelBusLg // NeoEsp8266BitBang800KbpsMethod +//FW1906 GRBCW +#define B_32_RN_FW6_5 NeoPixelBusLg +#ifndef WLED_NO_I2S0_PIXELBUS +#define B_32_I0_FW6_5 NeoPixelBusLg +#endif +#ifndef WLED_NO_I2S1_PIXELBUS +#define B_32_I1_FW6_5 NeoPixelBusLg +#endif #endif @@ -290,6 +314,12 @@ //handles pointer type conversion for all possible bus types class PolyBus { public: + // WW and CW components for chips that support them (FW1906). They have to be set before calling + // PolyBus::setPixelColor(). In such case W component has no meaning in setPixelColor() + // as there is no support for WW/CW API yet + // if both values are 0, W component *may* be used instead (for WW & CW) + static uint8_t cctWW, cctCW; + // initialize SPI bus speed for DotStar methods template static void beginDotStar(void* busPtr, int8_t sck, int8_t miso, int8_t mosi, int8_t ss, uint16_t clock_kHz = 0U) { @@ -353,6 +383,10 @@ class PolyBus { case I_8266_U1_APA106_3: (static_cast(busPtr))->Begin(); break; case I_8266_DM_APA106_3: (static_cast(busPtr))->Begin(); break; case I_8266_BB_APA106_3: (static_cast(busPtr))->Begin(); break; + case I_8266_U0_FW6_5: (static_cast(busPtr))->Begin(); break; + case I_8266_U1_FW6_5: (static_cast(busPtr))->Begin(); break; + case I_8266_DM_FW6_5: (static_cast(busPtr))->Begin(); break; + case I_8266_BB_FW6_5: (static_cast(busPtr))->Begin(); break; #endif #ifdef ARDUINO_ARCH_ESP32 case I_32_RN_NEO_3: (static_cast(busPtr))->Begin(); break; @@ -404,6 +438,14 @@ class PolyBus { #ifndef WLED_NO_I2S1_PIXELBUS case I_32_I1_UCS_4: (static_cast(busPtr))->Begin(); break; #endif + case I_32_RN_FW6_5: (static_cast(busPtr))->Begin(); break; + #ifndef WLED_NO_I2S0_PIXELBUS + case I_32_I0_FW6_5: (static_cast(busPtr))->Begin(); break; + #endif + #ifndef WLED_NO_I2S1_PIXELBUS + case I_32_I1_FW6_5: (static_cast(busPtr))->Begin(); break; + #endif + // case I_32_BB_UCS_4: (static_cast(busPtr))->Begin(); break; case I_32_RN_APA106_3: (static_cast(busPtr))->Begin(); break; #ifndef WLED_NO_I2S0_PIXELBUS @@ -465,6 +507,10 @@ class PolyBus { case I_8266_U1_APA106_3: busPtr = new B_8266_U1_APA106_3(len, pins[0]); break; case I_8266_DM_APA106_3: busPtr = new B_8266_DM_APA106_3(len, pins[0]); break; case I_8266_BB_APA106_3: busPtr = new B_8266_BB_APA106_3(len, pins[0]); break; + case I_8266_U0_FW6_5: busPtr = new B_8266_U0_FW6_5(len, pins[0]); break; + case I_8266_U1_FW6_5: busPtr = new B_8266_U1_FW6_5(len, pins[0]); break; + case I_8266_DM_FW6_5: busPtr = new B_8266_DM_FW6_5(len, pins[0]); break; + case I_8266_BB_FW6_5: busPtr = new B_8266_BB_FW6_5(len, pins[0]); break; #endif #ifdef ARDUINO_ARCH_ESP32 case I_32_RN_NEO_3: busPtr = new B_32_RN_NEO_3(len, pins[0], (NeoBusChannel)channel); break; @@ -525,6 +571,13 @@ class PolyBus { case I_32_I1_APA106_3: busPtr = new B_32_I1_APA106_3(len, pins[0]); break; #endif // case I_32_BB_APA106_3: busPtr = new B_32_BB_APA106_3(len, pins[0], (NeoBusChannel)channel); break; + case I_32_RN_FW6_5: busPtr = new B_32_RN_FW6_5(len, pins[0], (NeoBusChannel)channel); break; + #ifndef WLED_NO_I2S0_PIXELBUS + case I_32_I0_FW6_5: busPtr = new B_32_I0_FW6_5(len, pins[0]); break; + #endif + #ifndef WLED_NO_I2S1_PIXELBUS + case I_32_I1_FW6_5: busPtr = new B_32_I1_FW6_5(len, pins[0]); break; + #endif #endif // for 2-wire: pins[1] is clk, pins[0] is dat. begin expects (len, clk, dat) case I_HS_DOT_3: busPtr = new B_HS_DOT_3(len, pins[1], pins[0]); break; @@ -578,6 +631,10 @@ class PolyBus { case I_8266_U1_APA106_3: (static_cast(busPtr))->Show(consistent); break; case I_8266_DM_APA106_3: (static_cast(busPtr))->Show(consistent); break; case I_8266_BB_APA106_3: (static_cast(busPtr))->Show(consistent); break; + case I_8266_U0_FW6_5: (static_cast(busPtr))->Show(consistent); break; + case I_8266_U1_FW6_5: (static_cast(busPtr))->Show(consistent); break; + case I_8266_DM_FW6_5: (static_cast(busPtr))->Show(consistent); break; + case I_8266_BB_FW6_5: (static_cast(busPtr))->Show(consistent); break; #endif #ifdef ARDUINO_ARCH_ESP32 case I_32_RN_NEO_3: (static_cast(busPtr))->Show(consistent); break; @@ -638,6 +695,13 @@ class PolyBus { case I_32_I1_APA106_3: (static_cast(busPtr))->Show(consistent); break; #endif // case I_32_BB_APA106_3: (static_cast(busPtr))->Show(consistent); break; + case I_32_RN_FW6_5: (static_cast(busPtr))->Show(consistent); break; + #ifndef WLED_NO_I2S0_PIXELBUS + case I_32_I0_FW6_5: (static_cast(busPtr))->Show(consistent); break; + #endif + #ifndef WLED_NO_I2S1_PIXELBUS + case I_32_I1_FW6_5: (static_cast(busPtr))->Show(consistent); break; + #endif #endif case I_HS_DOT_3: (static_cast(busPtr))->Show(consistent); break; case I_SS_DOT_3: (static_cast(busPtr))->Show(consistent); break; @@ -687,6 +751,10 @@ class PolyBus { case I_8266_U1_APA106_3: return (static_cast(busPtr))->CanShow(); break; case I_8266_DM_APA106_3: return (static_cast(busPtr))->CanShow(); break; case I_8266_BB_APA106_3: return (static_cast(busPtr))->CanShow(); break; + case I_8266_U0_FW6_5: return (static_cast(busPtr))->CanShow(); break; + case I_8266_U1_FW6_5: return (static_cast(busPtr))->CanShow(); break; + case I_8266_DM_FW6_5: return (static_cast(busPtr))->CanShow(); break; + case I_8266_BB_FW6_5: return (static_cast(busPtr))->CanShow(); break; #endif #ifdef ARDUINO_ARCH_ESP32 case I_32_RN_NEO_3: return (static_cast(busPtr))->CanShow(); break; @@ -747,6 +815,13 @@ class PolyBus { case I_32_I1_APA106_3: return (static_cast(busPtr))->CanShow(); break; #endif // case I_32_BB_APA106_3: return (static_cast(busPtr))->CanShow(); break; + case I_32_RN_FW6_5: return (static_cast(busPtr))->CanShow(); break; + #ifndef WLED_NO_I2S0_PIXELBUS + case I_32_I0_FW6_5: return (static_cast(busPtr))->CanShow(); break; + #endif + #ifndef WLED_NO_I2S1_PIXELBUS + case I_32_I1_FW6_5: return (static_cast(busPtr))->CanShow(); break; + #endif #endif case I_HS_DOT_3: return (static_cast(busPtr))->CanShow(); break; case I_SS_DOT_3: return (static_cast(busPtr))->CanShow(); break; @@ -821,6 +896,10 @@ class PolyBus { case I_8266_U1_APA106_3: (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_8266_DM_APA106_3: (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_8266_BB_APA106_3: (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; + case I_8266_U0_FW6_5: (static_cast(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break; + case I_8266_U1_FW6_5: (static_cast(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break; + case I_8266_DM_FW6_5: (static_cast(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break; + case I_8266_BB_FW6_5: (static_cast(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break; #endif #ifdef ARDUINO_ARCH_ESP32 case I_32_RN_NEO_3: (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; @@ -881,6 +960,13 @@ class PolyBus { case I_32_I1_APA106_3: (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; #endif // case I_32_BB_APA106_3: (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; + case I_32_RN_FW6_5: (static_cast(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break; + #ifndef WLED_NO_I2S0_PIXELBUS + case I_32_I0_FW6_5: (static_cast(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break; + #endif + #ifndef WLED_NO_I2S1_PIXELBUS + case I_32_I1_FW6_5: (static_cast(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break; + #endif #endif case I_HS_DOT_3: (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_SS_DOT_3: (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; @@ -931,6 +1017,10 @@ class PolyBus { case I_8266_U1_APA106_3: (static_cast(busPtr))->SetLuminance(b); break; case I_8266_DM_APA106_3: (static_cast(busPtr))->SetLuminance(b); break; case I_8266_BB_APA106_3: (static_cast(busPtr))->SetLuminance(b); break; + case I_8266_U0_FW6_5: (static_cast(busPtr))->SetLuminance(b); break; + case I_8266_U1_FW6_5: (static_cast(busPtr))->SetLuminance(b); break; + case I_8266_DM_FW6_5: (static_cast(busPtr))->SetLuminance(b); break; + case I_8266_BB_FW6_5: (static_cast(busPtr))->SetLuminance(b); break; #endif #ifdef ARDUINO_ARCH_ESP32 case I_32_RN_NEO_3: (static_cast(busPtr))->SetLuminance(b); break; @@ -991,6 +1081,14 @@ class PolyBus { case I_32_I1_APA106_3: (static_cast(busPtr))->SetLuminance(b); break; #endif // case I_32_BB_APA106_3: (static_cast(busPtr))->SetLuminance(b); break; + case I_32_RN_FW6_5: (static_cast(busPtr))->SetLuminance(b); break; + #ifndef WLED_NO_I2S0_PIXELBUS + case I_32_I0_FW6_5: (static_cast(busPtr))->SetLuminance(b); break; + #endif + #ifndef WLED_NO_I2S1_PIXELBUS + case I_32_I1_FW6_5: (static_cast(busPtr))->SetLuminance(b); break; + #endif + #endif case I_HS_DOT_3: (static_cast(busPtr))->SetLuminance(b); break; case I_SS_DOT_3: (static_cast(busPtr))->SetLuminance(b); break; @@ -1042,6 +1140,10 @@ class PolyBus { case I_8266_U1_APA106_3: col = (static_cast(busPtr))->GetPixelColor(pix); break; case I_8266_DM_APA106_3: col = (static_cast(busPtr))->GetPixelColor(pix); break; case I_8266_BB_APA106_3: col = (static_cast(busPtr))->GetPixelColor(pix); break; + case I_8266_U0_FW6_5: { RgbwwColor c = (static_cast(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.WW>>8); } break; + case I_8266_U1_FW6_5: { RgbwwColor c = (static_cast(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.WW>>8); } break; + case I_8266_DM_FW6_5: { RgbwwColor c = (static_cast(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.WW>>8); } break; + case I_8266_BB_FW6_5: { RgbwwColor c = (static_cast(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.WW>>8); } break; #endif #ifdef ARDUINO_ARCH_ESP32 case I_32_RN_NEO_3: col = (static_cast(busPtr))->GetPixelColor(pix); break; @@ -1102,6 +1204,13 @@ class PolyBus { case I_32_I1_APA106_3: col = (static_cast(busPtr))->GetPixelColor(pix); break; #endif // case I_32_BB_APA106_3: col = (static_cast(busPtr))->GetPixelColor(pix); break; + case I_32_RN_FW6_5: { RgbwwColor c = (static_cast(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.WW>>8); } break; + #ifndef WLED_NO_I2S0_PIXELBUS + case I_32_I0_FW6_5: { RgbwwColor c = (static_cast(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.WW>>8); } break; + #endif + #ifndef WLED_NO_I2S1_PIXELBUS + case I_32_I1_FW6_5: { RgbwwColor c = (static_cast(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.WW>>8); } break; + #endif #endif case I_HS_DOT_3: col = (static_cast(busPtr))->GetPixelColor(pix); break; case I_SS_DOT_3: col = (static_cast(busPtr))->GetPixelColor(pix); break; @@ -1171,6 +1280,10 @@ class PolyBus { case I_8266_U1_APA106_3: delete (static_cast(busPtr)); break; case I_8266_DM_APA106_3: delete (static_cast(busPtr)); break; case I_8266_BB_APA106_3: delete (static_cast(busPtr)); break; + case I_8266_U0_FW6_5: delete (static_cast(busPtr)); break; + case I_8266_U1_FW6_5: delete (static_cast(busPtr)); break; + case I_8266_DM_FW6_5: delete (static_cast(busPtr)); break; + case I_8266_BB_FW6_5: delete (static_cast(busPtr)); break; #endif #ifdef ARDUINO_ARCH_ESP32 case I_32_RN_NEO_3: delete (static_cast(busPtr)); break; @@ -1231,6 +1344,13 @@ class PolyBus { case I_32_I1_APA106_3: delete (static_cast(busPtr)); break; #endif // case I_32_BB_APA106_3: delete (static_cast(busPtr)); break; + case I_32_RN_FW6_5: delete (static_cast(busPtr)); break; + #ifndef WLED_NO_I2S0_PIXELBUS + case I_32_I0_FW6_5: delete (static_cast(busPtr)); break; + #endif + #ifndef WLED_NO_I2S1_PIXELBUS + case I_32_I1_FW6_5: delete (static_cast(busPtr)); break; + #endif #endif case I_HS_DOT_3: delete (static_cast(busPtr)); break; case I_SS_DOT_3: delete (static_cast(busPtr)); break; @@ -1292,6 +1412,8 @@ class PolyBus { return I_8266_U0_UCS_4 + offset; case TYPE_APA106: return I_8266_U0_APA106_3 + offset; + case TYPE_FW1906: + return I_8266_U0_FW6_5 + offset; } #else //ESP32 uint8_t offset = 0; //0 = RMT (num 0-7) 8 = I2S0 9 = I2S1 @@ -1332,6 +1454,8 @@ class PolyBus { return I_32_RN_UCS_4 + offset; case TYPE_APA106: return I_32_RN_APA106_3 + offset; + case TYPE_FW1906: + return I_32_RN_FW6_5 + offset; } #endif } @@ -1339,4 +1463,6 @@ class PolyBus { } }; -#endif \ No newline at end of file +uint8_t PolyBus::cctWW; +uint8_t PolyBus::cctCW; +#endif diff --git a/wled00/const.h b/wled00/const.h index dd965bc40..6f4c2649e 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -269,6 +269,7 @@ #define TYPE_TM1829 25 #define TYPE_UCS8903 26 #define TYPE_APA106 27 +#define TYPE_FW1906 28 //RGB + CW + WW + unused channel (6 channels per IC) #define TYPE_UCS8904 29 //first RGBW digital type (hardcoded in busmanager.cpp, memUsage()) #define TYPE_SK6812_RGBW 30 #define TYPE_TM1814 31 diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 611653a64..061d5a9ac 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -188,6 +188,7 @@ if (isDig(t)) { if (is16b(t)) len *= 2; // 16 bit LEDs if (t > 28 && t < 40) ch = 4; //RGBW + if (t == 28) ch = 5; //GRBCW if (maxM < 10000 && d.getElementsByName("L0"+n)[0].value == 3) { //8266 DMA uses 5x the mem mul = 5; } @@ -242,7 +243,7 @@ d.Sf["MA"+n].min = (isVir(t) || isAna(t)) ? 0 : 250; } gId("rf"+n).onclick = (t == 31) ? (()=>{return false}) : (()=>{}); // prevent change for TM1814 - gRGBW |= isRGBW = ((t > 17 && t < 22) || (t > 28 && t < 32) || (t > 40 && t < 46 && t != 43) || t == 88); // RGBW checkbox, TYPE_xxxx values from const.h + gRGBW |= isRGBW = ((t > 17 && t < 22) || (t > 27 && t < 32) || (t > 40 && t < 46 && t != 43) || t == 88); // RGBW checkbox, TYPE_xxxx values from const.h gId("co"+n).style.display = (isVir(t) || isAna(t)) ? "none":"inline"; // hide color order for PWM gId("dig"+n+"w").style.display = (isDig(t) && isRGBW) ? "inline":"none"; // show swap channels dropdown if (!(isDig(t) && isRGBW)) d.Sf["WO"+n].value = 0; // reset swapping @@ -383,6 +384,7 @@ ${i+1}: \ \ \ +\ \ \ \