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_rotary_encoder_ui_ALT/platformio–override.sample.ini b/usermods/usermod_v2_four_line_display_ALT/platformio_override.sample.ini
similarity index 59%
rename from usermods/usermod_v2_rotary_encoder_ui_ALT/platformio–override.sample.ini
rename to usermods/usermod_v2_four_line_display_ALT/platformio_override.sample.ini
index 6b32c71fb..e59637453 100644
--- a/usermods/usermod_v2_rotary_encoder_ui_ALT/platformio–override.sample.ini
+++ b/usermods/usermod_v2_four_line_display_ALT/platformio_override.sample.ini
@@ -7,11 +7,12 @@ platform = ${esp32.platform}
build_unflags = ${common.build_unflags}
build_flags =
${common.build_flags_esp32}
- -D USERMOD_FOUR_LINE_DISPLAY -D USE_ALT_DISPlAY
- -D USERMOD_ROTARY_ENCODER_UI -D ENCODER_DT_PIN=18 -D ENCODER_CLK_PIN=5 -D ENCODER_SW_PIN=19
-upload_speed = 460800
+ -D USERMOD_FOUR_LINE_DISPLAY
+ -D FLD_TYPE=SH1106
+ -D I2CSCLPIN=27
+ -D I2CSDAPIN=26
+
lib_deps =
${esp32.lib_deps}
U8g2@~2.34.4
Wire
-
diff --git a/usermods/usermod_v2_four_line_display_ALT/readme.md b/usermods/usermod_v2_four_line_display_ALT/readme.md
index a8f386dac..39bb5d28e 100644
--- a/usermods/usermod_v2_four_line_display_ALT/readme.md
+++ b/usermods/usermod_v2_four_line_display_ALT/readme.md
@@ -1,16 +1,8 @@
# I2C/SPI 4 Line Display Usermod ALT
-Thank you to the authors of the original version of these usermods. It would not have been possible without them!
-"usermod_v2_four_line_display"
-"usermod_v2_rotary_encoder_ui"
+This usermod could be used in compination with `usermod_v2_rotary_encoder_ui_ALT`.
-The core of these usermods are a copy of the originals. The main changes are to the FourLineDisplay usermod.
-The display usermod UI has been completely changed.
-
-
-The changes made to the RotaryEncoder usermod were made to support the new UI in the display usermod.
-Without the display, it functions identical to the original.
-The original "usermod_v2_auto_save" will not work with the display just yet.
+## Functionalities
Press the encoder to cycle through the options:
* Brightness
@@ -18,26 +10,18 @@ Press the encoder to cycle through the options:
* Intensity
* Palette
* Effect
-* Main Color (only if display is used)
-* Saturation (only if display is used)
+* Main Color
+* Saturation
-Press and hold the encoder to display Network Info. If AP is active, it will display AP, SSID and password
+Press and hold the encoder to display Network Info. If AP is active, it will display the AP, SSID and Password
-Also shows if the timer is enabled
+Also shows if the timer is enabled.
[See the pair of usermods in action](https://www.youtube.com/watch?v=ulZnBt9z3TI)
## Installation
-Please refer to the original `usermod_v2_rotary_encoder_ui` readme for the main instructions.
-
-Copy the example `platformio_override.sample.ini` from the usermod_v2_rotary_encoder_ui_ALT folder to the root directory of your particular build and rename it to `platformio_override.ini`.
-
-This file should be placed in the same directory as `platformio.ini`.
-
-Then, to activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE SENSITIVE) to the `usermods_list.cpp` file,
- or add `-D USE_ALT_DISPlAY` to the original `platformio_override.ini.sample` file
-
+Copy the example `platformio_override.sample.ini` to the root directory of your particular build.
## Configuration
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/platformio_override.sample.ini b/usermods/usermod_v2_rotary_encoder_ui_ALT/platformio_override.sample.ini
new file mode 100644
index 000000000..8a88fd6b5
--- /dev/null
+++ b/usermods/usermod_v2_rotary_encoder_ui_ALT/platformio_override.sample.ini
@@ -0,0 +1,14 @@
+[platformio]
+default_envs = esp32dev
+
+[env:esp32dev]
+board = esp32dev
+platform = ${esp32.platform}
+build_unflags = ${common.build_unflags}
+build_flags =
+ ${common.build_flags_esp32}
+ -D USERMOD_ROTARY_ENCODER_UI
+ -D USERMOD_ROTARY_ENCODER_GPIO=INPUT
+ -D ENCODER_DT_PIN=21
+ -D ENCODER_CLK_PIN=23
+ -D ENCODER_SW_PIN=0
diff --git a/usermods/usermod_v2_rotary_encoder_ui_ALT/readme.md b/usermods/usermod_v2_rotary_encoder_ui_ALT/readme.md
index 10db879fb..c46e87663 100644
--- a/usermods/usermod_v2_rotary_encoder_ui_ALT/readme.md
+++ b/usermods/usermod_v2_rotary_encoder_ui_ALT/readme.md
@@ -1,16 +1,8 @@
# Rotary Encoder UI Usermod ALT
-Thank you to the authors of the original version of these usermods. It would not have been possible without them!
-"usermod_v2_four_line_display"
-"usermod_v2_rotary_encoder_ui"
+This usermod supports the UI of the `usermod_v2_rotary_encoder_ui_ALT`.
-The core of these usermods are a copy of the originals. The main changes are to the FourLineDisplay usermod.
-The display usermod UI has been completely changed.
-
-
-The changes made to the RotaryEncoder usermod were made to support the new UI in the display usermod.
-Without the display, it functions identical to the original.
-The original "usermod_v2_auto_save" will not work with the display just yet.
+## Functionalities
Press the encoder to cycle through the options:
* Brightness
@@ -21,8 +13,7 @@ Press the encoder to cycle through the options:
* Main Color (only if display is used)
* Saturation (only if display is used)
-Press and hold the encoder to display Network Info
- if AP is active, it will display the AP, SSID and Password
+Press and hold the encoder to display Network Info. If AP is active, it will display the AP, SSID and Password
Also shows if the timer is enabled.
@@ -30,9 +21,7 @@ Also shows if the timer is enabled.
## Installation
-Copy the example `platformio_override.sample.ini` to the root directory of your particular build and rename it to `platformio_override.ini`.
-
-To activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE SENSITIVE) to the `usermods_list.cpp` file, or add `-D USE_ALT_DISPlAY` to your `platformio_override.ini` file
+Copy the example `platformio_override.sample.ini` to the root directory of your particular build.
### Define Your Options
@@ -40,7 +29,6 @@ To activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE
* `USERMOD_FOUR_LINE_DISPLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp
also tells this usermod that the display is available
(see the Four Line Display usermod `readme.md` for more details)
-* `USE_ALT_DISPlAY` - Mandatory to use Four Line Display
* `ENCODER_DT_PIN` - defaults to 18
* `ENCODER_CLK_PIN` - defaults to 5
* `ENCODER_SW_PIN` - defaults to 19
@@ -50,7 +38,7 @@ To activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE
### PlatformIO requirements
-Note: the Four Line Display usermod requires the libraries `U8g2` and `Wire`.
+No special requirements.
## Change Log
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 da2967a3c..a2ceb591a 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
*/
@@ -1980,7 +1966,7 @@ uint16_t mode_palette() {
const bool inputAnimateRotation = SEGMENT.check2;
const bool inputAssumeSquare = SEGMENT.check3;
- const angleType theta = (!inputAnimateRotation) ? (inputRotation * maxAngle / staticRotationScale) : (((strip.now * ((inputRotation >> 4) +1)) & 0xFFFF) * animatedRotationScale);
+ const angleType theta = (!inputAnimateRotation) ? ((inputRotation + 128) * maxAngle / staticRotationScale) : (((strip.now * ((inputRotation >> 4) +1)) & 0xFFFF) * animatedRotationScale);
const mathType sinTheta = sinFunction(theta);
const mathType cosTheta = cosFunction(theta);
@@ -1999,7 +1985,7 @@ uint16_t mode_palette() {
// So the rectangle needs to have exactly the right size. That size depends on the rotation.
// This scale computation here only considers one dimension. You can think of it like the rectangle is always scaled so that
// the left and right most points always match the left and right side of the display.
- const mathType scale = std::abs(sinTheta) + (std::abs(cosTheta) * maxYOut / maxXOut);
+ const mathType scale = std::abs(sinTheta) + (std::abs(cosTheta) * maxYOut / maxXOut);
// 2D simulation:
// If we are dealing with a 1D setup, we assume that each segment represents one line on a 2-dimensional display.
// The function is called once per segments, so we need to handle one line at a time.
@@ -2030,8 +2016,8 @@ uint16_t mode_palette() {
colorIndex = ((inputSize - 112) * colorIndex) / 16;
}
// Finally, shift the palette a bit.
- const int paletteOffset = (!inputAnimateShift) ? (inputShift-128) : (((strip.now * ((inputShift >> 3) +1)) & 0xFFFF) >> 8);
- colorIndex += paletteOffset;
+ const int paletteOffset = (!inputAnimateShift) ? (inputShift) : (((strip.now * ((inputShift >> 3) +1)) & 0xFFFF) >> 8);
+ colorIndex -= paletteOffset;
const uint32_t color = SEGMENT.color_wheel((uint8_t)colorIndex);
if (isMatrix) {
SEGMENT.setPixelColorXY(x, y, color);
@@ -2042,7 +2028,7 @@ uint16_t mode_palette() {
}
return FRAMETIME;
}
-static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Shift,Size,Rotation,,,Animate Shift,Animate Rotation,Anamorphic;;!;12;c1=128,c2=128,c3=128,o1=1,o2=1,o3=0";
+static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Shift,Size,Rotation,,,Animate Shift,Animate Rotation,Anamorphic;;!;12;ix=112,c1=0,o1=1,o2=0,o3=1";
// WLED limitation: Analog Clock overlay will NOT work when Fire2012 is active
@@ -2520,9 +2506,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
}
@@ -3561,7 +3547,7 @@ uint16_t mode_exploding_fireworks(void)
if (segs <= (strip.getMaxSegments() /4)) maxData *= 2; //ESP8266: 1024 if <= 4 segs ESP32: 2560 if <= 8 segs
int maxSparks = maxData / sizeof(spark); //ESP8266: max. 21/42/85 sparks/seg, ESP32: max. 53/106/213 sparks/seg
- unsigned numSparks = min(2 + ((rows*cols) >> 1), maxSparks);
+ unsigned numSparks = min(5 + ((rows*cols) >> 1), maxSparks);
unsigned dataSize = sizeof(spark) * numSparks;
if (!SEGENV.allocateData(dataSize + sizeof(float))) return mode_static(); //allocation failed
float *dying_gravity = reinterpret_cast(SEGENV.data + dataSize);
@@ -3616,7 +3602,8 @@ uint16_t mode_exploding_fireworks(void)
* Size is proportional to the height.
*/
unsigned nSparks = flare->pos + random8(4);
- nSparks = constrain(nSparks, 4, numSparks);
+ nSparks = std::max(nSparks, 4U); // This is not a standard constrain; numSparks is not guaranteed to be at least 4
+ nSparks = std::min(nSparks, numSparks);
// initialize sparks
if (SEGENV.aux0 == 2) {
@@ -4031,7 +4018,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;
@@ -4046,7 +4033,7 @@ uint16_t mode_pacifica()
sCIStart3 -= (deltams1 * beatsin88_t(501,5,7));
sCIStart4 -= (deltams2 * beatsin88_t(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);
@@ -4077,7 +4064,7 @@ uint16_t mode_pacifica()
c.green = scale8(c.green, 200);
c |= CRGB( 2, 5, 7);
- SEGMENT.setPixelColor(i, c.red, c.green, c.blue);
+ SEGMENT.setPixelColor(i, c);
}
strip.now = nowOld;
@@ -4644,7 +4631,7 @@ uint16_t mode_tv_simulator(void) {
return FRAMETIME;
}
-static const char _data_FX_MODE_TV_SIMULATOR[] PROGMEM = "TV Simulator@!,!;;";
+static const char _data_FX_MODE_TV_SIMULATOR[] PROGMEM = "TV Simulator@!,!;;!;01";
/*
diff --git a/wled00/FX.h b/wled00/FX.h
index 3c28274d6..545161546 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
*/
@@ -61,6 +47,15 @@
#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
@@ -539,12 +534,12 @@ typedef struct Segment {
inline static const CRGBPalette16 &getCurrentPalette() { return Segment::_currentPalette; }
void setUp(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);
- 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(Segment& b) const;
void refreshLightCapabilities();
@@ -559,7 +554,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
@@ -613,9 +608,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
@@ -720,7 +721,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),
// semi-private (just obscured) used in effect functions through macros
@@ -733,7 +738,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),
@@ -788,7 +793,8 @@ class WS2812FX { // 96 bytes
setTargetFps(uint8_t 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 setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setColor(slot, RGBW32(r,g,b,w)); }
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)); }
@@ -844,10 +850,8 @@ class WS2812FX { // 96 bytes
inline uint16_t getLength() const { return _length; } // returns actual amount of LEDs on a strip (2D matrix may have less LEDs than W*H)
inline uint16_t getTransition() const { return _transitionDur; } // returns currently set transition time (in ms)
- uint32_t
- now,
- timebase,
- getPixelColor(uint16_t) const;
+ unsigned long now, timebase;
+ uint32_t getPixelColor(unsigned) const;
inline uint32_t getLastShow() const { return _lastShow; } // returns millis() timestamp of last strip.show() call
inline uint32_t segColor(uint8_t i) const { return _colors_t[i]; } // returns currently valid color (for slot i) AKA SEGCOLOR(); may be blended between two colors while in transition
diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp
index 0f6690549..7c1ae366b 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
*/
@@ -171,7 +156,7 @@ uint16_t IRAM_ATTR_YN Segment::XY(int x, int y)
void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col)
{
if (!isActive()) return; // not active
- if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
+ if ((unsigned)x >= virtualWidth() || (unsigned)y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
uint8_t _bri_t = currentBri();
if (_bri_t < 255) {
@@ -266,7 +251,7 @@ 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
- if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit
+ if ((unsigned)x >= virtualWidth() || (unsigned)y >= virtualHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit
if (reverse ) x = virtualWidth() - x - 1;
if (reverse_y) y = virtualHeight() - y - 1;
if (transpose) { std::swap(x,y); } // swap X & Y if segment transposed
diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp
index 1bbfa365b..7177ca89e 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
*/
@@ -523,46 +509,53 @@ void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t
}
-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
@@ -594,9 +587,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) {
@@ -604,37 +598,24 @@ void Segment::setPalette(uint8_t pal) {
palette = pal;
stateChanged = true; // send UDP/WS broadcast
}
+ return *this;
}
// 2D matrix
-uint16_t IRAM_ATTR Segment::virtualWidth() const {
+unsigned IRAM_ATTR 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 IRAM_ATTR Segment::virtualHeight() const {
+unsigned IRAM_ATTR 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 IRAM_ATTR_YN Segment::nrOfVStrips() const {
- unsigned vLen = 1;
-#ifndef WLED_DISABLE_2D
- if (is2D()) {
- switch (map1D2D) {
- case M12_pBar:
- vLen = virtualWidth();
- break;
- }
- }
-#endif
- return vLen;
-}
-
// Constants for mapping mode "Pinwheel"
#ifndef WLED_DISABLE_2D
constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16
@@ -1201,10 +1182,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
@@ -1308,14 +1286,9 @@ void WS2812FX::finalizeInit() {
_isOffRefreshRequired |= bus->isOffRefreshRequired() && !bus->isPWM(); // use refresh bit for phase shift with analog
unsigned busEnd = bus->getStart() + bus->getLength();
if (busEnd > _length) _length = busEnd;
- #ifdef ESP8266
- // why do we need to reinitialise GPIO3???
- //if (!bus->isDigital() || bus->is2Pin()) continue;
- //uint8_t pins[5];
- //if (!bus->getPins(pins)) continue;
- //BusDigital* bd = static_cast(bus);
- //if (pins[0] == 3) bd->reinit();
- #endif
+
+ // This must be done after all buses have been created, as some kinds (parallel I2S) interact
+ bus->begin();
}
Segment::maxWidth = _length;
@@ -1351,7 +1324,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)
@@ -1371,7 +1344,7 @@ void WS2812FX::service() {
// overwritten by later effect. To enable seamless blending for every effect, additional LED buffer
// 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
- 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;
@@ -1380,16 +1353,16 @@ void WS2812FX::service() {
_virtualSegmentLength = seg.virtualLength(); // update SEGLEN (mapping may have changed)
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++;
}
@@ -1416,7 +1389,7 @@ void IRAM_ATTR WS2812FX::setPixelColor(unsigned i, uint32_t col) {
BusManager::setPixelColor(i, col);
}
-uint32_t IRAM_ATTR WS2812FX::getPixelColor(uint16_t i) const {
+uint32_t IRAM_ATTR WS2812FX::getPixelColor(unsigned i) const {
i = getMappedPixelIndex(i);
if (i >= _length) return 0;
return BusManager::getPixelColor(i);
@@ -1434,10 +1407,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;
+ }
}
/**
@@ -1454,7 +1429,7 @@ bool WS2812FX::isUpdating() const {
*/
uint16_t WS2812FX::getFps() const {
if (millis() - _lastShow > 2000) return 0;
- return _cumulativeFps +1;
+ return (FPS_MULTIPLIER * _cumulativeFps) >> FPS_CALC_SHIFT; // _cumulativeFps is stored in fixed point
}
void WS2812FX::setTargetFps(uint8_t fps) {
diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp
index 5b948b9c4..5b031bebb 100644
--- a/wled00/bus_manager.cpp
+++ b/wled00/bus_manager.cpp
@@ -150,7 +150,7 @@ BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com)
//_buffering = bc.doubleBuffer;
uint16_t lenToCreate = bc.count;
if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(bc.count); // only needs a third of "RGB" LEDs for NeoPixelBus
- _busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr, _frequencykHz);
+ _busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr);
_valid = (_busPtr != nullptr);
DEBUG_PRINTF_P(PSTR("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u). mA=%d/%d\n"), _valid?"S":"Uns", nr, bc.count, bc.type, _pins[0], is2Pin(bc.type)?_pins[1]:255, _iType, _milliAmpsPerLed, _milliAmpsMax);
}
@@ -410,9 +410,9 @@ std::vector BusDigital::getLEDTypes() {
};
}
-void BusDigital::reinit() {
+void BusDigital::begin() {
if (!_valid) return;
- PolyBus::begin(_busPtr, _iType, _pins);
+ PolyBus::begin(_busPtr, _iType, _pins, _frequencykHz);
}
void BusDigital::cleanup() {
@@ -910,7 +910,7 @@ void BusManager::on() {
if (busses[i]->isDigital() && busses[i]->getPins(pins)) {
if (pins[0] == LED_BUILTIN || pins[1] == LED_BUILTIN) {
BusDigital *bus = static_cast(busses[i]);
- bus->reinit();
+ bus->begin();
break;
}
}
diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h
index e96b9de71..ecebc120e 100644
--- a/wled00/bus_manager.h
+++ b/wled00/bus_manager.h
@@ -79,6 +79,7 @@ class Bus {
virtual ~Bus() {} //throw the bus under the bus
+ virtual void begin() {};
virtual void show() = 0;
virtual bool canShow() const { return true; }
virtual void setStatusPixel(uint32_t c) {}
@@ -213,7 +214,7 @@ class BusDigital : public Bus {
uint16_t getLEDCurrent() const override { return _milliAmpsPerLed; }
uint16_t getUsedCurrent() const override { return _milliAmpsTotal; }
uint16_t getMaxCurrent() const override { return _milliAmpsMax; }
- void reinit();
+ void begin() override;
void cleanup();
static std::vector getLEDTypes();
diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h
index 84c32f46b..d2a18c9d8 100644
--- a/wled00/bus_wrapper.h
+++ b/wled00/bus_wrapper.h
@@ -336,7 +336,7 @@ class PolyBus {
// 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) {
+ static void beginDotStar(void* busPtr, int8_t sck, int8_t miso, int8_t mosi, int8_t ss, uint16_t clock_kHz /* 0 == use default */) {
T dotStar_strip = static_cast(busPtr);
#ifdef ESP8266
dotStar_strip->Begin();
@@ -363,7 +363,7 @@ class PolyBus {
tm1914_strip->SetPixelSettings(NeoTm1914Settings()); //NeoTm1914_Mode_DinFdinAutoSwitch, NeoTm1914_Mode_DinOnly, NeoTm1914_Mode_FdinOnly
}
- static void begin(void* busPtr, uint8_t busType, uint8_t* pins, uint16_t clock_kHz = 0U) {
+ static void begin(void* busPtr, uint8_t busType, uint8_t* pins, uint16_t clock_kHz /* only used by DotStar */) {
switch (busType) {
case I_NONE: break;
#ifdef ESP8266
@@ -480,7 +480,7 @@ class PolyBus {
}
}
- static void* create(uint8_t busType, uint8_t* pins, uint16_t len, uint8_t channel, uint16_t clock_kHz = 0U) {
+ static void* create(uint8_t busType, uint8_t* pins, uint16_t len, uint8_t channel) {
#if defined(ARDUINO_ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3))
// NOTE: "channel" is only used on ESP32 (and its variants) for RMT channel allocation
// since 0.15.0-b3 I2S1 is favoured for classic ESP32 and moved to position 0 (channel 0) so we need to subtract 1 for correct RMT allocation
@@ -597,7 +597,7 @@ class PolyBus {
case I_HS_P98_3: busPtr = new B_HS_P98_3(len, pins[1], pins[0]); break;
case I_SS_P98_3: busPtr = new B_SS_P98_3(len, pins[1], pins[0]); break;
}
- begin(busPtr, busType, pins, clock_kHz);
+
return busPtr;
}
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 @@