Set to \"*\" to "
"connect to any die. Leave Blank to disable. Saving will replace \"*\" with die names.','');"));
#if USING_TFT_DISPLAY
- oappend(SET_F("ddr=addDropdown('DiceTray','rotation');"));
- oappend(SET_F("addOption(ddr,'0 deg',0);"));
- oappend(SET_F("addOption(ddr,'90 deg',1);"));
- oappend(SET_F("addOption(ddr,'180 deg',2);"));
- oappend(SET_F("addOption(ddr,'270 deg',3);"));
- oappend(SET_F(
+ oappend(F("ddr=addDropdown('DiceTray','rotation');"));
+ oappend(F("addOption(ddr,'0 deg',0);"));
+ oappend(F("addOption(ddr,'90 deg',1);"));
+ oappend(F("addOption(ddr,'180 deg',2);"));
+ oappend(F("addOption(ddr,'270 deg',3);"));
+ oappend(F(
"addInfo('DiceTray:rotation',1,' DO NOT CHANGE "
"SPI PINS. CHANGES ARE IGNORED.','');"));
- oappend(SET_F("addInfo('TFT:pin[]',0,'','SPI CS');"));
- oappend(SET_F("addInfo('TFT:pin[]',1,'','SPI DC');"));
- oappend(SET_F("addInfo('TFT:pin[]',2,'','SPI RST');"));
- oappend(SET_F("addInfo('TFT:pin[]',3,'','SPI BL');"));
+ oappend(F("addInfo('TFT:pin[]',0,'','SPI CS');"));
+ oappend(F("addInfo('TFT:pin[]',1,'','SPI DC');"));
+ oappend(F("addInfo('TFT:pin[]',2,'','SPI RST');"));
+ oappend(F("addInfo('TFT:pin[]',3,'','SPI BL');"));
#endif
}
diff --git a/usermods/sht/usermod_sht.h b/usermods/sht/usermod_sht.h
index c6e17221b..f10c78a25 100644
--- a/usermods/sht/usermod_sht.h
+++ b/usermods/sht/usermod_sht.h
@@ -310,22 +310,22 @@ void ShtUsermod::onMqttConnect(bool sessionPresent) {
* @return void
*/
void ShtUsermod::appendConfigData() {
- oappend(SET_F("dd=addDropdown('"));
+ oappend(F("dd=addDropdown('"));
oappend(_name);
- oappend(SET_F("','"));
+ oappend(F("','"));
oappend(_shtType);
- oappend(SET_F("');"));
- oappend(SET_F("addOption(dd,'SHT30',0);"));
- oappend(SET_F("addOption(dd,'SHT31',1);"));
- oappend(SET_F("addOption(dd,'SHT35',2);"));
- oappend(SET_F("addOption(dd,'SHT85',3);"));
- oappend(SET_F("dd=addDropdown('"));
+ oappend(F("');"));
+ oappend(F("addOption(dd,'SHT30',0);"));
+ oappend(F("addOption(dd,'SHT31',1);"));
+ oappend(F("addOption(dd,'SHT35',2);"));
+ oappend(F("addOption(dd,'SHT85',3);"));
+ oappend(F("dd=addDropdown('"));
oappend(_name);
- oappend(SET_F("','"));
+ oappend(F("','"));
oappend(_unitOfTemp);
- oappend(SET_F("');"));
- oappend(SET_F("addOption(dd,'Celsius',0);"));
- oappend(SET_F("addOption(dd,'Fahrenheit',1);"));
+ oappend(F("');"));
+ oappend(F("addOption(dd,'Celsius',0);"));
+ oappend(F("addOption(dd,'Fahrenheit',1);"));
}
/**
diff --git a/usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h b/usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h
index f712316b8..707479df1 100644
--- a/usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h
+++ b/usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h
@@ -96,7 +96,7 @@ void setup() {
jsonTransitionOnce = true;
strip.setTransition(0); //no transition
effectCurrent = FX_MODE_COLOR_WIPE;
- resetTimebase(); //make sure wipe starts from beginning
+ strip.resetTimebase(); //make sure wipe starts from beginning
//set wipe direction
Segment& seg = strip.getSegment(0);
diff --git a/usermods/stairway_wipe_basic/wled06_usermod.ino b/usermods/stairway_wipe_basic/wled06_usermod.ino
index c1264ebfb..dc2159ee9 100644
--- a/usermods/stairway_wipe_basic/wled06_usermod.ino
+++ b/usermods/stairway_wipe_basic/wled06_usermod.ino
@@ -86,7 +86,7 @@ void startWipe()
bri = briLast; //turn on
transitionDelayTemp = 0; //no transition
effectCurrent = FX_MODE_COLOR_WIPE;
- resetTimebase(); //make sure wipe starts from beginning
+ strip.resetTimebase(); //make sure wipe starts from beginning
//set wipe direction
Segment& seg = strip.getSegment(0);
diff --git a/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h b/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h
index dfab7e6ff..684dd86e4 100644
--- a/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h
+++ b/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h
@@ -1202,21 +1202,21 @@ void FourLineDisplayUsermod::onUpdateBegin(bool init) {
//}
void FourLineDisplayUsermod::appendConfigData() {
- oappend(SET_F("dd=addDropdown('4LineDisplay','type');"));
- oappend(SET_F("addOption(dd,'None',0);"));
- oappend(SET_F("addOption(dd,'SSD1306',1);"));
- oappend(SET_F("addOption(dd,'SH1106',2);"));
- oappend(SET_F("addOption(dd,'SSD1306 128x64',3);"));
- oappend(SET_F("addOption(dd,'SSD1305',4);"));
- oappend(SET_F("addOption(dd,'SSD1305 128x64',5);"));
- oappend(SET_F("addOption(dd,'SSD1309 128x64',9);"));
- oappend(SET_F("addOption(dd,'SSD1306 SPI',6);"));
- oappend(SET_F("addOption(dd,'SSD1306 SPI 128x64',7);"));
- oappend(SET_F("addOption(dd,'SSD1309 SPI 128x64',8);"));
- oappend(SET_F("addInfo('4LineDisplay:type',1,' Change may require reboot','');"));
- oappend(SET_F("addInfo('4LineDisplay:pin[]',0,'','SPI CS');"));
- oappend(SET_F("addInfo('4LineDisplay:pin[]',1,'','SPI DC');"));
- oappend(SET_F("addInfo('4LineDisplay:pin[]',2,'','SPI RST');"));
+ oappend(F("dd=addDropdown('4LineDisplay','type');"));
+ oappend(F("addOption(dd,'None',0);"));
+ oappend(F("addOption(dd,'SSD1306',1);"));
+ oappend(F("addOption(dd,'SH1106',2);"));
+ oappend(F("addOption(dd,'SSD1306 128x64',3);"));
+ oappend(F("addOption(dd,'SSD1305',4);"));
+ oappend(F("addOption(dd,'SSD1305 128x64',5);"));
+ oappend(F("addOption(dd,'SSD1309 128x64',9);"));
+ oappend(F("addOption(dd,'SSD1306 SPI',6);"));
+ oappend(F("addOption(dd,'SSD1306 SPI 128x64',7);"));
+ oappend(F("addOption(dd,'SSD1309 SPI 128x64',8);"));
+ oappend(F("addInfo('4LineDisplay:type',1,' Change may require reboot','');"));
+ oappend(F("addInfo('4LineDisplay:pin[]',0,'','SPI CS');"));
+ oappend(F("addInfo('4LineDisplay:pin[]',1,'','SPI DC');"));
+ oappend(F("addInfo('4LineDisplay:pin[]',2,'','SPI RST');"));
}
/*
diff --git a/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h b/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h
index 55715b7c7..383c1193e 100644
--- a/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h
+++ b/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h
@@ -1090,8 +1090,8 @@ void RotaryEncoderUIUsermod::addToConfig(JsonObject &root) {
}
void RotaryEncoderUIUsermod::appendConfigData() {
- oappend(SET_F("addInfo('Rotary-Encoder:PCF8574-address',1,'(not hex!)');"));
- oappend(SET_F("d.extra.push({'Rotary-Encoder':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});"));
+ oappend(F("addInfo('Rotary-Encoder:PCF8574-address',1,'(not hex!)');"));
+ oappend(F("d.extra.push({'Rotary-Encoder':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});"));
}
/**
diff --git a/usermods/usermod_v2_word_clock/usermod_v2_word_clock.h b/usermods/usermod_v2_word_clock/usermod_v2_word_clock.h
index b66be290a..7ecec08e5 100644
--- a/usermods/usermod_v2_word_clock/usermod_v2_word_clock.h
+++ b/usermods/usermod_v2_word_clock/usermod_v2_word_clock.h
@@ -433,8 +433,8 @@ class WordClockUsermod : public Usermod
void appendConfigData()
{
- oappend(SET_F("addInfo('WordClockUsermod:ledOffset', 1, 'Number of LEDs before the letters');"));
- oappend(SET_F("addInfo('WordClockUsermod:Norddeutsch', 1, 'Viertel vor instead of Dreiviertel');"));
+ oappend(F("addInfo('WordClockUsermod:ledOffset', 1, 'Number of LEDs before the letters');"));
+ oappend(F("addInfo('WordClockUsermod:Norddeutsch', 1, 'Viertel vor instead of Dreiviertel');"));
}
/*
diff --git a/usermods/wireguard/wireguard.h b/usermods/wireguard/wireguard.h
index 8c88d0001..8656a704a 100644
--- a/usermods/wireguard/wireguard.h
+++ b/usermods/wireguard/wireguard.h
@@ -54,13 +54,13 @@ class WireguardUsermod : public Usermod {
}
void appendConfigData() {
- oappend(SET_F("addInfo('WireGuard:host',1,'Server Hostname');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:port',1,'Server Port');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:ip',1,'Device IP');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:psk',1,'Pre Shared Key (optional)');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:pem',1,'Private Key');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:pub',1,'Public Key');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:tz',1,'POSIX timezone string');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('WireGuard:host',1,'Server Hostname');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('WireGuard:port',1,'Server Port');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('WireGuard:ip',1,'Device IP');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('WireGuard:psk',1,'Pre Shared Key (optional)');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('WireGuard:pem',1,'Private Key');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('WireGuard:pub',1,'Public Key');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('WireGuard:tz',1,'POSIX timezone string');")); // 0 is field type, 1 is actual field
}
void addToConfig(JsonObject& root) {
diff --git a/wled00/FX.cpp b/wled00/FX.cpp
index 77167b02d..97169cf0d 100644
--- a/wled00/FX.cpp
+++ b/wled00/FX.cpp
@@ -2,24 +2,10 @@
WS2812FX.cpp contains all effect methods
Harm Aldick - 2016
www.aldick.org
- LICENSE
- The MIT License (MIT)
+
Copyright (c) 2016 Harm Aldick
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
+ Licensed under the EUPL v. 1.2 or later
+ Adapted from code originally licensed under the MIT license
Modified heavily for WLED
*/
@@ -2516,9 +2502,9 @@ static uint16_t ripple_base() {
#endif
{
int left = rippleorigin - propI -1;
- int right = rippleorigin + propI +3;
+ int right = rippleorigin + propI +2;
for (int v = 0; v < 4; v++) {
- unsigned mag = scale8(cubicwave8((propF>>2)+(v-left)*64), amp);
+ unsigned mag = scale8(cubicwave8((propF>>2) + v * 64), amp);
SEGMENT.setPixelColor(left + v, color_blend(SEGMENT.getPixelColor(left + v), col, mag)); // TODO
SEGMENT.setPixelColor(right - v, color_blend(SEGMENT.getPixelColor(right - v), col, mag)); // TODO
}
@@ -4027,7 +4013,7 @@ uint16_t mode_pacifica()
// Increment the four "color index start" counters, one for each wave layer.
// Each is incremented at a different speed, and the speeds vary over time.
- unsigned sCIStart1 = SEGENV.aux0, sCIStart2 = SEGENV.aux1, sCIStart3 = SEGENV.step, sCIStart4 = SEGENV.step >> 16;
+ unsigned sCIStart1 = SEGENV.aux0, sCIStart2 = SEGENV.aux1, sCIStart3 = SEGENV.step & 0xFFFF, sCIStart4 = (SEGENV.step >> 16);
uint32_t deltams = (FRAMETIME >> 2) + ((FRAMETIME * SEGMENT.speed) >> 7);
uint64_t deltat = (strip.now >> 2) + ((strip.now * SEGMENT.speed) >> 7);
strip.now = deltat;
@@ -4042,7 +4028,7 @@ uint16_t mode_pacifica()
sCIStart3 -= (deltams1 * beatsin88(501,5,7));
sCIStart4 -= (deltams2 * beatsin88(257,4,6));
SEGENV.aux0 = sCIStart1; SEGENV.aux1 = sCIStart2;
- SEGENV.step = sCIStart4; SEGENV.step = (SEGENV.step << 16) + sCIStart3;
+ SEGENV.step = (sCIStart4 << 16) | (sCIStart3 & 0xFFFF);
// Clear out the LED array to a dim background blue-green
//SEGMENT.fill(132618);
@@ -4920,8 +4906,8 @@ uint16_t mode_2DColoredBursts() { // By: ldirko https://editor.so
SEGMENT.fadeToBlackBy(40);
for (size_t i = 0; i < numLines; i++) {
byte x1 = beatsin8(2 + SEGMENT.speed/16, 0, (cols - 1));
- byte x2 = beatsin8(1 + SEGMENT.speed/16, 0, (cols - 1));
- byte y1 = beatsin8(5 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 24);
+ byte x2 = beatsin8(1 + SEGMENT.speed/16, 0, (rows - 1));
+ byte y1 = beatsin8(5 + SEGMENT.speed/16, 0, (cols - 1), 0, i * 24);
byte y2 = beatsin8(3 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 48 + 64);
uint32_t color = ColorFromPalette(SEGPALETTE, i * 255 / numLines + (SEGENV.aux0&0xFF), 255, LINEARBLEND);
@@ -4999,9 +4985,11 @@ uint16_t mode_2DDNASpiral() { // By: ldirko https://editor.soulma
// draw a gradient line between x and x1
x = x / 2; x1 = x1 / 2;
unsigned steps = abs8(x - x1) + 1;
+ bool positive = (x1 >= x); // direction of drawing
for (size_t k = 1; k <= steps; k++) {
unsigned rate = k * 255 / steps;
- unsigned dx = lerp8by8(x, x1, rate);
+ //unsigned dx = lerp8by8(x, x1, rate);
+ unsigned dx = positive? (x + k-1) : (x - k+1); // behaves the same as "lerp8by8" but does not create holes
//SEGMENT.setPixelColorXY(dx, i, ColorFromPalette(SEGPALETTE, hue, 255, LINEARBLEND).nscale8_video(rate));
SEGMENT.addPixelColorXY(dx, i, ColorFromPalette(SEGPALETTE, hue, 255, LINEARBLEND)); // use setPixelColorXY for different look
SEGMENT.fadePixelColorXY(dx, i, rate);
@@ -7516,8 +7504,9 @@ uint16_t mode_2DAkemi(void) {
//add geq left and right
if (um_data && fftResult) {
- for (int x=0; x < cols/8; x++) {
- unsigned band = x * cols/8;
+ int xMax = cols/8;
+ for (int x=0; x < xMax; x++) {
+ unsigned band = map(x, 0, max(xMax,4), 0, 15); // map 0..cols/8 to 16 GEQ bands
band = constrain(band, 0, 15);
int barHeight = map(fftResult[band], 0, 255, 0, 17*rows/32);
uint32_t color = SEGMENT.color_from_palette((band * 35), false, PALETTE_SOLID_WRAP, 0);
@@ -7734,7 +7723,7 @@ uint16_t mode_2Doctopus() {
const int C_Y = (rows / 2) + ((SEGMENT.custom2 - 128)*rows)/255;
for (int x = 0; x < cols; x++) {
for (int y = 0; y < rows; y++) {
- rMap[XY(x, y)].angle = 40.7436f * atan2f((y - C_Y), (x - C_X)); // avoid 128*atan2()/PI
+ rMap[XY(x, y)].angle = int(40.7436f * atan2f((y - C_Y), (x - C_X))); // avoid 128*atan2()/PI
rMap[XY(x, y)].radius = hypotf((x - C_X), (y - C_Y)) * mapp; //thanks Sutaburosu
}
}
diff --git a/wled00/FX.h b/wled00/FX.h
index d56c0fa99..f18aa0175 100644
--- a/wled00/FX.h
+++ b/wled00/FX.h
@@ -2,24 +2,10 @@
WS2812FX.h - Library for WS2812 LED effects.
Harm Aldick - 2016
www.aldick.org
- LICENSE
- The MIT License (MIT)
+
Copyright (c) 2016 Harm Aldick
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
+ Licensed under the EUPL v. 1.2 or later
+ Adapted from code originally licensed under the MIT license
Modified for WLED
*/
@@ -65,6 +51,15 @@ extern byte realtimeMode; // used in getMappedPixelIndex()
#define FRAMETIME_FIXED (1000/WLED_FPS)
#define FRAMETIME strip.getFrameTime()
+// FPS calculation (can be defined as compile flag for debugging)
+#ifndef FPS_CALC_AVG
+#define FPS_CALC_AVG 7 // average FPS calculation over this many frames (moving average)
+#endif
+#ifndef FPS_MULTIPLIER
+#define FPS_MULTIPLIER 1 // dev option: multiplier to get sub-frame FPS without floats
+#endif
+#define FPS_CALC_SHIFT 7 // bit shift for fixed point math
+
/* each segment uses 82 bytes of SRAM memory, so if you're application fails because of
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
#ifdef ESP8266
@@ -556,12 +551,12 @@ typedef struct Segment {
void beginDraw(); // set up parameters for current effect
void setGeometry(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1, uint8_t m12=0);
- bool setColor(uint8_t slot, uint32_t c); //returns true if changed
- void setCCT(uint16_t k);
- void setOpacity(uint8_t o);
- void setOption(uint8_t n, bool val);
- void setMode(uint8_t fx, bool loadDefaults = false);
- void setPalette(uint8_t pal);
+ Segment &setColor(uint8_t slot, uint32_t c);
+ Segment &setCCT(uint16_t k);
+ Segment &setOpacity(uint8_t o);
+ Segment &setOption(uint8_t n, bool val);
+ Segment &setMode(uint8_t fx, bool loadDefaults = false);
+ Segment &setPalette(uint8_t pal);
uint8_t differs(const Segment& b) const;
void refreshLightCapabilities();
@@ -576,7 +571,7 @@ typedef struct Segment {
* Call resetIfRequired before calling the next effect function.
* Safe to call from interrupts and network requests.
*/
- inline void markForReset() { reset = true; } // setOption(SEG_OPTION_RESET, true)
+ inline Segment &markForReset() { reset = true; return *this; } // setOption(SEG_OPTION_RESET, true)
// transition functions
void startTransition(uint16_t dur); // transition has to start before actual segment values change
@@ -627,9 +622,15 @@ typedef struct Segment {
}
// 2D matrix
- [[gnu::hot]] uint16_t virtualWidth() const; // segment width in virtual pixels (accounts for groupping and spacing)
- [[gnu::hot]] uint16_t virtualHeight() const; // segment height in virtual pixels (accounts for groupping and spacing)
- uint16_t nrOfVStrips() const; // returns number of virtual vertical strips in 2D matrix (used to expand 1D effects into 2D)
+ [[gnu::hot]] unsigned virtualWidth() const; // segment width in virtual pixels (accounts for groupping and spacing)
+ [[gnu::hot]] unsigned virtualHeight() const; // segment height in virtual pixels (accounts for groupping and spacing)
+ inline unsigned nrOfVStrips() const { // returns number of virtual vertical strips in 2D matrix (used to expand 1D effects into 2D)
+ #ifndef WLED_DISABLE_2D
+ return (is2D() && map1D2D == M12_pBar) ? virtualWidth() : 1;
+ #else
+ return 1;
+ #endif
+ }
#ifndef WLED_DISABLE_2D
[[gnu::hot]] uint16_t XY(int x, int y); // support function to get relative index within segment
[[gnu::hot]] void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
@@ -731,7 +732,11 @@ class WS2812FX { // 96 bytes
#ifndef WLED_DISABLE_2D
panels(1),
#endif
+#ifdef WLED_AUTOSEGMENTS
+ autoSegments(true),
+#else
autoSegments(false),
+#endif
correctWB(false),
cctFromRgb(false),
// true private variables
@@ -741,7 +746,7 @@ class WS2812FX { // 96 bytes
_transitionDur(750),
_targetFps(WLED_FPS),
_frametime(FRAMETIME_FIXED),
- _cumulativeFps(2),
+ _cumulativeFps(50 << FPS_CALC_SHIFT),
_isServicing(false),
_isOffRefreshRequired(false),
_hasWhiteChannel(false),
@@ -793,7 +798,8 @@ class WS2812FX { // 96 bytes
setTargetFps(unsigned fps),
setupEffectData(); // add default effects to the list; defined in FX.cpp
- inline void restartRuntime() { for (Segment &seg : _segments) seg.markForReset(); }
+ inline void resetTimebase() { timebase = 0UL - millis(); }
+ inline void restartRuntime() { for (Segment &seg : _segments) { seg.markForReset().resetIfRequired(); } }
inline void setTransitionMode(bool t) { for (Segment &seg : _segments) seg.startTransition(t ? _transitionDur : 0); }
inline void setPixelColor(unsigned n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); }
inline void setPixelColor(unsigned n, CRGB c) { setPixelColor(n, c.red, c.green, c.blue); }
@@ -841,7 +847,7 @@ class WS2812FX { // 96 bytes
getLengthPhysical() const,
getLengthTotal() const; // will include virtual/nonexistent pixels in matrix
- inline uint16_t getFps() const { return (millis() - _lastShow > 2000) ? 0 : _cumulativeFps +1; } // Returns the refresh rate of the LED strip
+ inline uint16_t getFps() const { return (millis() - _lastShow > 2000) ? 0 : (FPS_MULTIPLIER * _cumulativeFps) >> FPS_CALC_SHIFT; } // Returns the refresh rate of the LED strip (_cumulativeFps is stored in fixed point)
inline uint16_t getFrameTime() const { return _frametime; } // returns amount of time a frame should take (in ms)
inline uint16_t getMinShowDelay() const { return MIN_SHOW_DELAY; } // returns minimum amount of time strip.service() can be delayed (constant)
inline uint16_t getLength() const { return _length; } // returns actual amount of LEDs on a strip (2D matrix may have less LEDs than W*H)
@@ -851,7 +857,7 @@ class WS2812FX { // 96 bytes
return index;
};
- uint32_t now, timebase;
+ unsigned long now, timebase;
uint32_t getPixelColor(unsigned) const;
inline uint32_t getLastShow() const { return _lastShow; } // returns millis() timestamp of last strip.show() call
diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp
index 5a7dc76d3..adb9f8bca 100644
--- a/wled00/FX_2Dfcn.cpp
+++ b/wled00/FX_2Dfcn.cpp
@@ -1,24 +1,9 @@
/*
FX_2Dfcn.cpp contains all 2D utility functions
- LICENSE
- The MIT License (MIT)
Copyright (c) 2022 Blaz Kristan (https://blaz.at/home)
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
+ Licensed under the EUPL v. 1.2 or later
+ Adapted from code originally licensed under the MIT license
Parts of the code adapted from WLED Sound Reactive
*/
@@ -273,8 +258,8 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
// returns RGBW values of pixel
uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const {
if (!isActive()) return 0; // not active
- int vW = vWidth();
- int vH = vHeight();
+ const int vW = vWidth();
+ const int vH = vHeight();
if (unsigned(x) >= unsigned(vW) || unsigned(y) >= unsigned(vH)) return 0; // if pixel would fall out of virtual segment just exit
if (reverse ) x = vW - x - 1;
if (reverse_y) y = vH - y - 1;
@@ -684,11 +669,14 @@ void Segment::wu_pixel(uint32_t x, uint32_t y, CRGB c) { //awesome wu_pixel
WU_WEIGHT(ix, yy), WU_WEIGHT(xx, yy)};
// multiply the intensities by the colour, and saturating-add them to the pixels
for (int i = 0; i < 4; i++) {
- CRGB led = getPixelColorXY((x >> 8) + (i & 1), (y >> 8) + ((i >> 1) & 1));
+ int wu_x = (x >> 8) + (i & 1); // precalculate x
+ int wu_y = (y >> 8) + ((i >> 1) & 1); // precalculate y
+ CRGB led = getPixelColorXY(wu_x, wu_y);
+ CRGB oldLed = led;
led.r = qadd8(led.r, c.r * wu[i] >> 8);
led.g = qadd8(led.g, c.g * wu[i] >> 8);
led.b = qadd8(led.b, c.b * wu[i] >> 8);
- setPixelColorXY(int((x >> 8) + (i & 1)), int((y >> 8) + ((i >> 1) & 1)), led);
+ if (led != oldLed) setPixelColorXY(wu_x, wu_y, led); // don't repaint if same color
}
}
#undef WU_WEIGHT
diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp
index 69b0c028a..0020b5d94 100644
--- a/wled00/FX_fcn.cpp
+++ b/wled00/FX_fcn.cpp
@@ -2,24 +2,10 @@
WS2812FX_fcn.cpp contains all utility functions
Harm Aldick - 2016
www.aldick.org
- LICENSE
- The MIT License (MIT)
+
Copyright (c) 2016 Harm Aldick
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
+ Licensed under the EUPL v. 1.2 or later
+ Adapted from code originally licensed under the MIT license
Modified heavily for WLED
*/
@@ -554,46 +540,53 @@ void Segment::setGeometry(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, ui
}
-bool Segment::setColor(uint8_t slot, uint32_t c) { //returns true if changed
- if (slot >= NUM_COLORS || c == colors[slot]) return false;
+Segment &Segment::setColor(uint8_t slot, uint32_t c) {
+ if (slot >= NUM_COLORS || c == colors[slot]) return *this;
if (!_isRGB && !_hasW) {
- if (slot == 0 && c == BLACK) return false; // on/off segment cannot have primary color black
- if (slot == 1 && c != BLACK) return false; // on/off segment cannot have secondary color non black
+ if (slot == 0 && c == BLACK) return *this; // on/off segment cannot have primary color black
+ if (slot == 1 && c != BLACK) return *this; // on/off segment cannot have secondary color non black
}
if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change
colors[slot] = c;
stateChanged = true; // send UDP/WS broadcast
- return true;
+ return *this;
}
-void Segment::setCCT(uint16_t k) {
+Segment &Segment::setCCT(uint16_t k) {
if (k > 255) { //kelvin value, convert to 0-255
if (k < 1900) k = 1900;
if (k > 10091) k = 10091;
k = (k - 1900) >> 5;
}
- if (cct == k) return;
- if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change
- cct = k;
- stateChanged = true; // send UDP/WS broadcast
+ if (cct != k) {
+ //DEBUGFX_PRINTF_P(PSTR("- Starting CCT transition: %d\n"), k);
+ startTransition(strip.getTransition()); // start transition prior to change
+ cct = k;
+ stateChanged = true; // send UDP/WS broadcast
+ }
+ return *this;
}
-void Segment::setOpacity(uint8_t o) {
- if (opacity == o) return;
- if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change
- opacity = o;
- stateChanged = true; // send UDP/WS broadcast
+Segment &Segment::setOpacity(uint8_t o) {
+ if (opacity != o) {
+ //DEBUGFX_PRINTF_P(PSTR("- Starting opacity transition: %d\n"), o);
+ startTransition(strip.getTransition()); // start transition prior to change
+ opacity = o;
+ stateChanged = true; // send UDP/WS broadcast
+ }
+ return *this;
}
-void Segment::setOption(uint8_t n, bool val) {
+Segment &Segment::setOption(uint8_t n, bool val) {
bool prevOn = on;
if (fadeTransition && n == SEG_OPTION_ON && val != prevOn) startTransition(strip.getTransition()); // start transition prior to change
if (val) options |= 0x01 << n;
else options &= ~(0x01 << n);
if (!(n == SEG_OPTION_SELECTED || n == SEG_OPTION_RESET)) stateChanged = true; // send UDP/WS broadcast
+ return *this;
}
-void Segment::setMode(uint8_t fx, bool loadDefaults) {
+Segment &Segment::setMode(uint8_t fx, bool loadDefaults) {
// skip reserved
while (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4) == 0) fx++;
if (fx >= strip.getModeCount()) fx = 0; // set solid mode
@@ -625,9 +618,10 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
markForReset();
stateChanged = true; // send UDP/WS broadcast
}
+ return *this;
}
-void Segment::setPalette(uint8_t pal) {
+Segment &Segment::setPalette(uint8_t pal) {
if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes
if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // custom palettes
if (pal != palette) {
@@ -635,31 +629,24 @@ void Segment::setPalette(uint8_t pal) {
palette = pal;
stateChanged = true; // send UDP/WS broadcast
}
+ return *this;
}
// 2D matrix
-uint16_t Segment::virtualWidth() const {
+unsigned Segment::virtualWidth() const {
unsigned groupLen = groupLength();
unsigned vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen;
if (mirror) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED
return vWidth;
}
-uint16_t Segment::virtualHeight() const {
+unsigned Segment::virtualHeight() const {
unsigned groupLen = groupLength();
unsigned vHeight = ((transpose ? width() : height()) + groupLen - 1) / groupLen;
if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
return vHeight;
}
-uint16_t Segment::nrOfVStrips() const {
- unsigned vLen = 1;
-#ifndef WLED_DISABLE_2D
- if (is2D() && map1D2D == M12_pBar) vLen = virtualWidth();
-#endif
- return vLen;
-}
-
// Constants for mapping mode "Pinwheel"
#ifndef WLED_DISABLE_2D
constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16
@@ -1241,10 +1228,7 @@ uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_
//do not call this method from system context (network callback)
void WS2812FX::finalizeInit() {
//reset segment runtimes
- for (segment &seg : _segments) {
- seg.markForReset();
- seg.resetIfRequired();
- }
+ restartRuntime();
// for the lack of better place enumerate ledmaps here
// if we do it in json.cpp (serializeInfo()) we are getting flashes on LEDs
@@ -1391,7 +1375,7 @@ void WS2812FX::service() {
if (nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC))
{
doShow = true;
- unsigned delay = FRAMETIME;
+ unsigned frameDelay = FRAMETIME;
if (!seg.freeze) { //only run effect function if not frozen
int oldCCT = BusManager::getSegmentCCT(); // store original CCT value (actually it is not Segment based)
@@ -1407,7 +1391,7 @@ void WS2812FX::service() {
// would need to be allocated for each effect and then blended together for each pixel.
[[maybe_unused]] uint8_t tmpMode = seg.currentMode(); // this will return old mode while in transition
seg.beginDraw(); // set up parameters for get/setPixelColor()
- delay = (*_mode[seg.mode])(); // run new/current mode
+ frameDelay = (*_mode[seg.mode])(); // run new/current mode
#ifndef WLED_DISABLE_MODE_BLEND
if (modeBlending && seg.mode != tmpMode) {
Segment::tmpsegd_t _tmpSegData;
@@ -1416,16 +1400,16 @@ void WS2812FX::service() {
seg.beginDraw(); // set up parameters for get/setPixelColor()
unsigned d2 = (*_mode[tmpMode])(); // run old mode
seg.restoreSegenv(_tmpSegData); // restore mode state (will also update transitional state)
- delay = MIN(delay,d2); // use shortest delay
+ frameDelay = min(frameDelay,d2); // use shortest delay
Segment::modeBlend(false); // unset semaphore
}
#endif
seg.call++;
- if (seg.isInTransition() && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition
+ if (seg.isInTransition() && frameDelay > FRAMETIME) frameDelay = FRAMETIME; // force faster updates during transition
BusManager::setSegmentCCT(oldCCT); // restore old CCT for ABL adjustments
}
- seg.next_time = nowUp + delay;
+ seg.next_time = nowUp + frameDelay;
}
_segment_index++;
}
@@ -1469,10 +1453,12 @@ void WS2812FX::show() {
unsigned long showNow = millis();
size_t diff = showNow - _lastShow;
- size_t fpsCurr = 200;
- if (diff > 0) fpsCurr = 1000 / diff;
- _cumulativeFps = (3 * _cumulativeFps + fpsCurr +2) >> 2; // "+2" for proper rounding (2/4 = 0.5)
- _lastShow = showNow;
+
+ if (diff > 0) { // skip calculation if no time has passed
+ size_t fpsCurr = (1000 << FPS_CALC_SHIFT) / diff; // fixed point math
+ _cumulativeFps = (FPS_CALC_AVG * _cumulativeFps + fpsCurr + FPS_CALC_AVG / 2) / (FPS_CALC_AVG + 1); // "+FPS_CALC_AVG/2" for proper rounding
+ _lastShow = showNow;
+ }
}
void WS2812FX::setTargetFps(unsigned fps) {
diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h
index bf2d30c0e..84c32f46b 100644
--- a/wled00/bus_wrapper.h
+++ b/wled00/bus_wrapper.h
@@ -766,47 +766,47 @@ class PolyBus {
#endif
#ifdef ARDUINO_ARCH_ESP32
// RMT buses
- case I_32_RN_NEO_3: (static_cast(busPtr))->CanShow(); break;
- case I_32_RN_NEO_4: (static_cast(busPtr))->CanShow(); break;
- case I_32_RN_400_3: (static_cast(busPtr))->CanShow(); break;
- case I_32_RN_TM1_4: (static_cast(busPtr))->CanShow(); break;
- case I_32_RN_TM2_3: (static_cast(busPtr))->CanShow(); break;
- case I_32_RN_UCS_3: (static_cast(busPtr))->CanShow(); break;
- case I_32_RN_UCS_4: (static_cast(busPtr))->CanShow(); break;
- case I_32_RN_APA106_3: (static_cast(busPtr))->CanShow(); break;
- case I_32_RN_FW6_5: (static_cast(busPtr))->CanShow(); break;
- case I_32_RN_2805_5: (static_cast(busPtr))->CanShow(); break;
- case I_32_RN_TM1914_3: (static_cast(busPtr))->CanShow(); break;
- case I_32_RN_SM16825_5: (static_cast(busPtr))->CanShow(); break;
+ case I_32_RN_NEO_3: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_RN_NEO_4: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_RN_400_3: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_RN_TM1_4: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_RN_TM2_3: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_RN_UCS_3: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_RN_UCS_4: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_RN_APA106_3: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_RN_FW6_5: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_RN_2805_5: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_RN_TM1914_3: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_RN_SM16825_5: return (static_cast(busPtr))->CanShow(); break;
// I2S1 bus or paralell buses
#ifndef WLED_NO_I2S1_PIXELBUS
- case I_32_I1_NEO_3: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_NEO_4: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_400_3: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_TM1_4: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_TM2_3: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_UCS_3: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_UCS_4: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_APA106_3: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_FW6_5: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_2805_5: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_TM1914_3: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_SM16825_5: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break;
+ case I_32_I1_NEO_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I1_NEO_4: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I1_400_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I1_TM1_4: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I1_TM2_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I1_UCS_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I1_UCS_4: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I1_APA106_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I1_FW6_5: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I1_2805_5: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I1_TM1914_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I1_SM16825_5: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
#endif
// I2S0 bus
#ifndef WLED_NO_I2S0_PIXELBUS
- case I_32_I0_NEO_3: (static_cast(busPtr))->CanShow(); break;
- case I_32_I0_NEO_4: (static_cast(busPtr))->CanShow(); break;
- case I_32_I0_400_3: (static_cast(busPtr))->CanShow(); break;
- case I_32_I0_TM1_4: (static_cast(busPtr))->CanShow(); break;
- case I_32_I0_TM2_3: (static_cast(busPtr))->CanShow(); break;
- case I_32_I0_UCS_3: (static_cast(busPtr))->CanShow(); break;
- case I_32_I0_UCS_4: (static_cast(busPtr))->CanShow(); break;
- case I_32_I0_APA106_3: (static_cast(busPtr))->CanShow(); break;
- case I_32_I0_FW6_5: (static_cast(busPtr))->CanShow(); break;
- case I_32_I0_2805_5: (static_cast(busPtr))->CanShow(); break;
- case I_32_I0_TM1914_3: (static_cast(busPtr))->CanShow(); break;
- case I_32_I0_SM16825_5: (static_cast(busPtr))->CanShow(); break;
+ case I_32_I0_NEO_3: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I0_NEO_4: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I0_400_3: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I0_TM1_4: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I0_TM2_3: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I0_UCS_3: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I0_UCS_4: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I0_APA106_3: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I0_FW6_5: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I0_2805_5: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I0_TM1914_3: return (static_cast(busPtr))->CanShow(); break;
+ case I_32_I0_SM16825_5: return (static_cast(busPtr))->CanShow(); break;
#endif
#endif
case I_HS_DOT_3: return (static_cast(busPtr))->CanShow(); break;
diff --git a/wled00/button.cpp b/wled00/button.cpp
index f02ed3d6d..4d6f954f6 100644
--- a/wled00/button.cpp
+++ b/wled00/button.cpp
@@ -215,6 +215,7 @@ void handleAnalog(uint8_t b)
briLast = bri;
bri = 0;
} else {
+ if (bri == 0) strip.restartRuntime();
bri = aRead;
}
} else if (macroDoublePress[b] == 249) {
diff --git a/wled00/const.h b/wled00/const.h
index 14ec23b58..07873deca 100644
--- a/wled00/const.h
+++ b/wled00/const.h
@@ -53,7 +53,7 @@
#else
#define WLED_MAX_ANALOG_CHANNELS (LEDC_CHANNEL_MAX*LEDC_SPEED_MODE_MAX)
#if defined(CONFIG_IDF_TARGET_ESP32C3) // 2 RMT, 6 LEDC, only has 1 I2S but NPB does not support it ATM
- #define WLED_MAX_BUSSES 4 // will allow 2 digital & 2 analog RGB
+ #define WLED_MAX_BUSSES 6 // will allow 2 digital & 2 analog RGB or 6 PWM white
#define WLED_MAX_DIGITAL_CHANNELS 2
//#define WLED_MAX_ANALOG_CHANNELS 6
#define WLED_MIN_VIRTUAL_BUSSES 3
diff --git a/wled00/data/index.css b/wled00/data/index.css
index c4e85f73f..0e36ff08c 100644
--- a/wled00/data/index.css
+++ b/wled00/data/index.css
@@ -144,7 +144,7 @@ button {
}
.huge {
- font-size: 42px;
+ font-size: 60px !important;
}
.segt, .plentry TABLE {
@@ -584,6 +584,10 @@ button {
z-index: 3;
}
+#rover .ibtn {
+ margin: 5px;
+}
+
#ndlt {
margin: 12px 0;
}
@@ -624,7 +628,7 @@ button {
padding-bottom: 8px;
}
-.infobtn {
+#info .ibtn {
margin: 5px;
}
@@ -848,7 +852,7 @@ input[type=range]::-moz-range-thumb {
width: 135px;
}
-#nodes .infobtn {
+#nodes .ibtn {
margin: 0;
}
@@ -1036,7 +1040,7 @@ textarea {
.segname .flr, .pname .flr {
transform: rotate(0deg);
- right: -6px;
+ /*right: -6px;*/
}
/* segment power wrapper */
@@ -1331,6 +1335,11 @@ TD .checkmark, TD .radiomark {
box-shadow: 0 0 10px 4px var(--c-1);
}
+.lstI .flr:hover {
+ background: var(--c-6);
+ border-radius: 100%;
+}
+
#pcont .selected:not([class*="expanded"]) {
bottom: 52px;
top: 42px;
@@ -1524,7 +1533,7 @@ dialog {
#info table .btn, #nodes table .btn {
width: 200px;
}
- #info .infobtn, #nodes .infobtn {
+ #info .ibtn, #nodes .ibtn {
width: 145px;
}
#info div, #nodes div, #nodes a.btn {
diff --git a/wled00/data/index.htm b/wled00/data/index.htm
index 86b3b1879..e74ea0076 100644
--- a/wled00/data/index.htm
+++ b/wled00/data/index.htm
@@ -304,10 +304,10 @@