From 760a1d45124903070a62944faf6f0f3e95e9bbaf Mon Sep 17 00:00:00 2001 From: TripleWhy Date: Sat, 13 Jan 2024 18:52:57 +0100 Subject: [PATCH 1/3] Make color_wheel rotate in HSV sapce instead of linearly interpolating R->G->B --- wled00/FX_fcn.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 96e397aba1..b28ce4c91f 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1022,20 +1022,23 @@ void Segment::blur(uint8_t blur_amount) { /* * Put a value 0 to 255 in to get a color value. * The colours are a transition r -> g -> b -> back to r - * Inspired by the Adafruit examples. + * Rotates the color in HSV space, where pos is H. (0=0deg, 256=360deg) */ uint32_t Segment::color_wheel(uint8_t pos) { if (palette) return color_from_palette(pos, false, true, 0); uint8_t w = W(currentColor(0)); - pos = 255 - pos; - if (pos < 85) { - return RGBW32((255 - pos * 3), 0, (pos * 3), w); - } else if(pos < 170) { - pos -= 85; - return RGBW32(0, (pos * 3), (255 - pos * 3), w); - } else { - pos -= 170; - return RGBW32((pos * 3), (255 - pos * 3), 0, w); + // These h and f values are the same h and f you have in the regular HSV to RGB conversion. + // The whole funciton really is just a HSV conversion, but assuming H=pos, S=1 and V=1. + const uint32_t h = (pos * 3) / 128; + const uint32_t f = (pos * 6) % 256; + switch (h) { + case 0: return RGBW32(255 , f , 0 , w); + case 1: return RGBW32(255 - f, 255 , 0 , w); + case 2: return RGBW32(0 , 255 , f , w); + case 3: return RGBW32(0 , 255 - f, 255 , w); + case 4: return RGBW32(f , 0 , 255 , w); + case 5: return RGBW32(255 , 0 , 255 - f, w); + default: return 0; } } From 43cab3f3499d486bf32dcb6d64167114ce88d723 Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Thu, 18 Jan 2024 15:43:37 +0100 Subject: [PATCH 2/3] optional alternate colorwheel --- wled00/FX_fcn.cpp | 38 ++++++++++++++++++++++++----------- wled00/cfg.cpp | 8 +++++--- wled00/colors.cpp | 10 ++++----- wled00/data/settings_leds.htm | 1 + wled00/set.cpp | 1 + wled00/wled.h | 1 + wled00/xml.cpp | 1 + 7 files changed, 40 insertions(+), 20 deletions(-) mode change 100755 => 100644 wled00/cfg.cpp mode change 100755 => 100644 wled00/set.cpp mode change 100755 => 100644 wled00/wled.h mode change 100755 => 100644 wled00/xml.cpp diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index b28ce4c91f..23476ad9aa 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1027,18 +1027,32 @@ void Segment::blur(uint8_t blur_amount) { uint32_t Segment::color_wheel(uint8_t pos) { if (palette) return color_from_palette(pos, false, true, 0); uint8_t w = W(currentColor(0)); - // These h and f values are the same h and f you have in the regular HSV to RGB conversion. - // The whole funciton really is just a HSV conversion, but assuming H=pos, S=1 and V=1. - const uint32_t h = (pos * 3) / 128; - const uint32_t f = (pos * 6) % 256; - switch (h) { - case 0: return RGBW32(255 , f , 0 , w); - case 1: return RGBW32(255 - f, 255 , 0 , w); - case 2: return RGBW32(0 , 255 , f , w); - case 3: return RGBW32(0 , 255 - f, 255 , w); - case 4: return RGBW32(f , 0 , 255 , w); - case 5: return RGBW32(255 , 0 , 255 - f, w); - default: return 0; + if (useAltWheel) { + // by @TripleWhy https://github.com/Aircoookie/WLED/pull/3681 (https://github.com/TripleWhy) + // These h and f values are the same h and f you have in the regular HSV to RGB conversion. + // The whole funciton really is just a HSV conversion, but assuming H=pos, S=1 and V=1. + const uint32_t h = (pos * 3) / 128; + const uint32_t f = (pos * 6) % 256; + switch (h) { + case 0: return RGBW32(255 , f , 0 , w); + case 1: return RGBW32(255 - f, 255 , 0 , w); + case 2: return RGBW32(0 , 255 , f , w); + case 3: return RGBW32(0 , 255 - f, 255 , w); + case 4: return RGBW32(f , 0 , 255 , w); + case 5: return RGBW32(255 , 0 , 255 - f, w); + default: return 0; + } + } else { + pos = 255 - pos; + if (pos < 85) { + return RGBW32((255 - pos * 3), 0, (pos * 3), w); + } else if(pos < 170) { + pos -= 85; + return RGBW32(0, (pos * 3), (255 - pos * 3), w); + } else { + pos -= 170; + return RGBW32((pos * 3), (255 - pos * 3), 0, w); + } } } diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp old mode 100755 new mode 100644 index 1234a1c5f8..c4f9c72082 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -315,7 +315,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { if (serialBaud < 96 || serialBaud > 15000) serialBaud = 1152; updateBaudRate(serialBaud *100); - JsonArray hw_if_i2c = hw[F("if")][F("i2c-pin")]; + JsonArray hw_if_i2c = hw["if"][F("i2c-pin")]; CJSON(i2c_sda, hw_if_i2c[0]); CJSON(i2c_scl, hw_if_i2c[1]); PinManagerPinType i2c[2] = { { i2c_sda, true }, { i2c_scl, true } }; @@ -330,7 +330,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { i2c_sda = -1; i2c_scl = -1; } - JsonArray hw_if_spi = hw[F("if")][F("spi-pin")]; + JsonArray hw_if_spi = hw["if"][F("spi-pin")]; CJSON(spi_mosi, hw_if_spi[0]); CJSON(spi_sclk, hw_if_spi[1]); CJSON(spi_miso, hw_if_spi[2]); @@ -353,6 +353,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(briMultiplier, light[F("scale-bri")]); CJSON(strip.paletteBlend, light[F("pal-mode")]); CJSON(autoSegments, light[F("aseg")]); + CJSON(useAltWheel, light[F("alt-wheel")]); CJSON(gammaCorrectVal, light["gc"]["val"]); // default 2.8 float light_gc_bri = light["gc"]["bri"]; @@ -821,7 +822,7 @@ void serializeConfig() { hw[F("baud")] = serialBaud; - JsonObject hw_if = hw.createNestedObject(F("if")); + JsonObject hw_if = hw.createNestedObject("if"); JsonArray hw_if_i2c = hw_if.createNestedArray("i2c-pin"); hw_if_i2c.add(i2c_sda); hw_if_i2c.add(i2c_scl); @@ -837,6 +838,7 @@ void serializeConfig() { light[F("scale-bri")] = briMultiplier; light[F("pal-mode")] = strip.paletteBlend; light[F("aseg")] = autoSegments; + light[F("alt-wheel")] = useAltWheel; JsonObject light_gc = light.createNestedObject("gc"); light_gc["bri"] = (gammaCorrectBri) ? gammaCorrectVal : 1.0f; // keep compatibility diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 21c27d651c..a9d3e3bc0b 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -93,13 +93,13 @@ void setRandomColor(byte* rgb) void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb { - float h = ((float)hue)/65535.0f; + float h = ((float)hue)/10922.5f; // hue*6/65535 float s = ((float)sat)/255.0f; - int i = floorf(h*6); - float f = h * 6.0f - i; + int i = int(h); + float f = h - i; int p = int(255.0f * (1.0f-s)); - int q = int(255.0f * (1.0f-f*s)); - int t = int(255.0f * (1.0f-(1.0f-f)*s)); + int q = int(255.0f * (1.0f-s*f)); + int t = int(255.0f * (1.0f-s*(1.0f-f))); p = constrain(p, 0, 255); q = constrain(q, 0, 255); t = constrain(t, 0, 255); diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index ae1063f7dc..91968c41b0 100755 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -879,6 +879,7 @@

Advanced


+ Alt color wheel:
Target refresh rate: FPS
Config template:
diff --git a/wled00/set.cpp b/wled00/set.cpp old mode 100755 new mode 100644 index e839117836..4c719495ce --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -286,6 +286,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) strip.paletteFade = request->hasArg(F("PF")); t = request->arg(F("TP")).toInt(); randomPaletteChangeTime = MIN(255,MAX(1,t)); + useAltWheel = request->hasArg(F("ACW")); nightlightTargetBri = request->arg(F("TB")).toInt(); t = request->arg(F("TL")).toInt(); diff --git a/wled00/wled.h b/wled00/wled.h old mode 100755 new mode 100644 index 217acd6272..acb19b94bb --- a/wled00/wled.h +++ b/wled00/wled.h @@ -347,6 +347,7 @@ WLED_GLOBAL bool cctFromRgb _INIT(false); // CCT is calculated from RGB WLED_GLOBAL bool gammaCorrectCol _INIT(true); // use gamma correction on colors WLED_GLOBAL bool gammaCorrectBri _INIT(false); // use gamma correction on brightness WLED_GLOBAL float gammaCorrectVal _INIT(2.8f); // gamma correction value +WLED_GLOBAL bool useAltWheel _INIT(false); // alternate method for calculating Segment::color_wheel() WLED_GLOBAL byte col[] _INIT_N(({ 255, 160, 0, 0 })); // current RGB(W) primary color. col[] should be updated if you want to change the color. WLED_GLOBAL byte colSec[] _INIT_N(({ 0, 0, 0, 0 })); // current RGB(W) secondary color diff --git a/wled00/xml.cpp b/wled00/xml.cpp old mode 100755 new mode 100644 index de183c5a6d..f82c3897a0 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -461,6 +461,7 @@ void getSettingsJS(byte subPage, char* dest) sappend('v',SET_F("IR"),irPin); sappend('v',SET_F("IT"),irEnabled); sappend('c',SET_F("MSO"),!irApplyToAllSelected); + sappend('c',SET_F("ACW"),useAltWheel); } if (subPage == SUBPAGE_UI) From 86bb4ad041507f6fda8b57e5a5bc95efa04fc77c Mon Sep 17 00:00:00 2001 From: TripleWhy Date: Thu, 18 Jan 2024 21:03:49 +0100 Subject: [PATCH 3/3] Restore original credit comment for the original color_wheel version --- wled00/FX_fcn.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 30e66fafcd..ddd7511c25 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1022,13 +1022,13 @@ void Segment::blur(uint8_t blur_amount) { /* * Put a value 0 to 255 in to get a color value. * The colours are a transition r -> g -> b -> back to r - * Rotates the color in HSV space, where pos is H. (0=0deg, 256=360deg) */ uint32_t Segment::color_wheel(uint8_t pos) { if (palette) return color_from_palette(pos, false, true, 0); uint8_t w = W(currentColor(0)); if (useAltWheel) { // by @TripleWhy https://github.com/Aircoookie/WLED/pull/3681 (https://github.com/TripleWhy) + // Rotates the color in HSV space, where pos is H. (0=0deg, 256=360deg) // These h and f values are the same h and f you have in the regular HSV to RGB conversion. // The whole funciton really is just a HSV conversion, but assuming H=pos, S=1 and V=1. const uint32_t h = (pos * 3) / 128; @@ -1043,6 +1043,7 @@ uint32_t Segment::color_wheel(uint8_t pos) { default: return 0; } } else { + // Inspired by the Adafruit examples. pos = 255 - pos; if (pos < 85) { return RGBW32((255 - pos * 3), 0, (pos * 3), w);