From ef80abd88509856a0426735743ebc39ceda2952e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 4 Sep 2024 11:38:03 +0200 Subject: [PATCH 01/90] 8266 compatibility builds for older chips (another attempt t o solve #3690 and #3685) some users have reported that releases after 0.14.0 are not working reliably. So we add a few "compat" for 8266 that try to reproduce the buildenv of 0.14.0 as much as possible. * platform and platform_packages from 0.14.0 * not using PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48 * due to smaller IRAM, we had to move some functions back from IRAM to normal flash (may cause slowdown) --- platformio.ini | 44 +++++++++++++++++++++++++++++++++++++++++++- wled00/FX_2Dfcn.cpp | 4 ++-- wled00/FX_fcn.cpp | 3 ++- wled00/const.h | 8 ++++++++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/platformio.ini b/platformio.ini index cbe13c0dd..d19f47764 100644 --- a/platformio.ini +++ b/platformio.ini @@ -11,7 +11,7 @@ # CI binaries ; default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth # ESP32 variant builds are temporarily excluded from CI due to toolchain issues on the GitHub Actions Linux environment -default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, nodemcuv2_160, esp8266_2m_160, esp01_1m_full_160, esp32dev, esp32_eth, esp32dev_audioreactive, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB, esp32s3dev_8MB_PSRAM_opi +default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, nodemcuv2_compat, esp8266_2m_compat, esp01_1m_full_compat, nodemcuv2_160, esp8266_2m_160, esp01_1m_full_160, esp32dev, esp32_eth, esp32dev_audioreactive, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB, esp32s3dev_8MB_PSRAM_opi # Release binaries ; default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB @@ -226,6 +226,27 @@ lib_deps = ESPAsyncUDP ${env.lib_deps} +;; compatibilty flags - same as 0.14.0 which seems to work better on some 8266 boards. Not using PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48 +build_flags_compat = + -DESP8266 + -DFP_IN_IROM + ;;-Wno-deprecated-declarations + -Wno-misleading-indentation + ;;-Wno-attributes ;; silence warnings about unknown attribute 'maybe_unused' in NeoPixelBus + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 + -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH + -DVTABLES_IN_FLASH + -DMIMETYPE_MINIMAL + -DWLED_SAVE_IRAM ;; needed to prevent linker error + +;; this platform version was used for WLED 0.14.0 +platform_compat = espressif8266@4.2.0 +platform_packages_compat = + platformio/toolchain-xtensa @ ~2.100300.220621 #2.40802.200502 + platformio/tool-esptool #@ ~1.413.0 + platformio/tool-esptoolpy #@ ~1.30000.0 + + [esp32] #platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.3/platform-espressif32-2.0.2.3.zip platform = espressif32@3.5.0 @@ -336,6 +357,13 @@ build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 #-DWLED lib_deps = ${esp8266.lib_deps} monitor_filters = esp8266_exception_decoder +[env:nodemcuv2_compat] +extends = env:nodemcuv2 +;; using platform version and build options from WLED 0.14.0 +platform = ${esp8266.platform_compat} +platform_packages = ${esp8266.platform_packages_compat} +build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=ESP8266_compat #-DWLED_DISABLE_2D + [env:nodemcuv2_160] extends = env:nodemcuv2 board_build.f_cpu = 160000000L @@ -350,6 +378,13 @@ build_unflags = ${common.build_unflags} build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP02 lib_deps = ${esp8266.lib_deps} +[env:esp8266_2m_compat] +extends = env:esp8266_2m +;; using platform version and build options from WLED 0.14.0 +platform = ${esp8266.platform_compat} +platform_packages = ${esp8266.platform_packages_compat} +build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=ESP02_compat #-DWLED_DISABLE_2D + [env:esp8266_2m_160] extends = env:esp8266_2m board_build.f_cpu = 160000000L @@ -365,6 +400,13 @@ build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01 -D WLED_D ; -D WLED_USE_UNREAL_MATH ;; may cause wrong sunset/sunrise times, but saves 7064 bytes FLASH and 975 bytes RAM lib_deps = ${esp8266.lib_deps} +[env:esp01_1m_full_compat] +extends = env:esp01_1m_full +;; using platform version and build options from WLED 0.14.0 +platform = ${esp8266.platform_compat} +platform_packages = ${esp8266.platform_packages_compat} +build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=ESP01_compat -D WLED_DISABLE_OTA #-DWLED_DISABLE_2D + [env:esp01_1m_full_160] extends = env:esp01_1m_full board_build.f_cpu = 160000000L diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 5dc9e9ff2..918ce61e2 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -163,14 +163,14 @@ void WS2812FX::setUpMatrix() { #ifndef WLED_DISABLE_2D // XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element) -uint16_t IRAM_ATTR Segment::XY(uint16_t x, uint16_t y) +uint16_t IRAM_ATTR_YN Segment::XY(uint16_t x, uint16_t y) { uint16_t width = virtualWidth(); // segment width in logical pixels (can be 0 if segment is inactive) uint16_t height = virtualHeight(); // segment height in logical pixels (is always >= 1) return isActive() ? (x%width) + (y%height) * width : 0; } -void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col) +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 diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 10847ef57..58e2fdfa5 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -145,6 +145,7 @@ Segment& Segment::operator= (Segment &&orig) noexcept { } bool Segment::allocateData(size_t len) { + if (len == 0) return false; // nothing to do if (data && _dataLen >= len) { // already allocated enough (reduce fragmentation) if (call == 0) memset(data, 0, len); // erase buffer if called during effect initialisation return true; @@ -659,7 +660,7 @@ uint16_t Segment::virtualLength() const { return vLength; } -void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) +void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) { if (!isActive()) return; // not active #ifndef WLED_DISABLE_2D diff --git a/wled00/const.h b/wled00/const.h index 388b64c82..97bfcff1b 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -540,4 +540,12 @@ #define HW_PIN_MISOSPI MISO #endif +// IRAM_ATTR for 8266 with 32Kb IRAM causes error: section `.text1' will not fit in region `iram1_0_seg' +// this hack removes the IRAM flag for some 1D/2D functions - somewhat slower, but it solves problems with some older 8266 chips +#ifdef WLED_SAVE_IRAM + #define IRAM_ATTR_YN +#else + #define IRAM_ATTR_YN IRAM_ATTR +#endif + #endif From dc90a4ed42702e608b1f1482a541a4adbd1ae1ac Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Wed, 4 Sep 2024 21:17:21 +0200 Subject: [PATCH 02/90] Mirroring bugfix. --- wled00/FX_2Dfcn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 918ce61e2..1461a1a9e 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -214,7 +214,7 @@ void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) else strip.setPixelColorXY(start + xX, startY + height() - yY - 1, tmpCol); } if (mirror_y && mirror) { //set the corresponding vertically AND horizontally mirrored pixel - strip.setPixelColorXY(width() - xX - 1, height() - yY - 1, tmpCol); + strip.setPixelColorXY(start + width() - xX - 1, startY + height() - yY - 1, tmpCol); } } } From 058e66c7fcc8b8ea568c777f7574f1295d82d4e2 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Sep 2024 20:32:40 +0200 Subject: [PATCH 03/90] Update CONTRIBUTING.md - adding a hint to avoid force-pushing --- CONTRIBUTING.md | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 168131160..8ab9bb9f0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,6 +16,20 @@ A good description helps us to review and understand your proposed changes. For Please make all PRs against the `0_15` branch. +### Updating your code +While the PR is open - and under review by maintainers - you may be asked to modify your PR source code. +You can simply update your own branch, and push changes in response to reviewer recommendations. +Github will pick up the changes so your PR stays up-to-date. + +> [!CAUTION] +> Do not use "force-push" while your PR is open! +> It has many subtle and unexpected consequences on our github reposistory. +> For example, we regularly lost review comments when the PR author force-pushes code changes. So, pretty please, do not force-push. + + +You kan find a collection of very usefull tips and tricks here: https://github.com/Aircoookie/WLED/wiki/How-to-properly-submit-a-PR + + ### Code style When in doubt, it is easiest to replicate the code style you find in the files you want to edit :) @@ -37,6 +51,11 @@ if (a == b) { } ``` +```cpp +if (a == b) doStuff(a); +``` + +Acceptable - however the first variant is usually easier to read: ```cpp if (a == b) { @@ -44,9 +63,6 @@ if (a == b) } ``` -```cpp -if (a == b) doStuff(a); -``` There should always be a space between a keyword and its condition and between the condition and brace. Within the condition, no space should be between the paranthesis and variables. From 2cfd2e1410f2ebed85df0e56fef658ee018f6266 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Sep 2024 20:36:18 +0200 Subject: [PATCH 04/90] Update CONTRIBUTING.md - typo --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8ab9bb9f0..9b1affbc3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,7 +27,7 @@ Github will pick up the changes so your PR stays up-to-date. > For example, we regularly lost review comments when the PR author force-pushes code changes. So, pretty please, do not force-push. -You kan find a collection of very usefull tips and tricks here: https://github.com/Aircoookie/WLED/wiki/How-to-properly-submit-a-PR +You can find a collection of very useful tips and tricks here: https://github.com/Aircoookie/WLED/wiki/How-to-properly-submit-a-PR ### Code style From 1ff667b7eff07ebad100e48eb871c698eab11a71 Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Sun, 15 Sep 2024 10:59:50 +0200 Subject: [PATCH 05/90] AWS library fix --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index d19f47764..2ef4ae01b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -180,7 +180,7 @@ lib_deps = fastled/FastLED @ 3.6.0 IRremoteESP8266 @ 2.8.2 makuna/NeoPixelBus @ 2.7.5 - https://github.com/Aircoookie/ESPAsyncWebServer.git @ 2.2.1 + https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.2.1 #For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line #TFT_eSPI #For compatible OLED display uncomment following From 7b855c851d7824596557d4444796c2c3aec6356c Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sat, 5 Oct 2024 12:29:31 +0200 Subject: [PATCH 06/90] Added integer based `sin()/cos()` functions, changed all trig functions to wled_math - `sin16_t() / cos16_t()` are faster and more accurate than fastled versions - `sin_approx() / cos_approx()` are float wrappers for `sin16_t() / cos16_t()` and are accurate enough to replace `sinf()/cosf()` - `atan2()` is used only in octopus to calculate center offset, new approximated version saves flash - `tan(), atan(), asin(), acos(), floor(), fmod()` are used only for sunrise/sunset calculation, using wled_math version saves flash - `beatsinx()` replacements are to make use of new `sin16_t()/sin8_t()` functions to reduce flash size - Extensively tested surnise/sunset calculation: deviation is 1min. max - Tested some of the relevant FX and found no visual difference: Julia, 2D Drift, Drift Rose, Ghost rider, Rotozoomer, Palette, Arc 1D expansion - total flash savings: 7.4k --- usermods/Analog_Clock/Analog_Clock.h | 4 +- wled00/FX.cpp | 258 +++++++++++++-------------- wled00/fcn_declare.h | 53 +++--- wled00/util.cpp | 41 ++++- wled00/wled_math.cpp | 89 ++++++++- 5 files changed, 288 insertions(+), 157 deletions(-) diff --git a/usermods/Analog_Clock/Analog_Clock.h b/usermods/Analog_Clock/Analog_Clock.h index 596f0acb3..9d82f7670 100644 --- a/usermods/Analog_Clock/Analog_Clock.h +++ b/usermods/Analog_Clock/Analog_Clock.h @@ -102,9 +102,9 @@ private: void secondsEffectSineFade(int16_t secondLed, Toki::Time const& time) { uint32_t ms = time.ms % 1000; - uint8_t b0 = (cos8(ms * 64 / 1000) - 128) * 2; + uint8_t b0 = (cos8_t(ms * 64 / 1000) - 128) * 2; setPixelColor(secondLed, gamma32(scale32(secondColor, b0))); - uint8_t b1 = (sin8(ms * 64 / 1000) - 128) * 2; + uint8_t b1 = (sin8_t(ms * 64 / 1000) - 128) * 2; setPixelColor(inc(secondLed, 1, secondsSegment), gamma32(scale32(secondColor, b1))); } diff --git a/wled00/FX.cpp b/wled00/FX.cpp index f3e82275c..338dd2df9 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -39,7 +39,7 @@ // effect utility functions uint8_t sin_gap(uint16_t in) { if (in & 0x100) return 0; - return sin8(in + 192); // correct phase shift of sine so that it starts and stops at 0 + return sin8_t(in + 192); // correct phase shift of sine so that it starts and stops at 0 } uint16_t triwave16(uint16_t in) { @@ -349,7 +349,7 @@ uint16_t mode_breath(void) { counter = (counter >> 2) + (counter >> 4); //0-16384 + 0-2048 if (counter < 16384) { if (counter > 8192) counter = 8192 - (counter - 8192); - var = sin16(counter) / 103; //close to parabolic in range 0-8192, max val. 23170 + var = sin16_t(counter) / 103; //close to parabolic in range 0-8192, max val. 23170 } unsigned lum = 30 + var; @@ -531,7 +531,7 @@ static uint16_t running_base(bool saw, bool dual=false) { } a = 255 - a; } - uint8_t s = dual ? sin_gap(a) : sin8(a); + uint8_t s = dual ? sin_gap(a) : sin8_t(a); uint32_t ca = color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 0), s); if (dual) { unsigned b = (SEGLEN-1-i)*x_scale - counter; @@ -1893,16 +1893,16 @@ uint16_t mode_pride_2015(void) { unsigned sPseudotime = SEGENV.step; unsigned sHue16 = SEGENV.aux0; - uint8_t sat8 = beatsin88( 87, 220, 250); - uint8_t brightdepth = beatsin88( 341, 96, 224); - unsigned brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256)); - unsigned msmultiplier = beatsin88(147, 23, 60); + uint8_t sat8 = beatsin88_t( 87, 220, 250); + uint8_t brightdepth = beatsin88_t( 341, 96, 224); + unsigned brightnessthetainc16 = beatsin88_t( 203, (25 * 256), (40 * 256)); + unsigned msmultiplier = beatsin88_t(147, 23, 60); unsigned hue16 = sHue16;//gHue * 256; - unsigned hueinc16 = beatsin88(113, 1, 3000); + unsigned hueinc16 = beatsin88_t(113, 1, 3000); sPseudotime += duration * msmultiplier; - sHue16 += duration * beatsin88( 400, 5,9); + sHue16 += duration * beatsin88_t( 400, 5,9); unsigned brightnesstheta16 = sPseudotime; for (unsigned i = 0 ; i < SEGLEN; i++) { @@ -1910,7 +1910,7 @@ uint16_t mode_pride_2015(void) { uint8_t hue8 = hue16 >> 8; brightnesstheta16 += brightnessthetainc16; - unsigned b16 = sin16( brightnesstheta16 ) + 32768; + unsigned b16 = sin16_t( brightnesstheta16 ) + 32768; unsigned bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536; uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536; @@ -1935,7 +1935,7 @@ uint16_t mode_juggle(void) { CRGB fastled_col; byte dothue = 0; for (int i = 0; i < 8; i++) { - int index = 0 + beatsin88((16 + SEGMENT.speed)*(i + 7), 0, SEGLEN -1); + int index = 0 + beatsin88_t((16 + SEGMENT.speed)*(i + 7), 0, SEGLEN -1); fastled_col = CRGB(SEGMENT.getPixelColor(index)); fastled_col |= (SEGMENT.palette==0)?CHSV(dothue, 220, 255):ColorFromPalette(SEGPALETTE, dothue, 255); SEGMENT.setPixelColor(index, fastled_col); @@ -1956,8 +1956,8 @@ uint16_t mode_palette() { constexpr mathType maxAngle = 0x8000; constexpr mathType staticRotationScale = 256; constexpr mathType animatedRotationScale = 1; - constexpr int16_t (*sinFunction)(uint16_t) = &sin16; - constexpr int16_t (*cosFunction)(uint16_t) = &cos16; + constexpr int16_t (*sinFunction)(uint16_t) = &sin16_t; + constexpr int16_t (*cosFunction)(uint16_t) = &cos16_t; #else using mathType = float; using wideMathType = float; @@ -2141,15 +2141,15 @@ uint16_t mode_colorwaves() { unsigned sPseudotime = SEGENV.step; unsigned sHue16 = SEGENV.aux0; - unsigned brightdepth = beatsin88(341, 96, 224); - unsigned brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256)); - unsigned msmultiplier = beatsin88(147, 23, 60); + unsigned brightdepth = beatsin88_t(341, 96, 224); + unsigned brightnessthetainc16 = beatsin88_t( 203, (25 * 256), (40 * 256)); + unsigned msmultiplier = beatsin88_t(147, 23, 60); unsigned hue16 = sHue16;//gHue * 256; - unsigned hueinc16 = beatsin88(113, 60, 300)*SEGMENT.intensity*10/255; // Use the Intensity Slider for the hues + unsigned hueinc16 = beatsin88_t(113, 60, 300)*SEGMENT.intensity*10/255; // Use the Intensity Slider for the hues sPseudotime += duration * msmultiplier; - sHue16 += duration * beatsin88(400, 5, 9); + sHue16 += duration * beatsin88_t(400, 5, 9); unsigned brightnesstheta16 = sPseudotime; for (int i = 0 ; i < SEGLEN; i++) { @@ -2163,7 +2163,7 @@ uint16_t mode_colorwaves() { } brightnesstheta16 += brightnessthetainc16; - unsigned b16 = sin16(brightnesstheta16) + 32768; + unsigned b16 = sin16_t(brightnesstheta16) + 32768; unsigned bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536; uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536; @@ -2182,7 +2182,7 @@ static const char _data_FX_MODE_COLORWAVES[] PROGMEM = "Colorwaves@!,Hue;!;!"; // colored stripes pulsing at a defined Beats-Per-Minute (BPM) uint16_t mode_bpm() { uint32_t stp = (strip.now / 20) & 0xFF; - uint8_t beat = beatsin8(SEGMENT.speed, 64, 255); + uint8_t beat = beatsin8_t(SEGMENT.speed, 64, 255); for (int i = 0; i < SEGLEN; i++) { SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(stp + (i * 2), false, PALETTE_SOLID_WRAP, 0, beat - stp + (i * 10))); } @@ -2198,7 +2198,7 @@ uint16_t mode_fillnoise8() { unsigned index = inoise8(i * SEGLEN, SEGENV.step + i * SEGLEN); SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0)); } - SEGENV.step += beatsin8(SEGMENT.speed, 1, 6); //10,1,4 + SEGENV.step += beatsin8_t(SEGMENT.speed, 1, 6); //10,1,4 return FRAMETIME; } @@ -2210,13 +2210,13 @@ uint16_t mode_noise16_1() { SEGENV.step += (1 + SEGMENT.speed/16); for (int i = 0; i < SEGLEN; i++) { - unsigned shift_x = beatsin8(11); // the x position of the noise field swings @ 17 bpm + unsigned shift_x = beatsin8_t(11); // the x position of the noise field swings @ 17 bpm unsigned shift_y = SEGENV.step/42; // the y position becomes slowly incremented unsigned real_x = (i + shift_x) * scale; // the x position of the noise field swings @ 17 bpm unsigned real_y = (i + shift_y) * scale; // the y position becomes slowly incremented uint32_t real_z = SEGENV.step; // the z position becomes quickly incremented unsigned noise = inoise16(real_x, real_y, real_z) >> 8; // get the noise data and scale it down - unsigned index = sin8(noise * 3); // map LED color based on noise data + unsigned index = sin8_t(noise * 3); // map LED color based on noise data SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0)); } @@ -2234,7 +2234,7 @@ uint16_t mode_noise16_2() { unsigned shift_x = SEGENV.step >> 6; // x as a function of time uint32_t real_x = (i + shift_x) * scale; // calculate the coordinates within the noise field unsigned noise = inoise16(real_x, 0, 4223) >> 8; // get the noise data and scale it down - unsigned index = sin8(noise * 3); // map led color based on noise data + unsigned index = sin8_t(noise * 3); // map led color based on noise data SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0, noise)); } @@ -2255,7 +2255,7 @@ uint16_t mode_noise16_3() { uint32_t real_y = (i + shift_y) * scale; // based on the precalculated positions uint32_t real_z = SEGENV.step*8; unsigned noise = inoise16(real_x, real_y, real_z) >> 8; // get the noise data and scale it down - unsigned index = sin8(noise * 3); // map led color based on noise data + unsigned index = sin8_t(noise * 3); // map led color based on noise data SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0, noise)); } @@ -2335,13 +2335,13 @@ static const char _data_FX_MODE_COLORTWINKLE[] PROGMEM = "Colortwinkles@Fade spe //Calm effect, like a lake at night uint16_t mode_lake() { unsigned sp = SEGMENT.speed/10; - int wave1 = beatsin8(sp +2, -64,64); - int wave2 = beatsin8(sp +1, -64,64); - int wave3 = beatsin8(sp +2, 0,80); + int wave1 = beatsin8_t(sp +2, -64,64); + int wave2 = beatsin8_t(sp +1, -64,64); + int wave3 = beatsin8_t(sp +2, 0,80); for (int i = 0; i < SEGLEN; i++) { - int index = cos8((i*15)+ wave1)/2 + cubicwave8((i*23)+ wave2)/2; + int index = cos8_t((i*15)+ wave1)/2 + cubicwave8((i*23)+ wave2)/2; uint8_t lum = (index > wave3) ? index - wave3 : 0; SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, false, 0, lum)); } @@ -2514,7 +2514,7 @@ static uint16_t ripple_base() { propI /= 2; unsigned cx = rippleorigin >> 8; unsigned cy = rippleorigin & 0xFF; - unsigned mag = scale8(sin8((propF>>2)), amp); + unsigned mag = scale8(sin8_t((propF>>2)), amp); if (propI > 0) SEGMENT.drawCircle(cx, cy, propI, color_blend(SEGMENT.getPixelColorXY(cx + propI, cy), col, mag), true); } else #endif @@ -2581,7 +2581,7 @@ static CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat) unsigned ticks = ms / SEGENV.aux0; unsigned fastcycle8 = ticks; unsigned slowcycle16 = (ticks >> 8) + salt; - slowcycle16 += sin8(slowcycle16); + slowcycle16 += sin8_t(slowcycle16); slowcycle16 = (slowcycle16 * 2053) + 1384; unsigned slowcycle8 = (slowcycle16 & 0xFF) + (slowcycle16 >> 8); @@ -3152,7 +3152,7 @@ static const char _data_FX_MODE_ROLLINGBALLS[] PROGMEM = "Rolling Balls@!,# of b static uint16_t sinelon_base(bool dual, bool rainbow=false) { if (SEGLEN == 1) return mode_static(); SEGMENT.fade_out(SEGMENT.intensity); - unsigned pos = beatsin16(SEGMENT.speed/10,0,SEGLEN-1); + unsigned pos = beatsin16_t(SEGMENT.speed/10,0,SEGLEN-1); if (SEGENV.call == 0) SEGENV.aux0 = pos; uint32_t color1 = SEGMENT.color_from_palette(pos, true, false, 0); uint32_t color2 = SEGCOLOR(2); @@ -3868,13 +3868,13 @@ uint16_t mode_plasma(void) { if (SEGENV.call == 0) { SEGENV.aux0 = random8(0,2); // add a bit of randomness } - unsigned thisPhase = beatsin8(6+SEGENV.aux0,-64,64); - unsigned thatPhase = beatsin8(7+SEGENV.aux0,-64,64); + unsigned thisPhase = beatsin8_t(6+SEGENV.aux0,-64,64); + unsigned thatPhase = beatsin8_t(7+SEGENV.aux0,-64,64); for (unsigned i = 0; i < SEGLEN; i++) { // For each of the LED's in the strand, set color & brightness based on a wave as follows: unsigned colorIndex = cubicwave8((i*(2+ 3*(SEGMENT.speed >> 5))+thisPhase) & 0xFF)/2 // factor=23 // Create a wave and add a phase change and add another wave with its own phase change. - + cos8((i*(1+ 2*(SEGMENT.speed >> 5))+thatPhase) & 0xFF)/2; // factor=15 // Hey, you can even change the frequencies if you wish. - unsigned thisBright = qsub8(colorIndex, beatsin8(7,0, (128 - (SEGMENT.intensity>>1)))); + + cos8_t((i*(1+ 2*(SEGMENT.speed >> 5))+thatPhase) & 0xFF)/2; // factor=15 // Hey, you can even change the frequencies if you wish. + unsigned thisBright = qsub8(colorIndex, beatsin8_t(7,0, (128 - (SEGMENT.intensity>>1)))); SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(colorIndex, false, PALETTE_SOLID_WRAP, 0, thisBright)); } @@ -4001,10 +4001,10 @@ static CRGB pacifica_one_layer(uint16_t i, CRGBPalette16& p, uint16_t cistart, u unsigned wavescale_half = (wavescale >> 1) + 20; waveangle += ((120 + SEGMENT.intensity) * i); //original 250 * i - unsigned s16 = sin16(waveangle) + 32768; + unsigned s16 = sin16_t(waveangle) + 32768; unsigned cs = scale16(s16, wavescale_half) + wavescale_half; ci += (cs * i); - unsigned sindex16 = sin16(ci) + 32768; + unsigned sindex16 = sin16_t(ci) + 32768; unsigned sindex8 = scale16(sindex16, 240); return ColorFromPalette(p, sindex8, bri, LINEARBLEND); } @@ -4036,34 +4036,34 @@ uint16_t mode_pacifica() uint64_t deltat = (strip.now >> 2) + ((strip.now * SEGMENT.speed) >> 7); strip.now = deltat; - unsigned speedfactor1 = beatsin16(3, 179, 269); - unsigned speedfactor2 = beatsin16(4, 179, 269); + unsigned speedfactor1 = beatsin16_t(3, 179, 269); + unsigned speedfactor2 = beatsin16_t(4, 179, 269); uint32_t deltams1 = (deltams * speedfactor1) / 256; uint32_t deltams2 = (deltams * speedfactor2) / 256; uint32_t deltams21 = (deltams1 + deltams2) / 2; - sCIStart1 += (deltams1 * beatsin88(1011,10,13)); - sCIStart2 -= (deltams21 * beatsin88(777,8,11)); - sCIStart3 -= (deltams1 * beatsin88(501,5,7)); - sCIStart4 -= (deltams2 * beatsin88(257,4,6)); + sCIStart1 += (deltams1 * beatsin88_t(1011,10,13)); + sCIStart2 -= (deltams21 * beatsin88_t(777,8,11)); + 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; // Clear out the LED array to a dim background blue-green //SEGMENT.fill(132618); - unsigned basethreshold = beatsin8( 9, 55, 65); + unsigned basethreshold = beatsin8_t( 9, 55, 65); unsigned wave = beat8( 7 ); for (int i = 0; i < SEGLEN; i++) { CRGB c = CRGB(2, 6, 10); // Render each of four layers, with different scales and speeds, that vary over time - c += pacifica_one_layer(i, pacifica_palette_1, sCIStart1, beatsin16(3, 11 * 256, 14 * 256), beatsin8(10, 70, 130), 0-beat16(301)); - c += pacifica_one_layer(i, pacifica_palette_2, sCIStart2, beatsin16(4, 6 * 256, 9 * 256), beatsin8(17, 40, 80), beat16(401)); - c += pacifica_one_layer(i, pacifica_palette_3, sCIStart3, 6 * 256 , beatsin8(9, 10,38) , 0-beat16(503)); - c += pacifica_one_layer(i, pacifica_palette_3, sCIStart4, 5 * 256 , beatsin8(8, 10,28) , beat16(601)); + c += pacifica_one_layer(i, pacifica_palette_1, sCIStart1, beatsin16_t(3, 11 * 256, 14 * 256), beatsin8_t(10, 70, 130), 0-beat16(301)); + c += pacifica_one_layer(i, pacifica_palette_2, sCIStart2, beatsin16_t(4, 6 * 256, 9 * 256), beatsin8_t(17, 40, 80), beat16(401)); + c += pacifica_one_layer(i, pacifica_palette_3, sCIStart3, 6 * 256 , beatsin8_t(9, 10,38) , 0-beat16(503)); + c += pacifica_one_layer(i, pacifica_palette_3, sCIStart4, 5 * 256 , beatsin8_t(8, 10,28) , beat16(601)); // Add extra 'white' to areas where the four layers of light have lined up brightly - unsigned threshold = scale8( sin8( wave), 20) + basethreshold; + unsigned threshold = scale8( sin8_t( wave), 20) + basethreshold; wave += 7; unsigned l = c.getAverageLight(); if (l > threshold) { @@ -4187,7 +4187,7 @@ uint16_t mode_twinkleup(void) { // A very short twinkle routine for (int i = 0; i < SEGLEN; i++) { unsigned ranstart = random8(); // The starting value (aka brightness) for each pixel. Must be consistent each time through the loop for this to work. - unsigned pixBri = sin8(ranstart + 16 * strip.now/(256-SEGMENT.speed)); + unsigned pixBri = sin8_t(ranstart + 16 * strip.now/(256-SEGMENT.speed)); if (random8() > SEGMENT.intensity) pixBri = 0; SEGMENT.setPixelColor(i, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(random8()+strip.now/100, false, PALETTE_SOLID_WRAP, 0), pixBri)); } @@ -4230,7 +4230,7 @@ uint16_t mode_noisepal(void) { // Slow noise SEGMENT.setPixelColor(i, color.red, color.green, color.blue); } - SEGENV.aux0 += beatsin8(10,1,4); // Moving along the distance. Vary it a bit with a sine wave. + SEGENV.aux0 += beatsin8_t(10,1,4); // Moving along the distance. Vary it a bit with a sine wave. return FRAMETIME; } @@ -4312,7 +4312,7 @@ uint16_t mode_chunchun(void) for (unsigned i = 0; i < numBirds; i++) { counter -= span; - unsigned megumin = sin16(counter) + 0x8000; + unsigned megumin = sin16_t(counter) + 0x8000; unsigned bird = uint32_t(megumin * SEGLEN) >> 16; uint32_t c = SEGMENT.color_from_palette((i * 255)/ numBirds, false, false, 0); // no palette wrapping bird = constrain(bird, 0U, SEGLEN-1U); @@ -4481,7 +4481,7 @@ uint16_t mode_washing_machine(void) { SEGENV.step += (speed * 2048) / (512 - SEGMENT.speed); for (int i = 0; i < SEGLEN; i++) { - uint8_t col = sin8(((SEGMENT.intensity / 25 + 1) * 255 * i / SEGLEN) + (SEGENV.step >> 7)); + uint8_t col = sin8_t(((SEGMENT.intensity / 25 + 1) * 255 * i / SEGLEN) + (SEGENV.step >> 7)); SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(col, false, PALETTE_SOLID_WRAP, 3)); } @@ -4837,8 +4837,8 @@ static const char _data_FX_MODE_PERLINMOVE[] PROGMEM = "Perlin Move@!,# of pixel uint16_t mode_wavesins(void) { for (int i = 0; i < SEGLEN; i++) { - uint8_t bri = sin8(strip.now/4 + i * SEGMENT.intensity); - uint8_t index = beatsin8(SEGMENT.speed, SEGMENT.custom1, SEGMENT.custom1+SEGMENT.custom2, 0, i * (SEGMENT.custom3<<3)); // custom3 is reduced resolution slider + uint8_t bri = sin8_t(strip.now/4 + i * SEGMENT.intensity); + uint8_t index = beatsin8_t(SEGMENT.speed, SEGMENT.custom1, SEGMENT.custom1+SEGMENT.custom2, 0, i * (SEGMENT.custom3<<3)); // custom3 is reduced resolution slider //SEGMENT.setPixelColor(i, ColorFromPalette(SEGPALETTE, index, bri, LINEARBLEND)); SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0, bri)); } @@ -4860,9 +4860,9 @@ uint16_t mode_FlowStripe(void) { for (int i = 0; i < SEGLEN; i++) { int c = (abs(i - hl) / hl) * 127; - c = sin8(c); - c = sin8(c / 2 + t); - byte b = sin8(c + t/8); + c = sin8_t(c); + c = sin8_t(c / 2 + t); + byte b = sin8_t(c + t/8); SEGMENT.setPixelColor(i, CHSV(b + hue, 255, 255)); } @@ -4889,14 +4889,14 @@ uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulma unsigned long t = strip.now/128; // timebase // outer stars for (size_t i = 0; i < 8; i++) { - x = beatsin8(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + t * i); - y = beatsin8(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + t * i); + x = beatsin8_t(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + t * i); + y = beatsin8_t(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + t * i); SEGMENT.addPixelColorXY(x, y, SEGMENT.color_from_palette(i*32, false, PALETTE_SOLID_WRAP, SEGMENT.check1?0:255)); } // inner stars for (size_t i = 0; i < 4; i++) { - x = beatsin8(SEGMENT.custom2>>3, cols/4, cols - 1 - cols/4, 0, ((i % 2) ? 128 : 0) + t * i); - y = beatsin8(SEGMENT.custom3 , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + t * i); + x = beatsin8_t(SEGMENT.custom2>>3, cols/4, cols - 1 - cols/4, 0, ((i % 2) ? 128 : 0) + t * i); + y = beatsin8_t(SEGMENT.custom3 , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + t * i); SEGMENT.addPixelColorXY(x, y, SEGMENT.color_from_palette(255-i*64, false, PALETTE_SOLID_WRAP, SEGMENT.check1?0:255)); } // central white dot @@ -4930,10 +4930,10 @@ uint16_t mode_2DColoredBursts() { // By: ldirko https://editor.so SEGENV.aux0++; // hue 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, (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); + byte x1 = beatsin8_t(2 + SEGMENT.speed/16, 0, (cols - 1)); + byte x2 = beatsin8_t(1 + SEGMENT.speed/16, 0, (rows - 1)); + byte y1 = beatsin8_t(5 + SEGMENT.speed/16, 0, (cols - 1), 0, i * 24); + byte y2 = beatsin8_t(3 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 48 + 64); CRGB color = ColorFromPalette(SEGPALETTE, i * 255 / numLines + (SEGENV.aux0&0xFF), 255, LINEARBLEND); byte xsteps = abs8(x1 - y1) + 1; @@ -4972,8 +4972,8 @@ uint16_t mode_2Ddna(void) { // dna originally by by ldirko at https://pa SEGMENT.fadeToBlackBy(64); for (int i = 0; i < cols; i++) { - SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4 ), ColorFromPalette(SEGPALETTE, i*5+strip.now/17, beatsin8(5, 55, 255, 0, i*10), LINEARBLEND)); - SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4+128), ColorFromPalette(SEGPALETTE, i*5+128+strip.now/17, beatsin8(5, 55, 255, 0, i*10+128), LINEARBLEND)); + SEGMENT.setPixelColorXY(i, beatsin8_t(SEGMENT.speed/8, 0, rows-1, 0, i*4 ), ColorFromPalette(SEGPALETTE, i*5+strip.now/17, beatsin8_t(5, 55, 255, 0, i*10), LINEARBLEND)); + SEGMENT.setPixelColorXY(i, beatsin8_t(SEGMENT.speed/8, 0, rows-1, 0, i*4+128), ColorFromPalette(SEGPALETTE, i*5+128+strip.now/17, beatsin8_t(5, 55, 255, 0, i*10+128), LINEARBLEND)); } SEGMENT.blur(SEGMENT.intensity>>3); @@ -5002,8 +5002,8 @@ uint16_t mode_2DDNASpiral() { // By: ldirko https://editor.soulma SEGMENT.fadeToBlackBy(135); for (int i = 0; i < rows; i++) { - int x = beatsin8(speeds, 0, cols - 1, 0, i * freq) + beatsin8(speeds - 7, 0, cols - 1, 0, i * freq + 128); - int x1 = beatsin8(speeds, 0, cols - 1, 0, 128 + i * freq) + beatsin8(speeds - 7, 0, cols - 1, 0, 128 + 64 + i * freq); + int x = beatsin8_t(speeds, 0, cols - 1, 0, i * freq) + beatsin8_t(speeds - 7, 0, cols - 1, 0, i * freq + 128); + int x1 = beatsin8_t(speeds, 0, cols - 1, 0, 128 + i * freq) + beatsin8_t(speeds - 7, 0, cols - 1, 0, 128 + 64 + i * freq); unsigned hue = (i * 128 / rows) + ms; // skip every 4th row every now and then (fade it more) if ((i + ms / 8) & 3) { @@ -5104,9 +5104,9 @@ uint16_t mode_2DFrizzles(void) { // By: Stepko https://editor.so SEGMENT.fadeToBlackBy(16); for (size_t i = 8; i > 0; i--) { - SEGMENT.addPixelColorXY(beatsin8(SEGMENT.speed/8 + i, 0, cols - 1), - beatsin8(SEGMENT.intensity/8 - i, 0, rows - 1), - ColorFromPalette(SEGPALETTE, beatsin8(12, 0, 255), 255, LINEARBLEND)); + SEGMENT.addPixelColorXY(beatsin8_t(SEGMENT.speed/8 + i, 0, cols - 1), + beatsin8_t(SEGMENT.intensity/8 - i, 0, rows - 1), + ColorFromPalette(SEGPALETTE, beatsin8_t(12, 0, 255), 255, LINEARBLEND)); } SEGMENT.blur(SEGMENT.custom1>>3); @@ -5238,7 +5238,7 @@ uint16_t mode_2DHiphotic() { // By: ldirko https://edit for (int x = 0; x < cols; x++) { for (int y = 0; y < rows; y++) { - SEGMENT.setPixelColorXY(x, y, SEGMENT.color_from_palette(sin8(cos8(x * SEGMENT.speed/16 + a / 3) + sin8(y * SEGMENT.intensity/16 + a / 4) + a), false, PALETTE_SOLID_WRAP, 0)); + SEGMENT.setPixelColorXY(x, y, SEGMENT.color_from_palette(sin8_t(cos8_t(x * SEGMENT.speed/16 + a / 3) + sin8_t(y * SEGMENT.intensity/16 + a / 4) + a), false, PALETTE_SOLID_WRAP, 0)); } } @@ -5378,10 +5378,10 @@ uint16_t mode_2DLissajous(void) { // By: Andrew Tuline //for (int i=0; i < 4*(cols+rows); i ++) { for (int i=0; i < 256; i ++) { - //float xlocn = float(sin8(now/4+i*(SEGMENT.speed>>5))) / 255.0f; - //float ylocn = float(cos8(now/4+i*2)) / 255.0f; - uint_fast8_t xlocn = sin8(phase/2 + (i*SEGMENT.speed)/32); - uint_fast8_t ylocn = cos8(phase/2 + i*2); + //float xlocn = float(sin8_t(now/4+i*(SEGMENT.speed>>5))) / 255.0f; + //float ylocn = float(cos8_t(now/4+i*2)) / 255.0f; + uint_fast8_t xlocn = sin8_t(phase/2 + (i*SEGMENT.speed)/32); + uint_fast8_t ylocn = cos8_t(phase/2 + i*2); xlocn = (cols < 2) ? 1 : (map(2*xlocn, 0,511, 0,2*(cols-1)) +1) /2; // softhack007: "(2* ..... +1) /2" for proper rounding ylocn = (rows < 2) ? 1 : (map(2*ylocn, 0,511, 0,2*(rows-1)) +1) /2; // "rows > 1" is needed to avoid div/0 in map() SEGMENT.setPixelColorXY((uint8_t)xlocn, (uint8_t)ylocn, SEGMENT.color_from_palette(strip.now/100+i, false, PALETTE_SOLID_WRAP, 0)); @@ -5481,8 +5481,8 @@ uint16_t mode_2Dmetaballs(void) { // Metaballs by Stefan Petrick. Cannot have int y3 = map(inoise8(strip.now * speed, 25355, 22685), 0, 255, 0, rows-1); // and one Lissajou function - int x1 = beatsin8(23 * speed, 0, cols-1); - int y1 = beatsin8(28 * speed, 0, rows-1); + int x1 = beatsin8_t(23 * speed, 0, cols-1); + int y1 = beatsin8_t(28 * speed, 0, rows-1); for (int y = 0; y < rows; y++) { for (int x = 0; x < cols; x++) { @@ -5647,7 +5647,7 @@ uint16_t mode_2DPulser(void) { // By: ldirko https://edi SEGMENT.fadeToBlackBy(8 - (SEGMENT.intensity>>5)); uint32_t a = strip.now / (18 - SEGMENT.speed / 16); int x = (a / 14) % cols; - int y = map((sin8(a * 5) + sin8(a * 4) + sin8(a * 2)), 0, 765, rows-1, 0); + int y = map((sin8_t(a * 5) + sin8_t(a * 4) + sin8_t(a * 2)), 0, 765, rows-1, 0); SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, map(y, 0, rows-1, 0, 255), 255, LINEARBLEND)); SEGMENT.blur(SEGMENT.intensity>>4); @@ -5673,10 +5673,10 @@ uint16_t mode_2DSindots(void) { // By: ldirko http SEGMENT.fadeToBlackBy(SEGMENT.custom1>>3); byte t1 = strip.now / (257 - SEGMENT.speed); // 20; - byte t2 = sin8(t1) / 4 * 2; + byte t2 = sin8_t(t1) / 4 * 2; for (int i = 0; i < 13; i++) { - int x = sin8(t1 + i * SEGMENT.intensity/8)*(cols-1)/255; // max index now 255x15/255=15! - int y = sin8(t2 + i * SEGMENT.intensity/8)*(rows-1)/255; // max index now 255x15/255=15! + int x = sin8_t(t1 + i * SEGMENT.intensity/8)*(cols-1)/255; // max index now 255x15/255=15! + int y = sin8_t(t2 + i * SEGMENT.intensity/8)*(rows-1)/255; // max index now 255x15/255=15! SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, i * 255 / 13, 255, LINEARBLEND)); } SEGMENT.blur(SEGMENT.custom2>>3); @@ -5703,12 +5703,12 @@ uint16_t mode_2Dsquaredswirl(void) { // By: Mark Kriegsman. https://g SEGMENT.blur(SEGMENT.custom3>>1); // Use two out-of-sync sine waves - int i = beatsin8(19, kBorderWidth, cols-kBorderWidth); - int j = beatsin8(22, kBorderWidth, cols-kBorderWidth); - int k = beatsin8(17, kBorderWidth, cols-kBorderWidth); - int m = beatsin8(18, kBorderWidth, rows-kBorderWidth); - int n = beatsin8(15, kBorderWidth, rows-kBorderWidth); - int p = beatsin8(20, kBorderWidth, rows-kBorderWidth); + int i = beatsin8_t(19, kBorderWidth, cols-kBorderWidth); + int j = beatsin8_t(22, kBorderWidth, cols-kBorderWidth); + int k = beatsin8_t(17, kBorderWidth, cols-kBorderWidth); + int m = beatsin8_t(18, kBorderWidth, rows-kBorderWidth); + int n = beatsin8_t(15, kBorderWidth, rows-kBorderWidth); + int p = beatsin8_t(20, kBorderWidth, rows-kBorderWidth); SEGMENT.addPixelColorXY(i, m, ColorFromPalette(SEGPALETTE, strip.now/29, 255, LINEARBLEND)); SEGMENT.addPixelColorXY(j, n, ColorFromPalette(SEGPALETTE, strip.now/41, 255, LINEARBLEND)); @@ -5784,19 +5784,19 @@ uint16_t mode_2Dtartan(void) { // By: Elliott Kember https://editor.so uint8_t hue, bri; size_t intensity; - int offsetX = beatsin16(3, -360, 360); - int offsetY = beatsin16(2, -360, 360); + int offsetX = beatsin16_t(3, -360, 360); + int offsetY = beatsin16_t(2, -360, 360); int sharpness = SEGMENT.custom3 / 8; // 0-3 for (int x = 0; x < cols; x++) { for (int y = 0; y < rows; y++) { - hue = x * beatsin16(10, 1, 10) + offsetY; - intensity = bri = sin8(x * SEGMENT.speed/2 + offsetX); + hue = x * beatsin16_t(10, 1, 10) + offsetY; + intensity = bri = sin8_t(x * SEGMENT.speed/2 + offsetX); for (int i=0; i>= 8*sharpness; SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, hue, intensity, LINEARBLEND)); hue = y * 3 + offsetX; - intensity = bri = sin8(y * SEGMENT.intensity/2 + offsetY); + intensity = bri = sin8_t(y * SEGMENT.intensity/2 + offsetY); for (int i=0; i>= 8*sharpness; SEGMENT.addPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, hue, intensity, LINEARBLEND)); @@ -5831,9 +5831,9 @@ uint16_t mode_2Dspaceships(void) { //// Space ships by stepko (c)05.02.21 [ht SEGMENT.move(SEGENV.aux0, 1); for (size_t i = 0; i < 8; i++) { - int x = beatsin8(12 + i, 2, cols - 3); - int y = beatsin8(15 + i, 2, rows - 3); - CRGB color = ColorFromPalette(SEGPALETTE, beatsin8(12 + i, 0, 255), 255); + int x = beatsin8_t(12 + i, 2, cols - 3); + int y = beatsin8_t(15 + i, 2, rows - 3); + CRGB color = ColorFromPalette(SEGPALETTE, beatsin8_t(12 + i, 0, 255), 255); SEGMENT.addPixelColorXY(x, y, color); if (cols > 24 || rows > 24) { SEGMENT.addPixelColorXY(x+1, y, color); @@ -6229,8 +6229,8 @@ uint16_t mode_2Ddriftrose(void) { SEGMENT.fadeToBlackBy(32+(SEGMENT.speed>>3)); for (size_t i = 1; i < 37; i++) { float angle = radians(i * 10); - uint32_t x = (CX + (sin_t(angle) * (beatsin8(i, 0, L*2)-L))) * 255.f; - uint32_t y = (CY + (cos_t(angle) * (beatsin8(i, 0, L*2)-L))) * 255.f; + uint32_t x = (CX + (sin_t(angle) * (beatsin8_t(i, 0, L*2)-L))) * 255.f; + uint32_t y = (CY + (cos_t(angle) * (beatsin8_t(i, 0, L*2)-L))) * 255.f; SEGMENT.wu_pixel(x, y, CHSV(i * 10, 255, 255)); } SEGMENT.blur(SEGMENT.intensity>>4); @@ -6426,8 +6426,8 @@ uint16_t mode_2DSwirl(void) { SEGMENT.blur(SEGMENT.custom1); - int i = beatsin8( 27*SEGMENT.speed/255, borderWidth, cols - borderWidth); - int j = beatsin8( 41*SEGMENT.speed/255, borderWidth, rows - borderWidth); + int i = beatsin8_t( 27*SEGMENT.speed/255, borderWidth, cols - borderWidth); + int j = beatsin8_t( 41*SEGMENT.speed/255, borderWidth, rows - borderWidth); int ni = (cols - 1) - i; int nj = (cols - 1) - j; @@ -6639,7 +6639,7 @@ uint16_t mode_juggles(void) { // Juggles. By Andrew Tuline. for (size_t i=0; ithisphase += beatsin8(6,-4,4); // You can change direction and speed individually. - plasmoip->thatphase += beatsin8(7,-4,4); // Two phase values to make a complex pattern. By Andrew Tuline. + plasmoip->thisphase += beatsin8_t(6,-4,4); // You can change direction and speed individually. + plasmoip->thatphase += beatsin8_t(7,-4,4); // Two phase values to make a complex pattern. By Andrew Tuline. for (int i = 0; i < SEGLEN; i++) { // For each of the LED's in the strand, set a brightness based on a wave as follows. // updated, similar to "plasma" effect - softhack007 uint8_t thisbright = cubicwave8(((i*(1 + (3*SEGMENT.speed/32)))+plasmoip->thisphase) & 0xFF)/2; - thisbright += cos8(((i*(97 +(5*SEGMENT.speed/32)))+plasmoip->thatphase) & 0xFF)/2; // Let's munge the brightness a bit and animate it all with the phases. + thisbright += cos8_t(((i*(97 +(5*SEGMENT.speed/32)))+plasmoip->thatphase) & 0xFF)/2; // Let's munge the brightness a bit and animate it all with the phases. uint8_t colorIndex=thisbright; if (volumeSmth * SEGMENT.intensity / 64 < thisbright) {thisbright = 0;} @@ -7280,7 +7280,7 @@ uint16_t mode_rocktaves(void) { // Rocktaves. Same note from eac frTemp -= 132.0f; // This should give us a base musical note of C3 frTemp = fabsf(frTemp * 2.1f); // Fudge factors to compress octave range starting at 0 and going to 255; - unsigned i = map(beatsin8(8+octCount*4, 0, 255, 0, octCount*8), 0, 255, 0, SEGLEN-1); + unsigned i = map(beatsin8_t(8+octCount*4, 0, 255, 0, octCount*8), 0, 255, 0, SEGLEN-1); i = constrain(i, 0U, SEGLEN-1U); SEGMENT.addPixelColor(i, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette((uint8_t)frTemp, false, PALETTE_SOLID_WRAP, 0), volTemp)); @@ -7567,12 +7567,12 @@ uint16_t mode_2Ddistortionwaves() { unsigned a2 = a/2; unsigned a3 = a/3; - unsigned cx = beatsin8(10-speed,0,cols-1)*scale; - unsigned cy = beatsin8(12-speed,0,rows-1)*scale; - unsigned cx1 = beatsin8(13-speed,0,cols-1)*scale; - unsigned cy1 = beatsin8(15-speed,0,rows-1)*scale; - unsigned cx2 = beatsin8(17-speed,0,cols-1)*scale; - unsigned cy2 = beatsin8(14-speed,0,rows-1)*scale; + unsigned cx = beatsin8_t(10-speed,0,cols-1)*scale; + unsigned cy = beatsin8_t(12-speed,0,rows-1)*scale; + unsigned cx1 = beatsin8_t(13-speed,0,cols-1)*scale; + unsigned cy1 = beatsin8_t(15-speed,0,rows-1)*scale; + unsigned cx2 = beatsin8_t(17-speed,0,cols-1)*scale; + unsigned cy2 = beatsin8_t(14-speed,0,rows-1)*scale; unsigned xoffs = 0; for (int x = 0; x < cols; x++) { @@ -7582,17 +7582,17 @@ uint16_t mode_2Ddistortionwaves() { for (int y = 0; y < rows; y++) { yoffs += scale; - byte rdistort = cos8((cos8(((x<<3)+a )&255)+cos8(((y<<3)-a2)&255)+a3 )&255)>>1; - byte gdistort = cos8((cos8(((x<<3)-a2)&255)+cos8(((y<<3)+a3)&255)+a+32 )&255)>>1; - byte bdistort = cos8((cos8(((x<<3)+a3)&255)+cos8(((y<<3)-a) &255)+a2+64)&255)>>1; + byte rdistort = cos8_t((cos8_t(((x<<3)+a )&255)+cos8_t(((y<<3)-a2)&255)+a3 )&255)>>1; + byte gdistort = cos8_t((cos8_t(((x<<3)-a2)&255)+cos8_t(((y<<3)+a3)&255)+a+32 )&255)>>1; + byte bdistort = cos8_t((cos8_t(((x<<3)+a3)&255)+cos8_t(((y<<3)-a) &255)+a2+64)&255)>>1; byte valueR = rdistort+ w* (a- ( ((xoffs - cx) * (xoffs - cx) + (yoffs - cy) * (yoffs - cy))>>7 )); byte valueG = gdistort+ w* (a2-( ((xoffs - cx1) * (xoffs - cx1) + (yoffs - cy1) * (yoffs - cy1))>>7 )); byte valueB = bdistort+ w* (a3-( ((xoffs - cx2) * (xoffs - cx2) + (yoffs - cy2) * (yoffs - cy2))>>7 )); - valueR = gamma8(cos8(valueR)); - valueG = gamma8(cos8(valueG)); - valueB = gamma8(cos8(valueB)); + valueR = gamma8(cos8_t(valueR)); + valueG = gamma8(cos8_t(valueG)); + valueB = gamma8(cos8_t(valueB)); SEGMENT.setPixelColorXY(x, y, RGBW32(valueR, valueG, valueB, 0)); } @@ -7749,7 +7749,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 = 40.7436f * atan2_t((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 } } @@ -7760,8 +7760,8 @@ uint16_t mode_2Doctopus() { for (int y = 0; y < rows; y++) { byte angle = rMap[XY(x,y)].angle; byte radius = rMap[XY(x,y)].radius; - //CRGB c = CHSV(SEGENV.step / 2 - radius, 255, sin8(sin8((angle * 4 - radius) / 4 + SEGENV.step) + radius - SEGENV.step * 2 + angle * (SEGMENT.custom3/3+1))); - unsigned intensity = sin8(sin8((angle * 4 - radius) / 4 + SEGENV.step/2) + radius - SEGENV.step + angle * (SEGMENT.custom3/4+1)); + //CRGB c = CHSV(SEGENV.step / 2 - radius, 255, sin8_t(sin8_t((angle * 4 - radius) / 4 + SEGENV.step) + radius - SEGENV.step * 2 + angle * (SEGMENT.custom3/3+1))); + unsigned intensity = sin8_t(sin8_t((angle * 4 - radius) / 4 + SEGENV.step/2) + radius - SEGENV.step + angle * (SEGMENT.custom3/4+1)); intensity = map((intensity*intensity) & 0xFFFF, 0, 65535, 0, 255); // add a bit of non-linearity for cleaner display CRGB c = ColorFromPalette(SEGPALETTE, SEGENV.step / 2 - radius, intensity); SEGMENT.setPixelColorXY(x, y, c); @@ -7769,7 +7769,7 @@ uint16_t mode_2Doctopus() { } return FRAMETIME; } -static const char _data_FX_MODE_2DOCTOPUS[] PROGMEM = "Octopus@!,,Offset X,Offset Y,Legs;;!;2;"; +static const char _data_FX_MODE_2DOCTOPUS[] PROGMEM = "Octopus@!,,Offset X,Offset Y,Legs,fasttan;;!;2;"; //Waving Cell @@ -7786,7 +7786,7 @@ uint16_t mode_2Dwavingcell() { uint8_t aY = SEGMENT.custom2/16 + 1; uint8_t aZ = SEGMENT.custom3 + 1; for (int x = 0; x < cols; x++) for (int y = 0; y T atan_t(T x); - float cos_t(float phi); - float sin_t(float x); - float tan_t(float x); - float acos_t(float x); - float asin_t(float x); - float floor_t(float x); - float fmod_t(float num, float denom); -#else - #include - #define sin_t sinf - #define cos_t cosf - #define tan_t tanf - #define asin_t asinf - #define acos_t acosf - #define atan_t atanf - #define fmod_t fmodf - #define floor_t floorf -#endif +//float cos_t(float phi); // use float math +//float sin_t(float phi); +//float tan_t(float x); +int16_t sin16_t(uint16_t theta); +int16_t cos16_t(uint16_t theta); +uint8_t sin8_t(uint8_t theta); +uint8_t cos8_t(uint8_t theta); +float sin_approx(float theta); // uses integer math (converted to float), accuracy +/-0.0015 (compared to sinf()) +float cos_approx(float theta); +float tan_approx(float x); +float atan2_t(float y, float x); +float acos_t(float x); +float asin_t(float x); +template T atan_t(T x); +float floor_t(float x); +float fmod_t(float num, float denom); +#define sin_t sin_approx +#define cos_t cos_approx +#define tan_t tan_approx +/* +#include // standard math functions. use a lot of flash +#define sin_t sinf +#define cos_t cosf +#define tan_t tanf +#define asin_t asinf +#define acos_t acosf +#define atan_t atanf +#define fmod_t fmodf +#define floor_t floorf +*/ //wled_serial.cpp void handleSerial(); void updateBaudRate(uint32_t rate); diff --git a/wled00/util.cpp b/wled00/util.cpp index 0b78a4646..c43fdeabf 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -372,6 +372,39 @@ uint16_t crc16(const unsigned char* data_p, size_t length) { return crc; } +// fastled beatsin: 1:1 replacements to remove the use of fastled sin16() +// Generates a 16-bit sine wave at a given BPM that oscillates within a given range. see fastled for details. +uint16_t beatsin88_t(accum88 beats_per_minute_88, uint16_t lowest, uint16_t highest, uint32_t timebase, uint16_t phase_offset) +{ + uint16_t beat = beat88( beats_per_minute_88, timebase); + uint16_t beatsin (sin16_t( beat + phase_offset) + 32768); + uint16_t rangewidth = highest - lowest; + uint16_t scaledbeat = scale16( beatsin, rangewidth); + uint16_t result = lowest + scaledbeat; + return result; +} + +// Generates a 16-bit sine wave at a given BPM that oscillates within a given range. see fastled for details. +uint16_t beatsin16_t(accum88 beats_per_minute, uint16_t lowest, uint16_t highest, uint32_t timebase, uint16_t phase_offset) +{ + uint16_t beat = beat16( beats_per_minute, timebase); + uint16_t beatsin = (sin16_t( beat + phase_offset) + 32768); + uint16_t rangewidth = highest - lowest; + uint16_t scaledbeat = scale16( beatsin, rangewidth); + uint16_t result = lowest + scaledbeat; + return result; +} + +// Generates an 8-bit sine wave at a given BPM that oscillates within a given range. see fastled for details. +uint8_t beatsin8_t(accum88 beats_per_minute, uint8_t lowest, uint8_t highest, uint32_t timebase, uint8_t phase_offset) +{ + uint8_t beat = beat8( beats_per_minute, timebase); + uint8_t beatsin = sin8_t( beat + phase_offset); + uint8_t rangewidth = highest - lowest; + uint8_t scaledbeat = scale8( beatsin, rangewidth); + uint8_t result = lowest + scaledbeat; + return result; +} /////////////////////////////////////////////////////////////////////////////// // Begin simulateSound (to enable audio enhanced effects to display something) @@ -431,8 +464,8 @@ um_data_t* simulateSound(uint8_t simulationId) default: case UMS_BeatSin: for (int i = 0; i<16; i++) - fftResult[i] = beatsin8(120 / (i+1), 0, 255); - // fftResult[i] = (beatsin8(120, 0, 255) + (256/16 * i)) % 256; + fftResult[i] = beatsin8_t(120 / (i+1), 0, 255); + // fftResult[i] = (beatsin8_t(120, 0, 255) + (256/16 * i)) % 256; volumeSmth = fftResult[8]; break; case UMS_WeWillRockYou: @@ -469,12 +502,12 @@ um_data_t* simulateSound(uint8_t simulationId) break; case UMS_10_13: for (int i = 0; i<16; i++) - fftResult[i] = inoise8(beatsin8(90 / (i+1), 0, 200)*15 + (ms>>10), ms>>3); + fftResult[i] = inoise8(beatsin8_t(90 / (i+1), 0, 200)*15 + (ms>>10), ms>>3); volumeSmth = fftResult[8]; break; case UMS_14_3: for (int i = 0; i<16; i++) - fftResult[i] = inoise8(beatsin8(120 / (i+1), 10, 30)*10 + (ms>>14), ms>>3); + fftResult[i] = inoise8(beatsin8_t(120 / (i+1), 10, 30)*10 + (ms>>14), ms>>3); volumeSmth = fftResult[8]; break; } diff --git a/wled00/wled_math.cpp b/wled00/wled_math.cpp index a4c9fc123..401446a23 100644 --- a/wled00/wled_math.cpp +++ b/wled00/wled_math.cpp @@ -12,6 +12,12 @@ #define modd(x, y) ((x) - (int)((x) / (y)) * (y)) +// Note: cos_t, sin_t and tan_t are very accurate but may be slow +// the math.h functions use several kB of flash and are to be avoided if possible +// sin16_t / cos16_t are faster and much more accurate than the fastled variants +// sin_approx and cos_approx are float wrappers for sin16_t/cos16_t and have an accuracy of +/-0.0015 compared to sinf() +// sin8_t / cos8_t are fastled replacements and use sin16_t / cos16_t. Slightly slower than fastled version but very accurate + float cos_t(float phi) { float x = modd(phi, TWO_PI); @@ -31,8 +37,8 @@ float cos_t(float phi) return res; } -float sin_t(float x) { - float res = cos_t(HALF_PI - x); +float sin_t(float phi) { + float res = cos_t(HALF_PI - phi); #ifdef WLED_DEBUG_MATH Serial.printf("sin: %f,%f,%f,(%f)\n",x,res,sin(x),res-sin(x)); #endif @@ -49,6 +55,85 @@ float tan_t(float x) { return res; } +// 16-bit, integer based Bhaskara I's sine approximation: 16*x*(pi - x) / (5*pi^2 - 4*x*(pi - x)) +// input is 16bit unsigned (0-65535), output is 16bit signed (-32767 to +32767) +// optimized integer implementation by @dedehai +int16_t sin16_t(uint16_t theta) { + int scale = 1; + if (theta > 0x7FFF) { + theta = 0xFFFF - theta; + scale = -1; // second half of the sine function is negative (pi - 2*pi) + } + uint32_t precal = theta * (0x7FFF - theta); + uint64_t numerator = (uint64_t)precal * (4 * 0x7FFF); // 64bit required + int32_t denominator = 1342095361 - precal; // 1342095361 is 5 * 0x7FFF^2 / 4 + int16_t result = numerator / denominator; + return result * scale; +} + +int16_t cos16_t(uint16_t theta) { + return sin16_t(theta + 16384); //cos(x) = sin(x+pi/2) +} + +uint8_t sin8_t(uint8_t theta) { + int32_t sin16 = sin16_t((uint16_t)theta * 257); // 255 * 257 = 0xFFFF + sin16 += 0x7FFF; //shift result to range 0-0xFFFF + return sin16 >> 8; +} + +uint8_t cos8_t(uint8_t theta) { + return sin8_t(theta + 64); //cos(x) = sin(x+pi/2) +} + +float sin_approx(float theta) +{ + theta = modd(theta, TWO_PI); // modulo: bring to -2pi to 2pi range + if(theta < 0) theta += M_TWOPI; // 0-2pi range + uint16_t scaled_theta = (uint16_t)(theta * (0xFFFF / M_TWOPI)); + int32_t result = sin16_t(scaled_theta); + float sin = float(result) / 0x7FFF; + return sin; +} + +float cos_approx(float theta) +{ + return sin_approx(theta + M_PI_2); +} + +float tan_approx(float x) { + float c = cos_approx(x); + if (c==0.0f) return 0; + float res = sin_approx(x) / c; + return res; +} + +#define ATAN2_CONST_A 0.1963f +#define ATAN2_CONST_B 0.9817f + +// fast atan2() approximation source: public domain +float atan2_t(float y, float x) { + if (x == 0.0f) return (y > 0.0f) ? M_PI_2 : (y < 0.0f) ? -M_PI_2 : 0.0f; + + float abs_y = (y < 0.0f) ? -y : y + 1e-10f; // make sure y is not zero to prevent division by 0 + float z = abs_y / x; + float atan_approx; + + if (z < 1.0f) { + atan_approx = z / (1.0f + ATAN2_CONST_A * z * z); + if (x < 0.0f) { + return (y >= 0.0f) ? atan_approx + PI : atan_approx - PI; + } + } + else { + z = x / abs_y; + atan_approx = M_PI_2 - z / (1.0f + ATAN2_CONST_A * z * z); + if (y < 0.0f) { + return -atan_approx; + } + } + return atan_approx; +} + //https://stackoverflow.com/questions/3380628 // Absolute error <= 6.7e-5 float acos_t(float x) { From f301296f1e1c9ba9ceeb49aead1f89fc3cd94ba6 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sun, 6 Oct 2024 21:27:58 +0200 Subject: [PATCH 07/90] added rounding to sin8_t thx to @softhack007 --- wled00/wled_math.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/wled_math.cpp b/wled00/wled_math.cpp index 401446a23..080cc9425 100644 --- a/wled00/wled_math.cpp +++ b/wled00/wled_math.cpp @@ -77,8 +77,8 @@ int16_t cos16_t(uint16_t theta) { uint8_t sin8_t(uint8_t theta) { int32_t sin16 = sin16_t((uint16_t)theta * 257); // 255 * 257 = 0xFFFF - sin16 += 0x7FFF; //shift result to range 0-0xFFFF - return sin16 >> 8; + sin16 += 0x7FFF + 128; //shift result to range 0-0xFFFF, +128 for rounding + return min(sin16, int32_t(0xFFFF)) >> 8; // min performs saturation, and prevents overflow } uint8_t cos8_t(uint8_t theta) { From 5e29f2c1b7844492c5ccaf194f524fe810947c3f Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Tue, 15 Oct 2024 20:11:33 +0200 Subject: [PATCH 08/90] fixed atan2_t approximation was incorrect, now doing it right. also removed hypotf() from octopus, saving a little flash. --- wled00/FX.cpp | 6 ++++-- wled00/wled_math.cpp | 39 +++++++++++++++++---------------------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 338dd2df9..5b4513dc7 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -7749,8 +7749,10 @@ 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 * atan2_t((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 + rMap[XY(x, y)].angle = int(40.7436f * atan2_t((y - C_Y), (x - C_X))); // avoid 128*atan2()/PI + int dx = (x - C_X); + int dy = (y - C_Y); + rMap[XY(x, y)].radius = sqrtf(dx * dx + dy * dy) * mapp; //thanks Sutaburosu } } } diff --git a/wled00/wled_math.cpp b/wled00/wled_math.cpp index 080cc9425..1825ab198 100644 --- a/wled00/wled_math.cpp +++ b/wled00/wled_math.cpp @@ -88,8 +88,8 @@ uint8_t cos8_t(uint8_t theta) { float sin_approx(float theta) { theta = modd(theta, TWO_PI); // modulo: bring to -2pi to 2pi range - if(theta < 0) theta += M_TWOPI; // 0-2pi range - uint16_t scaled_theta = (uint16_t)(theta * (0xFFFF / M_TWOPI)); + if(theta < 0) theta += TWO_PI; // 0-2pi range + uint16_t scaled_theta = (uint16_t)(theta * (0xFFFF / TWO_PI)); int32_t result = sin16_t(scaled_theta); float sin = float(result) / 0x7FFF; return sin; @@ -110,28 +110,23 @@ float tan_approx(float x) { #define ATAN2_CONST_A 0.1963f #define ATAN2_CONST_B 0.9817f -// fast atan2() approximation source: public domain +// atan2_t approximation, with the idea from https://gist.github.com/volkansalma/2972237?permalink_comment_id=3872525#gistcomment-3872525 float atan2_t(float y, float x) { - if (x == 0.0f) return (y > 0.0f) ? M_PI_2 : (y < 0.0f) ? -M_PI_2 : 0.0f; - - float abs_y = (y < 0.0f) ? -y : y + 1e-10f; // make sure y is not zero to prevent division by 0 - float z = abs_y / x; - float atan_approx; - - if (z < 1.0f) { - atan_approx = z / (1.0f + ATAN2_CONST_A * z * z); - if (x < 0.0f) { - return (y >= 0.0f) ? atan_approx + PI : atan_approx - PI; - } + float abs_y = fabs(y); + float abs_x = fabs(x); + float r = (abs_x - abs_y) / (abs_y + abs_x + 1e-10f); // avoid division by zero by adding a small nubmer + float angle; + if(x < 0) { + r = -r; + angle = M_PI/2.0f + M_PI/4.f; } - else { - z = x / abs_y; - atan_approx = M_PI_2 - z / (1.0f + ATAN2_CONST_A * z * z); - if (y < 0.0f) { - return -atan_approx; - } - } - return atan_approx; + else + angle = M_PI/2.0f - M_PI/4.f; + + float add = (ATAN2_CONST_A * (r * r) - ATAN2_CONST_B) * r; + angle += add; + angle = y < 0 ? -angle : angle; + return angle; } //https://stackoverflow.com/questions/3380628 From 98a6907976bfa3142545467359e876bd6d0ddc22 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Wed, 16 Oct 2024 19:53:58 +0200 Subject: [PATCH 09/90] cleanup and improvement to sin_appros() -replaced all PI references with M_PI version -there is no need to do the angle-modulo in float, casting it to an integer does the same BUT it has to be cast to an `int` first, see comment. --- wled00/wled_math.cpp | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/wled00/wled_math.cpp b/wled00/wled_math.cpp index 1825ab198..a191968e1 100644 --- a/wled00/wled_math.cpp +++ b/wled00/wled_math.cpp @@ -15,17 +15,17 @@ // Note: cos_t, sin_t and tan_t are very accurate but may be slow // the math.h functions use several kB of flash and are to be avoided if possible // sin16_t / cos16_t are faster and much more accurate than the fastled variants -// sin_approx and cos_approx are float wrappers for sin16_t/cos16_t and have an accuracy of +/-0.0015 compared to sinf() +// sin_approx and cos_approx are float wrappers for sin16_t/cos16_t and have an accuracy better than +/-0.0015 compared to sinf() // sin8_t / cos8_t are fastled replacements and use sin16_t / cos16_t. Slightly slower than fastled version but very accurate float cos_t(float phi) { - float x = modd(phi, TWO_PI); + float x = modd(phi, M_TWOPI); if (x < 0) x = -1 * x; int8_t sign = 1; - if (x > PI) + if (x > M_PI) { - x -= PI; + x -= M_PI; sign = -1; } float xx = x * x; @@ -38,7 +38,7 @@ float cos_t(float phi) } float sin_t(float phi) { - float res = cos_t(HALF_PI - phi); + float res = cos_t(M_PI_2 - phi); #ifdef WLED_DEBUG_MATH Serial.printf("sin: %f,%f,%f,(%f)\n",x,res,sin(x),res-sin(x)); #endif @@ -87,9 +87,7 @@ uint8_t cos8_t(uint8_t theta) { float sin_approx(float theta) { - theta = modd(theta, TWO_PI); // modulo: bring to -2pi to 2pi range - if(theta < 0) theta += TWO_PI; // 0-2pi range - uint16_t scaled_theta = (uint16_t)(theta * (0xFFFF / TWO_PI)); + uint16_t scaled_theta = (int)(theta * (0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) int32_t result = sin16_t(scaled_theta); float sin = float(result) / 0x7FFF; return sin; @@ -118,10 +116,10 @@ float atan2_t(float y, float x) { float angle; if(x < 0) { r = -r; - angle = M_PI/2.0f + M_PI/4.f; + angle = M_PI_2 + M_PI_4; } else - angle = M_PI/2.0f - M_PI/4.f; + angle = M_PI_2 - M_PI_4; float add = (ATAN2_CONST_A * (r * r) - ATAN2_CONST_B) * r; angle += add; @@ -140,10 +138,10 @@ float acos_t(float x) { ret = ret * xabs; ret = ret - 0.2121144f; ret = ret * xabs; - ret = ret + HALF_PI; + ret = ret + M_PI_2; ret = ret * sqrt(1.0f-xabs); ret = ret - 2 * negate * ret; - float res = negate * PI + ret; + float res = negate * M_PI + ret; #ifdef WLED_DEBUG_MATH Serial.printf("acos: %f,%f,%f,(%f)\n",x,res,acos(x),res-acos(x)); #endif @@ -151,7 +149,7 @@ float acos_t(float x) { } float asin_t(float x) { - float res = HALF_PI - acos_t(x); + float res = M_PI_2 - acos_t(x); #ifdef WLED_DEBUG_MATH Serial.printf("asin: %f,%f,%f,(%f)\n",x,res,asin(x),res-asin(x)); #endif @@ -167,7 +165,7 @@ float atan_t(float x) { //For A/B/C, see https://stackoverflow.com/a/42542593 static const double A { 0.0776509570923569 }; static const double B { -0.287434475393028 }; - static const double C { ((HALF_PI/2) - A - B) }; + static const double C { ((M_PI_4) - A - B) }; // polynominal factors for approximation between 1 and 5 static const float C0 { 0.089494f }; static const float C1 { 0.974207f }; @@ -182,7 +180,7 @@ float atan_t(float x) { x = std::abs(x); float res; if (x > 5.0f) { // atan(x) converges to pi/2 - (1/x) for large values - res = HALF_PI - (1.0f/x); + res = M_PI_2 - (1.0f/x); } else if (x > 1.0f) { //1 < x < 5 float xx = x * x; res = (C4*xx*xx)+(C3*xx*x)+(C2*xx)+(C1*x)+C0; From bd68b977d512e28b072cfeb1d3c146e4af221e31 Mon Sep 17 00:00:00 2001 From: maxi4329 Date: Thu, 17 Oct 2024 18:07:01 +0200 Subject: [PATCH 10/90] minor webui enhancements --- wled00/data/index.css | 20 +++++++++++++++++--- wled00/data/index.htm | 2 +- wled00/data/settings_2D.htm | 12 ++++++------ wled00/data/settings_leds.htm | 8 ++++---- wled00/data/settings_pin.htm | 11 ++++++++++- wled00/data/settings_sec.htm | 4 ++-- wled00/data/settings_sync.htm | 10 +++++----- wled00/data/settings_time.htm | 6 +++--- wled00/data/settings_um.htm | 10 +++++----- wled00/data/settings_wifi.htm | 8 ++++---- wled00/data/update.htm | 2 +- 11 files changed, 58 insertions(+), 35 deletions(-) diff --git a/wled00/data/index.css b/wled00/data/index.css index 6f465e407..2ae17ffe5 100644 --- a/wled00/data/index.css +++ b/wled00/data/index.css @@ -97,6 +97,7 @@ button { .labels { margin: 0; padding: 8px 0 2px 0; + font-size: 19px; } #namelabel { @@ -890,12 +891,12 @@ a.btn { line-height: 28px; } -/* Quick color select Black button (has white border) */ -.qcsb { +/* Quick color select Black and White button (has white/black border, depending on the theme) */ +.qcsb, .qcsw { width: 26px; height: 26px; line-height: 26px; - border: 1px solid #fff; + border: 1px solid var(--c-f); } /* Hex color input wrapper div */ @@ -1299,6 +1300,14 @@ TD .checkmark, TD .radiomark { width: 100%; } +#segutil { + margin-bottom: 12px; +} + +#segcont > div:first-child, #fxFind { + margin-top: 4px; +} + /* Simplify segments */ .simplified #segcont .lstI { margin-top: 4px; @@ -1433,6 +1442,11 @@ dialog { position: relative; } +.presin { + width: 100%; + box-sizing: border-box; +} + .btn-s, .btn-n { border: 1px solid var(--c-2); diff --git a/wled00/data/index.htm b/wled00/data/index.htm index e74ea0076..8adec791f 100644 --- a/wled00/data/index.htm +++ b/wled00/data/index.htm @@ -106,7 +106,7 @@
-
+

diff --git a/wled00/data/settings_2D.htm b/wled00/data/settings_2D.htm index a70ca76be..2aec03682 100644 --- a/wled00/data/settings_2D.htm +++ b/wled00/data/settings_2D.htm @@ -54,8 +54,8 @@ Orientation:
Serpentine:
Dimensions (WxH): x
-Offset X: -Y:
(offset from top-left corner in # LEDs) +Offset X: +Y:
(offset from top-left corner in # LEDs) `; p.insertAdjacentHTML("beforeend", b); } @@ -246,7 +246,7 @@ Y:

2D setup

- Strip or panel: + Strip or panel:  Panel dimensions (WxH): x
Horizontal panels: Vertical panels:
- 1st panel:
- Orientation:
@@ -286,7 +286,7 @@ Y:
Gap file:
- Note: Gap file is a .json file containing an array with number of elements equal to the matrix size.
+ Note: Gap file is a .json file containing an array with number of elements equal to the matrix size.
A value of -1 means that pixel at that position is missing, a value of 0 means never paint that pixel, and 1 means regular pixel.

diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 6be5becd1..0a28fda3f 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -747,7 +747,7 @@ Swap:

- LED memory usage: 0 / ? B
+ LED memory usage: 0 / ? B

Advanced

- Palette wrapping: + Palette wrapping:  +
diff --git a/wled00/data/settings_sec.htm b/wled00/data/settings_sec.htm index fa75882c0..6cc03e9eb 100644 --- a/wled00/data/settings_sec.htm +++ b/wled00/data/settings_sec.htm @@ -72,8 +72,8 @@ Contributors, dependencies and special thanks
A huge thank you to everyone who helped me create WLED!

(c) 2016-2024 Christian Schwinne
- Licensed under the EUPL v1.2 license

- Server message: Response error!
+ Licensed under the EUPL v1.2 license

+ Server message:  Response error!
diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm index 34b9fc6cd..754605bf0 100644 --- a/wled00/data/settings_sync.htm +++ b/wled00/data/settings_sync.htm @@ -118,7 +118,7 @@ Receive UDP realtime:
Use main segment only:
Respect LED Maps:

Network DMX input
-Type: +Type: 
Multicast:
Start universe:
-Reboot required. Check out LedFx!
+Reboot required. Check out LedFx!
Skip out-of-sequence packets:
DMX start address:
DMX segment spacing:
E1.31 port priority:
-DMX mode: +DMX mode: 
Group Topic:
Publish on button press:
Retain brightness & color messages:
-Reboot required to apply changes. MQTT info +Reboot required to apply changes. MQTT info

Philips Hue

@@ -209,7 +209,7 @@ Hue status: Disabled in this build This firmware build does not support Serial interface.
-Baud rate: +Baud rate: 

Use 24h format:
- Time zone: + Time zone: 
UTC offset: seconds (max. 18 hours)
Current local time is unknown.
- Latitude:
- Longitude:
+ Latitude: 
+ Longitude: 
(opens new tab, only works in browser)
diff --git a/wled00/data/settings_um.htm b/wled00/data/settings_um.htm index c2f0ffbf2..9c53d560d 100644 --- a/wled00/data/settings_um.htm +++ b/wled00/data/settings_um.htm @@ -283,14 +283,14 @@

Usermod Setup

Global I2C GPIOs (HW)
(change requires reboot!)
- SDA: - SCL: + SDA:  + SCL: 
Global SPI GPIOs (HW)
(only changable on ESP32, change requires reboot!)
- MOSI: - MISO: - SCLK: + MOSI:  + MISO:  + SCLK: 
Reboot after save?
Loading settings...
diff --git a/wled00/data/settings_wifi.htm b/wled00/data/settings_wifi.htm index 30b6600ae..3b840f509 100644 --- a/wled00/data/settings_wifi.htm +++ b/wled00/data/settings_wifi.htm @@ -166,7 +166,7 @@ Static subnet mask:
Hide AP name:
AP password (leave empty for open):

Access Point WiFi channel:
- AP opens: + AP opens: 
- AP IP: Not active
+ AP IP:  Not active

Experimental

Force 802.11g mode (ESP8266 only):
Disable WiFi sleep:
Can help with connectivity issues and Audioreactive sync.
Disabling WiFi sleep increases power consumption.

-
TX power: @@ -205,7 +205,7 @@ Static subnet mask:
Listen for events over ESP-NOW
Keep disabled if not using a remote or wireless sync, increases power consumption.
Paired Remote MAC:
- Last device seen: None
+ Last device seen: None
diff --git a/wled00/data/update.htm b/wled00/data/update.htm index b68645a52..791a76f6b 100644 --- a/wled00/data/update.htm +++ b/wled00/data/update.htm @@ -16,7 +16,7 @@

WLED Software Update

- Installed version: ##VERSION##
+ Installed version: ##VERSION##
Download the latest binary: 
From caa997fff1750bd08e7d815674c3ff7728a14029 Mon Sep 17 00:00:00 2001 From: maxi4329 Date: Fri, 18 Oct 2024 18:43:41 +0200 Subject: [PATCH 11/90] removed onkeydown tried to find a replacement for the nbsp --- package-lock.json | 2 +- wled00/data/settings_2D.htm | 8 ++++---- wled00/data/settings_leds.htm | 8 ++++---- wled00/data/settings_pin.htm | 11 +---------- wled00/data/settings_sec.htm | 4 ++-- wled00/data/settings_sync.htm | 10 +++++----- wled00/data/settings_time.htm | 6 +++--- wled00/data/settings_um.htm | 10 +++++----- wled00/data/settings_wifi.htm | 8 ++++---- wled00/data/style.css | 3 +++ wled00/data/update.htm | 2 +- 11 files changed, 33 insertions(+), 39 deletions(-) diff --git a/package-lock.json b/package-lock.json index 85ee1df0f..e85857017 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "clean-css": "^5.3.3", "html-minifier-terser": "^7.2.0", "inliner": "^1.13.1", - "nodemon": "^3.0.2" + "nodemon": "^3.1.7" } }, "node_modules/@jridgewell/gen-mapping": { diff --git a/wled00/data/settings_2D.htm b/wled00/data/settings_2D.htm index 2aec03682..e372b3e21 100644 --- a/wled00/data/settings_2D.htm +++ b/wled00/data/settings_2D.htm @@ -246,7 +246,7 @@ Y: Back

2D setup

- Strip or panel:  + Strip or panel: x
Horizontal panels: Vertical panels:
- 1st panel: 
- Orientation: 
@@ -286,7 +286,7 @@ Y:
Gap file:
- Note: Gap file is a .json file containing an array with number of elements equal to the matrix size.
+ Note: Gap file is a .json file containing an array with number of elements equal to the matrix size.
A value of -1 means that pixel at that position is missing, a value of 0 means never paint that pixel, and 1 means regular pixel.

diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 0a28fda3f..6be5becd1 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -747,7 +747,7 @@ Swap:

- LED memory usage: 0 / ? B
+ LED memory usage: 0 / ? B

Advanced

- Palette wrapping:  + Palette wrapping: +
diff --git a/wled00/data/settings_sec.htm b/wled00/data/settings_sec.htm index 6cc03e9eb..fa75882c0 100644 --- a/wled00/data/settings_sec.htm +++ b/wled00/data/settings_sec.htm @@ -72,8 +72,8 @@ Contributors, dependencies and special thanks
A huge thank you to everyone who helped me create WLED!

(c) 2016-2024 Christian Schwinne
- Licensed under the EUPL v1.2 license

- Server message:  Response error!
+ Licensed under the EUPL v1.2 license

+ Server message: Response error!
diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm index 754605bf0..34b9fc6cd 100644 --- a/wled00/data/settings_sync.htm +++ b/wled00/data/settings_sync.htm @@ -118,7 +118,7 @@ Receive UDP realtime:
Use main segment only:
Respect LED Maps:

Network DMX input
-Type:  +Type:
Multicast:
Start universe:
-Reboot required. Check out LedFx!
+Reboot required. Check out LedFx!
Skip out-of-sequence packets:
DMX start address:
DMX segment spacing:
E1.31 port priority:
-DMX mode:  +DMX mode:
Group Topic:
Publish on button press:
Retain brightness & color messages:
-Reboot required to apply changes. MQTT info +Reboot required to apply changes. MQTT info

Philips Hue

@@ -209,7 +209,7 @@ Hue status: Disabled in this build This firmware build does not support Serial interface.
-Baud rate:  +Baud rate:

Use 24h format:
- Time zone:  + Time zone:
UTC offset: seconds (max. 18 hours)
Current local time is unknown.
- Latitude: 
- Longitude: 
+ Latitude:
+ Longitude:
(opens new tab, only works in browser)
diff --git a/wled00/data/settings_um.htm b/wled00/data/settings_um.htm index 9c53d560d..c2f0ffbf2 100644 --- a/wled00/data/settings_um.htm +++ b/wled00/data/settings_um.htm @@ -283,14 +283,14 @@

Usermod Setup

Global I2C GPIOs (HW)
(change requires reboot!)
- SDA:  - SCL:  + SDA: + SCL:
Global SPI GPIOs (HW)
(only changable on ESP32, change requires reboot!)
- MOSI:  - MISO:  - SCLK:  + MOSI: + MISO: + SCLK:
Reboot after save?
Loading settings...
diff --git a/wled00/data/settings_wifi.htm b/wled00/data/settings_wifi.htm index 3b840f509..30b6600ae 100644 --- a/wled00/data/settings_wifi.htm +++ b/wled00/data/settings_wifi.htm @@ -166,7 +166,7 @@ Static subnet mask:
Hide AP name:
AP password (leave empty for open):

Access Point WiFi channel:
- AP opens:  + AP opens:
- AP IP:  Not active
+ AP IP: Not active

Experimental

Force 802.11g mode (ESP8266 only):
Disable WiFi sleep:
Can help with connectivity issues and Audioreactive sync.
Disabling WiFi sleep increases power consumption.

-
TX power:  @@ -205,7 +205,7 @@ Static subnet mask:
Listen for events over ESP-NOW
Keep disabled if not using a remote or wireless sync, increases power consumption.
Paired Remote MAC:
- Last device seen: None
+ Last device seen: None
diff --git a/wled00/data/style.css b/wled00/data/style.css index b6cb0f9e6..42e49d304 100644 --- a/wled00/data/style.css +++ b/wled00/data/style.css @@ -44,6 +44,9 @@ button.sml { min-width: 40px; margin: 0 0 0 10px; } +span:before, b:before, b:after, i:after{ + content: "\00A0"; +} #scan { margin-top: -10px; } diff --git a/wled00/data/update.htm b/wled00/data/update.htm index 791a76f6b..b68645a52 100644 --- a/wled00/data/update.htm +++ b/wled00/data/update.htm @@ -16,7 +16,7 @@

WLED Software Update

- Installed version: ##VERSION##
+ Installed version: ##VERSION##
Download the latest binary: 
From 4fa8a3898a8771c6680bf84eaa5ab5101dd82b5b Mon Sep 17 00:00:00 2001 From: 1Prototype1 Date: Sat, 19 Oct 2024 00:30:24 +0530 Subject: [PATCH 12/90] Added Distribute for cpal Added a button to distribute the color markers in palette equally --- wled00/data/cpal/cpal.htm | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/wled00/data/cpal/cpal.htm b/wled00/data/cpal/cpal.htm index b58c0987a..8fa715bc8 100644 --- a/wled00/data/cpal/cpal.htm +++ b/wled00/data/cpal/cpal.htm @@ -167,9 +167,10 @@
-
- Currently in use custom palettes -
+
+
+ Currently in use custom palettes +
@@ -187,7 +188,7 @@ Available static palettes
- + @@ -204,6 +205,13 @@ var paletteName = []; // Holds the names of the palettes after load. var svgSave = '' var svgEdit = '' + var svgDist = '' + var svgTrash = '' + + const distDiv = gId("distDiv"); + distDiv.addEventListener('click', distribute); + distDiv.setAttribute('title', 'Distribute colors equally'); + distDiv.innerHTML = svgDist; function recOf() { rect = gradientBox.getBoundingClientRect(); @@ -433,7 +441,7 @@ renderY = e.srcElement.getBoundingClientRect().y + 13; trash.id = "trash"; - trash.innerHTML = ''; + trash.innerHTML = svgTrash; trash.style.position = "absolute"; trash.style.left = (renderX) + "px"; trash.style.top = (renderY) + "px"; @@ -712,9 +720,27 @@ } } + function distribute() { + let colorMarkers = [...gradientBox.querySelectorAll('.color-marker')]; + colorMarkers.sort((a, b) => a.getAttribute('data-truepos') - b.getAttribute('data-truepos')); + colorMarkers = colorMarkers.slice(1, -1); + const spacing = Math.round(256 / (colorMarkers.length + 1)); + + colorMarkers.forEach((e, i) => { + const markerId = e.id.match(/\d+/)[0]; + const trueCol = e.getAttribute("data-truecol"); + gradientBox.removeChild(e); + gradientBox.removeChild(gId(`colorPicker${markerId}`)); + gradientBox.removeChild(gId(`colorPickerMarker${markerId}`)); + gradientBox.removeChild(gId(`deleteMarker${markerId}`)); + addC(spacing * (i + 1), trueCol); + }); + } + function rgbToHex(r, g, b) { const hex = ((r << 16) | (g << 8) | b).toString(16); return "#" + "0".repeat(6 - hex.length) + hex; } + From dcfdca63515f2d3f80674d05c6ee7186f9458354 Mon Sep 17 00:00:00 2001 From: ingDIY <10012263+ingDIY@users.noreply.github.com> Date: Fri, 25 Oct 2024 12:14:37 +0200 Subject: [PATCH 13/90] cleaned up old references to USE_ALT_DISPlAY that aren't used anymore in the code/source files; fixed readme.md documents and updated instructions; removed referencies to old usermods; fixed invalid filenames; removed referencies to old usermods; checked cycle options; splitted and fixed platformio_override.sample.ini; --- platformio_override.sample.ini | 2 -- .../platformio_override.sample.ini} | 11 +++---- .../readme.md | 30 +++++-------------- .../platformio_override.sample.ini | 14 +++++++++ .../readme.md | 22 ++++---------- 5 files changed, 32 insertions(+), 47 deletions(-) rename usermods/{usermod_v2_rotary_encoder_ui_ALT/platformio–override.sample.ini => usermod_v2_four_line_display_ALT/platformio_override.sample.ini} (54%) create mode 100644 usermods/usermod_v2_rotary_encoder_ui_ALT/platformio_override.sample.ini diff --git a/platformio_override.sample.ini b/platformio_override.sample.ini index 8e5fdf003..c445cd32e 100644 --- a/platformio_override.sample.ini +++ b/platformio_override.sample.ini @@ -111,7 +111,6 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} ; ; Use 4 Line Display usermod with SPI display ; -D USERMOD_FOUR_LINE_DISPLAY -; -D USE_ALT_DISPlAY # mandatory ; -DFLD_SPI_DEFAULT ; -D FLD_TYPE=SSD1306_SPI64 ; -D FLD_PIN_CLOCKSPI=14 @@ -377,7 +376,6 @@ build_flags = ${common.build_flags} ${esp32.build_flags} -D USERMOD_DALLASTEMPERATURE -D USERMOD_FOUR_LINE_DISPLAY -D TEMPERATURE_PIN=23 - -D USE_ALT_DISPlAY ; new versions of USERMOD_FOUR_LINE_DISPLAY and USERMOD_ROTARY_ENCODER_UI -D USERMOD_AUDIOREACTIVE lib_deps = ${esp32.lib_deps} OneWire@~2.3.5 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 54% 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..9010648b3 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 + U8g2 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_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 From 798c398f23f9ea2c6e826acafa5a4a81ce35945a Mon Sep 17 00:00:00 2001 From: maxi4329 Date: Sat, 26 Oct 2024 20:33:38 +0200 Subject: [PATCH 14/90] specified required nodejs ver --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index d76d87687..0c016329b 100644 --- a/package.json +++ b/package.json @@ -27,5 +27,8 @@ "html-minifier-terser": "^7.2.0", "inliner": "^1.13.1", "nodemon": "^3.1.7" + }, + "engines": { + "node": ">=20.0.0" } } From 7c6bc5c4211c5c45342b2b833bf3d04991ee76ea Mon Sep 17 00:00:00 2001 From: maxi4329 Date: Sat, 26 Oct 2024 21:07:17 +0200 Subject: [PATCH 15/90] indened formating --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0c016329b..35fda6002 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,6 @@ "nodemon": "^3.1.7" }, "engines": { - "node": ">=20.0.0" + "node": ">=21.0.0" } } From d05c358fd23d86697ec343b9c46c231d30346fcb Mon Sep 17 00:00:00 2001 From: maxi4329 Date: Sun, 27 Oct 2024 11:13:56 +0100 Subject: [PATCH 16/90] version changed to 20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 35fda6002..0c016329b 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,6 @@ "nodemon": "^3.1.7" }, "engines": { - "node": ">=21.0.0" + "node": ">=20.0.0" } } From fa053b7e60effbbb76dc49822003ea5acb4b4dcf Mon Sep 17 00:00:00 2001 From: ingDIY <10012263+ingDIY@users.noreply.github.com> Date: Tue, 29 Oct 2024 01:14:02 +0100 Subject: [PATCH 17/90] Update platformio_override.sample.ini fixed back U8g2 version --- .../platformio_override.sample.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usermods/usermod_v2_four_line_display_ALT/platformio_override.sample.ini b/usermods/usermod_v2_four_line_display_ALT/platformio_override.sample.ini index 9010648b3..e59637453 100644 --- a/usermods/usermod_v2_four_line_display_ALT/platformio_override.sample.ini +++ b/usermods/usermod_v2_four_line_display_ALT/platformio_override.sample.ini @@ -14,5 +14,5 @@ build_flags = lib_deps = ${esp32.lib_deps} - U8g2 + U8g2@~2.34.4 Wire From 451cd4c74aff2faff9ab11f746f9e454ab10bd2e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 1 Nov 2024 23:19:38 +0100 Subject: [PATCH 18/90] Improved framerate control in strip.show(), strip.service() * separate fps calculation (strip.show) from framerate control (strio.service) * improved condition for early exit in strip.show * make MIN_SHOW_DELAY depend on target fps * strip.show consideres complete time for effect calculation + show; old code wrongly used the time between completion of last show and start of next effect drawing, causing unexpected slowdown * add "unlimited FPS mode" for testing * increase warning limits for "slow strip" and "slow effects" --- wled00/FX.h | 22 +++++++++++++++++----- wled00/FX_fcn.cpp | 37 +++++++++++++++++++++++++++---------- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index ad39a7c06..acdb62c81 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -44,8 +44,20 @@ /* Not used in all effects yet */ #define WLED_FPS 42 -#define FRAMETIME_FIXED (1000/WLED_FPS) #define FRAMETIME strip.getFrameTime() +#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) // all ESP32 except -C3(very slow, untested) + #define FRAMETIME_FIXED (strip.getFrameTime() < 10 ? 12 : 24) // allow faster FRAMETIME_FIXED when target FPS >= 100 + #define MIN_SHOW_DELAY (max(2, (_frametime*5)/8)) // supports higher framerates and better animation control -- 5/8 = 62% + // used to initialize for strip attributes: + #define WLED_FPS_SLOW 42 + #define FRAMETIME_FIXED_SLOW (24) // 1000/42 = 24ms +#else + #define FRAMETIME_FIXED (1000/WLED_FPS) + #define MIN_SHOW_DELAY (_frametime < 16 ? 8 : 15) // legacy MIN_SHOW_DELAY - creates more idle loops, but reduces framerates + #define WLED_FPS_SLOW WLED_FPS + #define FRAMETIME_FIXED_SLOW FRAMETIME_FIXED +#endif +#define FPS_UNLIMITED 119 /* each segment uses 82 bytes of SRAM memory, so if you're application fails because of insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ @@ -68,8 +80,6 @@ assuming each segment uses the same amount of data. 256 for ESP8266, 640 for ESP32. */ #define FAIR_DATA_PER_SEG (MAX_SEGMENT_DATA / strip.getMaxSegments()) -#define MIN_SHOW_DELAY (_frametime < 16 ? 8 : 15) - #define NUM_COLORS 3 /* number of colors per segment */ #define SEGMENT strip._segments[strip.getCurrSegmentId()] #define SEGENV strip._segments[strip.getCurrSegmentId()] @@ -727,8 +737,8 @@ class WS2812FX { // 96 bytes _length(DEFAULT_LED_COUNT), _brightness(DEFAULT_BRIGHTNESS), _transitionDur(750), - _targetFps(WLED_FPS), - _frametime(FRAMETIME_FIXED), + _targetFps(WLED_FPS_SLOW), + _frametime(FRAMETIME_FIXED_SLOW), _cumulativeFps(2), _isServicing(false), _isOffRefreshRequired(false), @@ -739,6 +749,7 @@ class WS2812FX { // 96 bytes customMappingTable(nullptr), customMappingSize(0), _lastShow(0), + _lastServiceShow(0), _segment_index(0), _mainSegment(0) { @@ -949,6 +960,7 @@ class WS2812FX { // 96 bytes uint16_t customMappingSize; unsigned long _lastShow; + unsigned long _lastServiceShow; uint8_t _segment_index; uint8_t _mainSegment; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 949b6a932..5856ad786 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1309,11 +1309,23 @@ void WS2812FX::finalizeInit() { void WS2812FX::service() { unsigned long nowUp = millis(); // Be aware, millis() rolls over every 49 days now = nowUp + timebase; - if (nowUp - _lastShow < MIN_SHOW_DELAY || _suspend) return; + if (_suspend) return; + unsigned long elapsed = nowUp - _lastServiceShow; + + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) + if (elapsed < 2) return; // keep wifi alive + if ( !_triggered && (_targetFps < FPS_UNLIMITED) && (_targetFps > 0)) { + if (elapsed < MIN_SHOW_DELAY) return; // WLEDMM too early for service + } + #else // legacy + if (nowUp - _lastShow < MIN_SHOW_DELAY) return; + #endif + bool doShow = false; _isServicing = true; _segment_index = 0; + unsigned speedLimit = (_targetFps < FPS_UNLIMITED) ? (0.85f * FRAMETIME) : 1; // lower limit for effect frametime for (segment &seg : _segments) { if (_suspend) return; // immediately stop processing segments if suspend requested during service() @@ -1326,10 +1338,10 @@ void WS2812FX::service() { if (!seg.isActive()) continue; // last condition ensures all solid segments are updated at the same time - if (nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC)) + 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) @@ -1349,7 +1361,8 @@ 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 + if (frameDelay < speedLimit) frameDelay = FRAMETIME; // limit effects that want to go faster than target FPS #ifndef WLED_DISABLE_MODE_BLEND if (modeBlending && seg.mode != tmpMode) { Segment::tmpsegd_t _tmpSegData; @@ -1358,16 +1371,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++; } @@ -1376,15 +1389,16 @@ void WS2812FX::service() { _triggered = false; #ifdef WLED_DEBUG - if (millis() - nowUp > _frametime) DEBUG_PRINTF_P(PSTR("Slow effects %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime); + if (millis() - nowUp > _frametime*2) DEBUG_PRINTF_P(PSTR("Slow effects %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime); #endif if (doShow) { yield(); Segment::handleRandomPalette(); // slowly transition random palette; move it into for loop when each segment has individual random palette show(); + _lastServiceShow = nowUp; // correct timestamp, for better FPS control } #ifdef WLED_DEBUG - if (millis() - nowUp > _frametime) DEBUG_PRINTF_P(PSTR("Slow strip %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime); + if (millis() - nowUp > _frametime*2) DEBUG_PRINTF_P(PSTR("Slow strip %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime); #endif } @@ -1404,18 +1418,19 @@ void WS2812FX::show() { // avoid race condition, capture _callback value show_callback callback = _callback; if (callback) callback(); + unsigned long showNow = millis(); // some buses send asynchronously and this method will return before // all of the data has been sent. // See https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#neoesp32rmt-methods BusManager::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; + _lastServiceShow = showNow; } /** @@ -1438,6 +1453,8 @@ uint16_t WS2812FX::getFps() const { void WS2812FX::setTargetFps(uint8_t fps) { if (fps > 0 && fps <= 120) _targetFps = fps; _frametime = 1000 / _targetFps; + if (_frametime < 1) _frametime = 1; // better safe than sorry + if (fps >= FPS_UNLIMITED) _frametime = 3; // unlimited mode } void WS2812FX::setMode(uint8_t segid, uint8_t m) { From 50934e6840995154109ab7d532dbb61af0377f90 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 2 Nov 2024 18:16:51 +0100 Subject: [PATCH 19/90] adressing some review comments * keep FRAMETIME_FIXED as a fixed value * remove WLED_FPS_SLOW and FRAMETIME_FIXED_SLOW * explicit test "(_targetFps != FPS_UNLIMITED)" for debug messages * don't modify _lastServiceShow in show() * test for "fps == FPS_UNLIMITED" explicitly, so we could pick a different magic number later --- wled00/FX.h | 13 ++++--------- wled00/FX_fcn.cpp | 12 +++++------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index acdb62c81..1f0df9da3 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -44,20 +44,15 @@ /* Not used in all effects yet */ #define WLED_FPS 42 +#define FRAMETIME_FIXED (1000/WLED_FPS) #define FRAMETIME strip.getFrameTime() #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) // all ESP32 except -C3(very slow, untested) - #define FRAMETIME_FIXED (strip.getFrameTime() < 10 ? 12 : 24) // allow faster FRAMETIME_FIXED when target FPS >= 100 #define MIN_SHOW_DELAY (max(2, (_frametime*5)/8)) // supports higher framerates and better animation control -- 5/8 = 62% // used to initialize for strip attributes: - #define WLED_FPS_SLOW 42 - #define FRAMETIME_FIXED_SLOW (24) // 1000/42 = 24ms #else - #define FRAMETIME_FIXED (1000/WLED_FPS) #define MIN_SHOW_DELAY (_frametime < 16 ? 8 : 15) // legacy MIN_SHOW_DELAY - creates more idle loops, but reduces framerates - #define WLED_FPS_SLOW WLED_FPS - #define FRAMETIME_FIXED_SLOW FRAMETIME_FIXED #endif -#define FPS_UNLIMITED 119 +#define FPS_UNLIMITED 120 /* each segment uses 82 bytes of SRAM memory, so if you're application fails because of insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ @@ -737,8 +732,8 @@ class WS2812FX { // 96 bytes _length(DEFAULT_LED_COUNT), _brightness(DEFAULT_BRIGHTNESS), _transitionDur(750), - _targetFps(WLED_FPS_SLOW), - _frametime(FRAMETIME_FIXED_SLOW), + _targetFps(WLED_FPS), + _frametime(FRAMETIME_FIXED), _cumulativeFps(2), _isServicing(false), _isOffRefreshRequired(false), diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 5856ad786..3972dad2c 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1314,7 +1314,7 @@ void WS2812FX::service() { #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) if (elapsed < 2) return; // keep wifi alive - if ( !_triggered && (_targetFps < FPS_UNLIMITED) && (_targetFps > 0)) { + if ( !_triggered && (_targetFps != FPS_UNLIMITED) && (_targetFps > 0)) { if (elapsed < MIN_SHOW_DELAY) return; // WLEDMM too early for service } #else // legacy @@ -1325,7 +1325,7 @@ void WS2812FX::service() { _isServicing = true; _segment_index = 0; - unsigned speedLimit = (_targetFps < FPS_UNLIMITED) ? (0.85f * FRAMETIME) : 1; // lower limit for effect frametime + unsigned speedLimit = (_targetFps != FPS_UNLIMITED) ? (0.85f * FRAMETIME) : 1; // lower limit for effect frametime for (segment &seg : _segments) { if (_suspend) return; // immediately stop processing segments if suspend requested during service() @@ -1389,7 +1389,7 @@ void WS2812FX::service() { _triggered = false; #ifdef WLED_DEBUG - if (millis() - nowUp > _frametime*2) DEBUG_PRINTF_P(PSTR("Slow effects %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime); + if ((_targetFps != FPS_UNLIMITED) && (millis() - nowUp > _frametime)) DEBUG_PRINTF_P(PSTR("Slow effects %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime); #endif if (doShow) { yield(); @@ -1398,7 +1398,7 @@ void WS2812FX::service() { _lastServiceShow = nowUp; // correct timestamp, for better FPS control } #ifdef WLED_DEBUG - if (millis() - nowUp > _frametime*2) DEBUG_PRINTF_P(PSTR("Slow strip %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime); + if ((_targetFps != FPS_UNLIMITED) && (millis() - nowUp > _frametime)) DEBUG_PRINTF_P(PSTR("Slow strip %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime); #endif } @@ -1430,7 +1430,6 @@ void WS2812FX::show() { if (diff > 0) fpsCurr = 1000 / diff; _cumulativeFps = (3 * _cumulativeFps + fpsCurr +2) >> 2; // "+2" for proper rounding (2/4 = 0.5) _lastShow = showNow; - _lastServiceShow = showNow; } /** @@ -1453,8 +1452,7 @@ uint16_t WS2812FX::getFps() const { void WS2812FX::setTargetFps(uint8_t fps) { if (fps > 0 && fps <= 120) _targetFps = fps; _frametime = 1000 / _targetFps; - if (_frametime < 1) _frametime = 1; // better safe than sorry - if (fps >= FPS_UNLIMITED) _frametime = 3; // unlimited mode + if (fps == FPS_UNLIMITED) _frametime = 3; // unlimited mode } void WS2812FX::setMode(uint8_t segid, uint8_t m) { From cf1630a94a3de7b59e2dd21562a607627c9fa2d2 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 4 Nov 2024 19:49:43 +0100 Subject: [PATCH 20/90] 0 FPS = unlimited --- wled00/FX.h | 2 +- wled00/FX_fcn.cpp | 8 ++++---- wled00/data/settings_leds.htm | 8 +++++++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 1f0df9da3..5c80686d6 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -52,7 +52,7 @@ #else #define MIN_SHOW_DELAY (_frametime < 16 ? 8 : 15) // legacy MIN_SHOW_DELAY - creates more idle loops, but reduces framerates #endif -#define FPS_UNLIMITED 120 +#define FPS_UNLIMITED 0 /* each segment uses 82 bytes of SRAM memory, so if you're application fails because of insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 3972dad2c..30882c4e7 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1314,7 +1314,7 @@ void WS2812FX::service() { #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) if (elapsed < 2) return; // keep wifi alive - if ( !_triggered && (_targetFps != FPS_UNLIMITED) && (_targetFps > 0)) { + if ( !_triggered && (_targetFps != FPS_UNLIMITED)) { if (elapsed < MIN_SHOW_DELAY) return; // WLEDMM too early for service } #else // legacy @@ -1450,9 +1450,9 @@ uint16_t WS2812FX::getFps() const { } void WS2812FX::setTargetFps(uint8_t fps) { - if (fps > 0 && fps <= 120) _targetFps = fps; - _frametime = 1000 / _targetFps; - if (fps == FPS_UNLIMITED) _frametime = 3; // unlimited mode + if (fps <= 120) _targetFps = fps; + if (_targetFps > 0) _frametime = 1000 / _targetFps; + else _frametime = 3; // unlimited mode } void WS2812FX::setMode(uint8_t segid, uint8_t m) { diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 6be5becd1..35bbbd312 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -380,6 +380,10 @@ gId('psu').innerHTML = s; gId('psu2').innerHTML = s2; gId("json").style.display = d.Sf.IT.value==8 ? "" : "none"; + + // show/hide unlimited FPS message + gId('fpsNone').style.display = (d.Sf.FR.value == 0) ? 'block':'none'; + gId('fpsHelp').style.display = (d.Sf.FR.value == 0)? 'none':'block'; } function lastEnd(i) { if (i-- < 1) return 0; @@ -870,7 +874,9 @@ Swap:
- Target refresh rate: FPS + Target refresh rate: FPS +
use 0 for unlimited
+
Config template:

From 029293a08621df71ed0546ed5bf3c0e4cc9d49c7 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 4 Nov 2024 20:11:10 +0100 Subject: [PATCH 21/90] simplify sheduler logic * _frametime ensures that effects are not serviced too often * MIN_SHOW_DELAY is the minimum allowed FRAMETIME that can be requested by effects --- wled00/FX.h | 3 +-- wled00/FX_fcn.cpp | 13 ++++--------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 5c80686d6..d749d7796 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -47,8 +47,7 @@ #define FRAMETIME_FIXED (1000/WLED_FPS) #define FRAMETIME strip.getFrameTime() #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) // all ESP32 except -C3(very slow, untested) - #define MIN_SHOW_DELAY (max(2, (_frametime*5)/8)) // supports higher framerates and better animation control -- 5/8 = 62% - // used to initialize for strip attributes: + #define MIN_SHOW_DELAY 3 // supports higher framerates and better animation control #else #define MIN_SHOW_DELAY (_frametime < 16 ? 8 : 15) // legacy MIN_SHOW_DELAY - creates more idle loops, but reduces framerates #endif diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 30882c4e7..6bc61d10d 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1312,20 +1312,15 @@ void WS2812FX::service() { if (_suspend) return; unsigned long elapsed = nowUp - _lastServiceShow; - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) - if (elapsed < 2) return; // keep wifi alive - if ( !_triggered && (_targetFps != FPS_UNLIMITED)) { - if (elapsed < MIN_SHOW_DELAY) return; // WLEDMM too early for service + if (elapsed < 2) return; // keep wifi alive - no matter if triggered or unlimited + if ( !_triggered && (_targetFps != FPS_UNLIMITED)) { // unlimited mode = no frametime + if (elapsed < _frametime) return; // too early for service } - #else // legacy - if (nowUp - _lastShow < MIN_SHOW_DELAY) return; - #endif bool doShow = false; _isServicing = true; _segment_index = 0; - unsigned speedLimit = (_targetFps != FPS_UNLIMITED) ? (0.85f * FRAMETIME) : 1; // lower limit for effect frametime for (segment &seg : _segments) { if (_suspend) return; // immediately stop processing segments if suspend requested during service() @@ -1362,7 +1357,6 @@ 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 frameDelay = (*_mode[seg.mode])(); // run new/current mode - if (frameDelay < speedLimit) frameDelay = FRAMETIME; // limit effects that want to go faster than target FPS #ifndef WLED_DISABLE_MODE_BLEND if (modeBlending && seg.mode != tmpMode) { Segment::tmpsegd_t _tmpSegData; @@ -1375,6 +1369,7 @@ void WS2812FX::service() { Segment::modeBlend(false); // unset semaphore } #endif + frameDelay = max(frameDelay, unsigned(MIN_SHOW_DELAY)); // limit effects that want to go faster than target FPS seg.call++; if (seg.isInTransition() && frameDelay > FRAMETIME) frameDelay = FRAMETIME; // force faster updates during transition BusManager::setSegmentCCT(oldCCT); // restore old CCT for ABL adjustments From ab7b2d729e68099b140473079dc22ea9b186d7b5 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 5 Nov 2024 12:24:20 +0100 Subject: [PATCH 22/90] use class="warn" for unlimited mode message --- wled00/data/settings_leds.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 35bbbd312..caeaacea9 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -876,7 +876,7 @@ Swap:
Target refresh rate: FPS
use 0 for unlimited
- +
Config template:

From 1e761c31bdd53850aca805c9400ef24b10f3afda Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 6 Nov 2024 22:09:33 +0100 Subject: [PATCH 23/90] simpler hight FPS warning * removed "use 0 for unlimited" * added "high FPS mode is experimental" warning * added "backup first!" warning * added anchor #backup to sec page --- wled00/data/settings_leds.htm | 10 ++++++---- wled00/data/settings_sec.htm | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index caeaacea9..55f8122e8 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -381,9 +381,10 @@ gId('psu2').innerHTML = s2; gId("json").style.display = d.Sf.IT.value==8 ? "" : "none"; - // show/hide unlimited FPS message + // show/hide FPS warning messages gId('fpsNone').style.display = (d.Sf.FR.value == 0) ? 'block':'none'; - gId('fpsHelp').style.display = (d.Sf.FR.value == 0)? 'none':'block'; + gId('fpsWarn').style.display = (d.Sf.FR.value == 0) || (d.Sf.FR.value >= 80) ? 'block':'none'; + gId('fpsHigh').style.display = (d.Sf.FR.value >= 80) ? 'block':'none'; } function lastEnd(i) { if (i-- < 1) return 0; @@ -875,8 +876,9 @@ Swap:
Target refresh rate: FPS -
use 0 for unlimited
- + + +
Config template:

diff --git a/wled00/data/settings_sec.htm b/wled00/data/settings_sec.htm index fa75882c0..5181858d5 100644 --- a/wled00/data/settings_sec.htm +++ b/wled00/data/settings_sec.htm @@ -57,7 +57,7 @@

Software Update


Enable ArduinoOTA: -
+

Backup & Restore

⚠ Restoring presets/configuration will OVERWRITE your current presets/configuration.
Incorrect upload or configuration may require a factory reset or re-flashing of your ESP.
From 6ff5c88ebf0525f8101c49f19702c0ee0cec0e65 Mon Sep 17 00:00:00 2001 From: netmindz Date: Thu, 7 Nov 2024 08:17:08 +0000 Subject: [PATCH 24/90] List ESP32 first --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 11c1733f8..595b9ee0b 100644 --- a/readme.md +++ b/readme.md @@ -12,7 +12,7 @@ # Welcome to my project WLED! ✨ -A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812) LEDs or also SPI based chipsets like the WS2801 and APA102! +A fast and feature-rich implementation of an ESP32 and ESP8266 webserver to control NeoPixel (WS2812B, WS2811, SK6812) LEDs or also SPI based chipsets like the WS2801 and APA102! ## ⚙️ Features - WS2812FX library with more than 100 special effects From 0404ec988137acca997e620384cf446b19dce350 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 7 Nov 2024 23:15:39 +0100 Subject: [PATCH 25/90] changes in response to feedback from @willmmiles * MIN_SHOW_DELAY -> MIN_FRAME_DELAY * allow up to 250 for target FPS * minor cleanup * added specific MIN_FRAME_DELAY for -S2 --- wled00/FX.h | 10 ++++++---- wled00/FX_fcn.cpp | 11 +++++------ wled00/data/settings_leds.htm | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index d749d7796..56a0c9bd0 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -46,10 +46,12 @@ #define WLED_FPS 42 #define FRAMETIME_FIXED (1000/WLED_FPS) #define FRAMETIME strip.getFrameTime() -#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) // all ESP32 except -C3(very slow, untested) - #define MIN_SHOW_DELAY 3 // supports higher framerates and better animation control +#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) + #define MIN_FRAME_DELAY 2 // minimum wait between repaints, to keep other functions like WiFi alive +#elif defined(CONFIG_IDF_TARGET_ESP32S2) + #define MIN_FRAME_DELAY 4 // S2 is slower than normal esp32, and only has one core #else - #define MIN_SHOW_DELAY (_frametime < 16 ? 8 : 15) // legacy MIN_SHOW_DELAY - creates more idle loops, but reduces framerates + #define MIN_FRAME_DELAY 8 // 8266 legacy MIN_SHOW_DELAY #endif #define FPS_UNLIMITED 0 @@ -842,7 +844,7 @@ class WS2812FX { // 96 bytes getMappedPixelIndex(uint16_t index) const; 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 getMinShowDelay() const { return MIN_FRAME_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) inline uint16_t getTransition() const { return _transitionDur; } // returns currently set transition time (in ms) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 6bc61d10d..f4b46dade 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1312,7 +1312,7 @@ void WS2812FX::service() { if (_suspend) return; unsigned long elapsed = nowUp - _lastServiceShow; - if (elapsed < 2) return; // keep wifi alive - no matter if triggered or unlimited + if (elapsed <= MIN_FRAME_DELAY) return; // keep wifi alive - no matter if triggered or unlimited if ( !_triggered && (_targetFps != FPS_UNLIMITED)) { // unlimited mode = no frametime if (elapsed < _frametime) return; // too early for service } @@ -1369,7 +1369,6 @@ void WS2812FX::service() { Segment::modeBlend(false); // unset semaphore } #endif - frameDelay = max(frameDelay, unsigned(MIN_SHOW_DELAY)); // limit effects that want to go faster than target FPS seg.call++; if (seg.isInTransition() && frameDelay > FRAMETIME) frameDelay = FRAMETIME; // force faster updates during transition BusManager::setSegmentCCT(oldCCT); // restore old CCT for ABL adjustments @@ -1390,7 +1389,7 @@ void WS2812FX::service() { yield(); Segment::handleRandomPalette(); // slowly transition random palette; move it into for loop when each segment has individual random palette show(); - _lastServiceShow = nowUp; // correct timestamp, for better FPS control + _lastServiceShow = nowUp; // update timestamp, for precise FPS control } #ifdef WLED_DEBUG if ((_targetFps != FPS_UNLIMITED) && (millis() - nowUp > _frametime)) DEBUG_PRINTF_P(PSTR("Slow strip %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime); @@ -1445,9 +1444,9 @@ uint16_t WS2812FX::getFps() const { } void WS2812FX::setTargetFps(uint8_t fps) { - if (fps <= 120) _targetFps = fps; + if (fps <= 250) _targetFps = fps; if (_targetFps > 0) _frametime = 1000 / _targetFps; - else _frametime = 3; // unlimited mode + else _frametime = MIN_FRAME_DELAY; // unlimited mode } void WS2812FX::setMode(uint8_t segid, uint8_t m) { @@ -1495,7 +1494,7 @@ void WS2812FX::setBrightness(uint8_t b, bool direct) { BusManager::setBrightness(b); if (!direct) { unsigned long t = millis(); - if (_segments[0].next_time > t + 22 && t - _lastShow > MIN_SHOW_DELAY) trigger(); //apply brightness change immediately if no refresh soon + if (_segments[0].next_time > t + 22 && t - _lastShow > MIN_FRAME_DELAY) trigger(); //apply brightness change immediately if no refresh soon } } diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 55f8122e8..b467d5b9b 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -875,7 +875,7 @@ Swap:
- Target refresh rate: FPS + Target refresh rate: FPS From 001e2ad2875742b51861ba826baa9a9727698ea0 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 8 Nov 2024 19:35:42 +0100 Subject: [PATCH 26/90] adjust audioreactive for the new FRAME_DELAY logic minor --- usermods/audioreactive/audio_reactive.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h index ad449fc83..9c463e0a1 100644 --- a/usermods/audioreactive/audio_reactive.h +++ b/usermods/audioreactive/audio_reactive.h @@ -75,7 +75,7 @@ static uint8_t soundAgc = 0; // Automagic gain control: 0 - n //static float volumeSmth = 0.0f; // either sampleAvg or sampleAgc depending on soundAgc; smoothed sample static float FFT_MajorPeak = 1.0f; // FFT: strongest (peak) frequency static float FFT_Magnitude = 0.0f; // FFT: volume (magnitude) of peak frequency -static bool samplePeak = false; // Boolean flag for peak - used in effects. Responding routine may reset this flag. Auto-reset after strip.getMinShowDelay() +static bool samplePeak = false; // Boolean flag for peak - used in effects. Responding routine may reset this flag. Auto-reset after strip.getFrameTime() static bool udpSamplePeak = false; // Boolean flag for peak. Set at the same time as samplePeak, but reset by transmitAudioData static unsigned long timeOfPeak = 0; // time of last sample peak detection. static uint8_t fftResult[NUM_GEQ_CHANNELS]= {0};// Our calculated freq. channel result table to be used by effects @@ -536,8 +536,8 @@ static void detectSamplePeak(void) { #endif static void autoResetPeak(void) { - uint16_t MinShowDelay = MAX(50, strip.getMinShowDelay()); // Fixes private class variable compiler error. Unsure if this is the correct way of fixing the root problem. -THATDONFC - if (millis() - timeOfPeak > MinShowDelay) { // Auto-reset of samplePeak after a complete frame has passed. + uint16_t peakDelay = max(uint16_t(50), strip.getFrameTime()); + if (millis() - timeOfPeak > peakDelay) { // Auto-reset of samplePeak after at least one complete frame has passed. samplePeak = false; if (audioSyncEnabled == 0) udpSamplePeak = false; // this is normally reset by transmitAudioData } From 536444f9d1fae4c092a6cfd2f3d944e31cf30055 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sat, 9 Nov 2024 16:38:18 +0100 Subject: [PATCH 27/90] fixed palette FX to more closely match original 1D version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - rotation scale is now exactly 180° (divide slider input by 255 instead of 256) - removed shift offset: offset is now zero at slider 0, to hit 128 on touch input devices is really hard - added a 90° shift to input rotation, enabling to rotate from 0 to 180° instead of +90 to -90 (which is not useful in 1D) - changed default settings values to more closely match the old 1D effect --- wled00/FX.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 2f24f745a..47200655d 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1940,7 +1940,7 @@ uint16_t mode_palette() { using angleType = unsigned; constexpr mathType sInt16Scale = 0x7FFF; constexpr mathType maxAngle = 0x8000; - constexpr mathType staticRotationScale = 256; + constexpr mathType staticRotationScale = 255; constexpr mathType animatedRotationScale = 1; constexpr int16_t (*sinFunction)(uint16_t) = &sin16; constexpr int16_t (*cosFunction)(uint16_t) = &cos16; @@ -1949,7 +1949,7 @@ uint16_t mode_palette() { using wideMathType = float; using angleType = float; constexpr mathType sInt16Scale = 1.0f; - constexpr mathType maxAngle = M_PI / 256.0; + constexpr mathType maxAngle = M_PI / 255.0; constexpr mathType staticRotationScale = 1.0f; constexpr mathType animatedRotationScale = M_TWOPI / double(0xFFFF); constexpr float (*sinFunction)(float) = &sin_t; @@ -1961,7 +1961,7 @@ uint16_t mode_palette() { const int inputShift = SEGMENT.speed; const int inputSize = SEGMENT.intensity; - const int inputRotation = SEGMENT.custom1; + const int inputRotation = SEGMENT.custom1 + 128; const bool inputAnimateShift = SEGMENT.check1; const bool inputAnimateRotation = SEGMENT.check2; const bool inputAssumeSquare = SEGMENT.check3; @@ -1985,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. @@ -2016,7 +2016,7 @@ 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); + 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) { @@ -2028,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 From 5de86d3d9166e1d629d5fdcd128008360378dccd Mon Sep 17 00:00:00 2001 From: Woody <27882680+w00000dy@users.noreply.github.com> Date: Sat, 9 Nov 2024 23:55:09 +0100 Subject: [PATCH 28/90] fix problem with spaces --- tools/cdata.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/cdata.js b/tools/cdata.js index d65573a8e..c5d3c6aa5 100644 --- a/tools/cdata.js +++ b/tools/cdata.js @@ -101,6 +101,7 @@ function adoptVersionAndRepo(html) { async function minify(str, type = "plain") { const options = { collapseWhitespace: true, + conservativeCollapse: true, // preserve spaces in text collapseBooleanAttributes: true, collapseInlineTagWhitespace: true, minifyCSS: true, From 9a564ee20457664e09f2d12aeceac874d1edef53 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 10 Nov 2024 14:45:55 +0100 Subject: [PATCH 29/90] readme.md - link to multi-strip KB page --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 595b9ee0b..0a02826af 100644 --- a/readme.md +++ b/readme.md @@ -21,7 +21,7 @@ A fast and feature-rich implementation of an ESP32 and ESP8266 webserver to cont - Segments to set different effects and colors to user defined parts of the LED string - Settings page - configuration via the network - Access Point and station mode - automatic failsafe AP -- Up to 10 LED outputs per instance +- [Up to 10 LED outputs](https://kno.wled.ge/features/multi-strip/#esp32) per instance - Support for RGBW strips - Up to 250 user presets to save and load colors/effects easily, supports cycling through them. - Presets can be used to automatically execute API calls From d437027f2630c88ea660fa4e4ad199f537b1abea Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sun, 10 Nov 2024 22:39:52 +0100 Subject: [PATCH 30/90] Replaced single palette cases with an array to consolidate code - all palettes are defined in palettes.h - access to fastled palettes as an array to remove the switch cases - palette createn in json.cpp in a loop instead of repeaded calls to save flash --- wled00/FX_fcn.cpp | 16 ++------------- wled00/json.cpp | 52 ++++++++--------------------------------------- wled00/palettes.h | 11 ++++++++++ 3 files changed, 21 insertions(+), 58 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index e706f2b43..d666513ae 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -236,23 +236,11 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) { targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,sec,sec,sec); } break;} - case 6: //Party colors - targetPalette = PartyColors_p; break; - case 7: //Cloud colors - targetPalette = CloudColors_p; break; - case 8: //Lava colors - targetPalette = LavaColors_p; break; - case 9: //Ocean colors - targetPalette = OceanColors_p; break; - case 10: //Forest colors - targetPalette = ForestColors_p; break; - case 11: //Rainbow colors - targetPalette = RainbowColors_p; break; - case 12: //Rainbow stripe colors - targetPalette = RainbowStripeColors_p; break; default: //progmem palettes if (pal>245) { targetPalette = strip.customPalettes[255-pal]; // we checked bounds above + } else if (pal < 13) { // palette 6 - 12, fastled palettes + targetPalette = *fastledPalettes[pal-6]; } else { byte tcp[72]; memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[pal-13])), 72); diff --git a/wled00/json.cpp b/wled00/json.cpp index 288059653..c74bf6a8d 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -902,10 +902,7 @@ void serializePalettes(JsonObject root, int page) setPaletteColors(curPalette, PartyColors_p); break; case 1: //random - curPalette.add("r"); - curPalette.add("r"); - curPalette.add("r"); - curPalette.add("r"); + for (int j = 0; j < 4; j++) curPalette.add("r"); break; case 2: //primary color only curPalette.add("c1"); @@ -922,53 +919,20 @@ void serializePalettes(JsonObject root, int page) curPalette.add("c1"); break; case 5: //primary + secondary (+tertiary if not off), more distinct + for (int j = 0; j < 5; j++) curPalette.add("c1"); + for (int j = 0; j < 5; j++) curPalette.add("c2"); + for (int j = 0; j < 5; j++) curPalette.add("c3"); curPalette.add("c1"); - curPalette.add("c1"); - curPalette.add("c1"); - curPalette.add("c1"); - curPalette.add("c1"); - curPalette.add("c2"); - curPalette.add("c2"); - curPalette.add("c2"); - curPalette.add("c2"); - curPalette.add("c2"); - curPalette.add("c3"); - curPalette.add("c3"); - curPalette.add("c3"); - curPalette.add("c3"); - curPalette.add("c3"); - curPalette.add("c1"); - break; - case 6: //Party colors - setPaletteColors(curPalette, PartyColors_p); - break; - case 7: //Cloud colors - setPaletteColors(curPalette, CloudColors_p); - break; - case 8: //Lava colors - setPaletteColors(curPalette, LavaColors_p); - break; - case 9: //Ocean colors - setPaletteColors(curPalette, OceanColors_p); - break; - case 10: //Forest colors - setPaletteColors(curPalette, ForestColors_p); - break; - case 11: //Rainbow colors - setPaletteColors(curPalette, RainbowColors_p); - break; - case 12: //Rainbow stripe colors - setPaletteColors(curPalette, RainbowStripeColors_p); break; default: - { - if (i>=palettesCount) { + if (i >= palettesCount) setPaletteColors(curPalette, strip.customPalettes[i - palettesCount]); - } else { + else if (i < 13) // palette 6 - 12, fastled palettes + setPaletteColors(curPalette, *fastledPalettes[i-6]); + else { memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[i - 13])), 72); setPaletteColors(curPalette, tcp); } - } break; } } diff --git a/wled00/palettes.h b/wled00/palettes.h index 41dfbbc16..1ead342bb 100644 --- a/wled00/palettes.h +++ b/wled00/palettes.h @@ -844,6 +844,17 @@ const byte candy2_gp[] PROGMEM = { 211, 39, 33, 34, 255, 1, 1, 1}; +// array of fastled palettes (palette 6 - 12) +const TProgmemRGBPalette16 *const fastledPalettes[] PROGMEM = { + &PartyColors_p, //06-00 Party + &CloudColors_p, //07-01 Cloud + &LavaColors_p, //08-02 Lava + &OceanColors_p, //09-03 Ocean + &ForestColors_p, //10-04 Forest + &RainbowColors_p, //11-05 Rainbow + &RainbowStripeColors_p //12-06 Rainbow Bands +}; + // Single array of defined cpt-city color palettes. // This will let us programmatically choose one based on // a number, rather than having to activate each explicitly From 223b97b8848d8f44c891ea511dadc20e40270cf7 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Sun, 10 Nov 2024 18:04:07 -0500 Subject: [PATCH 31/90] handleSet: Fix incorrect response generation Don't generate a response if there's no HTTP request. Fixes #4269 --- wled00/set.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/set.cpp b/wled00/set.cpp index c446a2eff..712e5f254 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -1191,7 +1191,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply) // internal call, does not send XML response pos = req.indexOf(F("IN")); - if (pos < 1) { + if ((request != nullptr) && (pos < 1)) { auto response = request->beginResponseStream("text/xml"); XML_response(*response); request->send(response); From 8c5e0cd4e94ebc4a2d59c24fce620f6e3540c903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Fri, 15 Nov 2024 16:01:58 +0100 Subject: [PATCH 32/90] Keep selected FX while searching --- wled00/data/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index d9c64bdfb..cbc389391 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -2850,7 +2850,7 @@ function search(field, listId = null) { if (listId!=='pcont' && i===0) return; const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase(); const searchIndex = listItemName.indexOf(field.value.toUpperCase()); - listItem.style.display = (searchIndex < 0) ? 'none' : ''; + listItem.style.display = (searchIndex < 0) && !listItem.classList.contains("selected") ? 'none' : ''; listItem.dataset.searchIndex = searchIndex; }); @@ -2924,7 +2924,7 @@ function filterFx() { const listItemName = listItem.querySelector('.lstIname').innerText; let hide = false; gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { if (e.checked && !listItemName.includes(e.dataset.flt)) hide = i>0 /*true*/; }); - listItem.style.display = hide ? 'none' : ''; + listItem.style.display = hide && !listItem.classList.contains("selected") ? 'none' : ''; }); } From 86be5df475468824cee3654efc6175170d3dbf83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Fri, 15 Nov 2024 19:03:46 +0100 Subject: [PATCH 33/90] xml comma bugfix + few optimisations --- wled00/xml.cpp | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/wled00/xml.cpp b/wled00/xml.cpp index dc2673271..a4a72abea 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -83,7 +83,7 @@ void appendGPIOinfo(Print& settingsScript) { // usermod pin reservations will become unnecessary when settings pages will read cfg.json directly if (requestJSONBufferLock(6)) { // if we can't allocate JSON buffer ignore usermod pins - JsonObject mods = pDoc->createNestedObject(F("um")); + JsonObject mods = pDoc->createNestedObject("um"); UsermodManager::addToConfig(mods); if (!mods.isNull()) fillUMPins(settingsScript, mods); releaseJSONBufferLock(); @@ -91,35 +91,42 @@ void appendGPIOinfo(Print& settingsScript) { settingsScript.print(F("];")); // add reserved (unusable) pins + bool firstPin = true; settingsScript.print(F("d.rsvd=[")); for (unsigned i = 0; i < WLED_NUM_PINS; i++) { if (!PinManager::isPinOk(i, false)) { // include readonly pins - settingsScript.print(i); settingsScript.print(","); + if (!firstPin) settingsScript.print(','); + settingsScript.print(i); + firstPin = false; } } #ifdef WLED_ENABLE_DMX - settingsScript.print(F("2,")); // DMX hardcoded pin + if (!firstPin) settingsScript.print(','); + settingsScript.print(2); // DMX hardcoded pin + firstPin = false; #endif #if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST) - settingsScript.printf_P(PSTR(",%d"),hardwareTX); // debug output (TX) pin + if (!firstPin) settingsScript.print(','); + settingsScript.print(hardwareTX); // debug output (TX) pin + firstPin = false; #endif - //Note: Using pin 3 (RX) disables Adalight / Serial JSON #ifdef WLED_USE_ETHERNET if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) { - for (unsigned p=0; p=0) { settingsScript.printf(",%d", ethernetBoards[ethernetType].eth_power); } - if (ethernetBoards[ethernetType].eth_mdc>=0) { settingsScript.printf(",%d", ethernetBoards[ethernetType].eth_mdc); } - if (ethernetBoards[ethernetType].eth_mdio>=0) { settingsScript.printf(",%d", ethernetBoards[ethernetType].eth_mdio); } - switch (ethernetBoards[ethernetType].eth_clk_mode) { + if (!firstPin) settingsScript.print(','); + for (unsigned p=0; p= 0) { settingsScript.printf("%d,",ethernetBoards[ethernetType].eth_power); } + if (ethernetBoards[ethernetType].eth_mdc >= 0) { settingsScript.printf("%d,",ethernetBoards[ethernetType].eth_mdc); } + if (ethernetBoards[ethernetType].eth_mdio >= 0) { settingsScript.printf("%d,",ethernetBoards[ethernetType].eth_mdio); } + switch (ethernetBoards[ethernetType].eth_clk_mode) { case ETH_CLOCK_GPIO0_IN: case ETH_CLOCK_GPIO0_OUT: - settingsScript.print(F("0")); + settingsScript.print(0); break; case ETH_CLOCK_GPIO16_OUT: - settingsScript.print(F("16")); + settingsScript.print(16); break; case ETH_CLOCK_GPIO17_OUT: - settingsScript.print(F("17")); + settingsScript.print(17); break; } } @@ -128,11 +135,11 @@ void appendGPIOinfo(Print& settingsScript) { // add info for read-only GPIO settingsScript.print(F("d.ro_gpio=[")); - bool firstPin = true; + firstPin = true; for (unsigned i = 0; i < WLED_NUM_PINS; i++) { if (PinManager::isReadOnlyPin(i)) { // No comma before the first pin - if (!firstPin) settingsScript.print(F(",")); + if (!firstPin) settingsScript.print(','); settingsScript.print(i); firstPin = false; } @@ -142,7 +149,7 @@ void appendGPIOinfo(Print& settingsScript) { // add info about max. # of pins settingsScript.print(F("d.max_gpio=")); settingsScript.print(WLED_NUM_PINS); - settingsScript.print(F(";")); + settingsScript.print(';'); } //get values for settings form in javascript @@ -152,6 +159,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) DEBUG_PRINTF_P(PSTR("settings resp %u\n"), (unsigned)subPage); if (subPage <0 || subPage >10) return; + char nS[32]; if (subPage == SUBPAGE_MENU) { @@ -259,8 +267,6 @@ void getSettingsJS(byte subPage, Print& settingsScript) if (subPage == SUBPAGE_LEDS) { - char nS[32]; - appendGPIOinfo(settingsScript); settingsScript.print(F("d.ledTypes=")); settingsScript.print(BusManager::getLEDTypesJSONString().c_str()); settingsScript.print(";"); @@ -399,7 +405,6 @@ void getSettingsJS(byte subPage, Print& settingsScript) if (subPage == SUBPAGE_SYNC) { - [[maybe_unused]] char nS[32]; printSetFormValue(settingsScript,PSTR("UP"),udpPort); printSetFormValue(settingsScript,PSTR("U2"),udpPort2); #ifndef WLED_DISABLE_ESPNOW @@ -637,7 +642,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) #if defined(ARDUINO_ARCH_ESP32) ESP.getChipModel(), #else - F("esp8266"), + "esp8266", #endif VERSION); From 7f69a0bc5ec42c507f3923b456257c517b65e1ef Mon Sep 17 00:00:00 2001 From: maxi4329 Date: Sat, 16 Nov 2024 12:37:24 +0100 Subject: [PATCH 34/90] removed obsolete code as of #4267 --- wled00/data/style.css | 3 --- wled00/data/update.htm | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/wled00/data/style.css b/wled00/data/style.css index 42e49d304..b6cb0f9e6 100644 --- a/wled00/data/style.css +++ b/wled00/data/style.css @@ -44,9 +44,6 @@ button.sml { min-width: 40px; margin: 0 0 0 10px; } -span:before, b:before, b:after, i:after{ - content: "\00A0"; -} #scan { margin-top: -10px; } diff --git a/wled00/data/update.htm b/wled00/data/update.htm index b68645a52..23a6a866e 100644 --- a/wled00/data/update.htm +++ b/wled00/data/update.htm @@ -17,7 +17,7 @@

WLED Software Update

Installed version: ##VERSION##
- Download the latest binary: 

From 6fe2024542b12fc17af98fa6402ca5f557a6d958 Mon Sep 17 00:00:00 2001 From: Woody <27882680+w00000dy@users.noreply.github.com> Date: Sat, 16 Nov 2024 19:53:10 +0100 Subject: [PATCH 35/90] move selected to the bottom in search result --- wled00/data/index.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index cbc389391..f93511aaf 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -2827,7 +2827,7 @@ function search(field, listId = null) { // restore default preset sorting if no search term is entered if (!search) { - if (listId === 'pcont') { populatePresets(); return; } + if (listId === 'pcont') { populatePresets(); return; } if (listId === 'pallist') { let id = parseInt(d.querySelector('#pallist input[name="palette"]:checked').value); // preserve selected palette populatePalettes(); @@ -2846,12 +2846,17 @@ function search(field, listId = null) { // filter list items but leave (Default & Solid) always visible const listItems = gId(listId).querySelectorAll('.lstI'); - listItems.forEach((listItem,i)=>{ - if (listId!=='pcont' && i===0) return; + listItems.forEach((listItem, i) => { const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase(); const searchIndex = listItemName.indexOf(field.value.toUpperCase()); - listItem.style.display = (searchIndex < 0) && !listItem.classList.contains("selected") ? 'none' : ''; - listItem.dataset.searchIndex = searchIndex; + if (searchIndex < 0) { + listItem.dataset.searchIndex = Number.MAX_SAFE_INTEGER; + } else { + listItem.dataset.searchIndex = searchIndex; + } + + if ((listId !== 'pcont' && i === 0) || listItem.classList.contains("selected")) return; + listItem.style.display = (searchIndex < 0) ? 'none' : ''; }); // sort list items by search index and name @@ -2920,10 +2925,10 @@ function filterFx() { inputField.value = ''; inputField.focus(); clean(inputField.nextElementSibling); - gId("fxlist").querySelectorAll('.lstI').forEach((listItem,i) => { + gId("fxlist").querySelectorAll('.lstI').forEach((listItem, i) => { const listItemName = listItem.querySelector('.lstIname').innerText; let hide = false; - gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { if (e.checked && !listItemName.includes(e.dataset.flt)) hide = i>0 /*true*/; }); + gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { if (e.checked && !listItemName.includes(e.dataset.flt)) hide = i > 0 /*true*/; }); listItem.style.display = hide && !listItem.classList.contains("selected") ? 'none' : ''; }); } From 4d3df5d98fb283e936db9eb7f19406a3a5a38b24 Mon Sep 17 00:00:00 2001 From: Woody <27882680+w00000dy@users.noreply.github.com> Date: Sat, 16 Nov 2024 20:12:29 +0100 Subject: [PATCH 36/90] Fix default/solid not being first --- wled00/data/index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index f93511aaf..1482c27b5 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -2847,6 +2847,7 @@ function search(field, listId = null) { // filter list items but leave (Default & Solid) always visible const listItems = gId(listId).querySelectorAll('.lstI'); listItems.forEach((listItem, i) => { + if (listId !== 'pcont' && i === 0) return; const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase(); const searchIndex = listItemName.indexOf(field.value.toUpperCase()); if (searchIndex < 0) { @@ -2854,9 +2855,7 @@ function search(field, listId = null) { } else { listItem.dataset.searchIndex = searchIndex; } - - if ((listId !== 'pcont' && i === 0) || listItem.classList.contains("selected")) return; - listItem.style.display = (searchIndex < 0) ? 'none' : ''; + listItem.style.display = (searchIndex < 0) && !listItem.classList.contains("selected") ? 'none' : ''; }); // sort list items by search index and name From a765903a41d3272c166ff5351da5c0338947c183 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Sat, 16 Nov 2024 17:10:08 -0500 Subject: [PATCH 37/90] Fix array overflow in exploding_fireworks Attempt to allocate enough room for the "minimum" sparks; and ensure that we never overrun the allocated array size. Fixes #4120 --- wled00/FX.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 2f24f745a..947788fee 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -3547,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); @@ -3602,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) { From 84dd26c1b7d90b2f4466253bc9e6b9faa545451a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Sun, 17 Nov 2024 10:47:09 +0100 Subject: [PATCH 38/90] Some more optimisations. --- wled00/xml.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/wled00/xml.cpp b/wled00/xml.cpp index a4a72abea..df52b6248 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -147,9 +147,7 @@ void appendGPIOinfo(Print& settingsScript) { settingsScript.print(F("];")); // add info about max. # of pins - settingsScript.print(F("d.max_gpio=")); - settingsScript.print(WLED_NUM_PINS); - settingsScript.print(';'); + settingsScript.printf_P(PSTR("d.max_gpio=%d;"),WLED_NUM_PINS); } //get values for settings form in javascript @@ -269,7 +267,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) { appendGPIOinfo(settingsScript); - settingsScript.print(F("d.ledTypes=")); settingsScript.print(BusManager::getLEDTypesJSONString().c_str()); settingsScript.print(";"); + settingsScript.printf_P(PSTR("d.ledTypes=%s;"), BusManager::getLEDTypesJSONString().c_str()); // set limits settingsScript.printf_P(PSTR("bLimits(%d,%d,%d,%d,%d,%d,%d,%d);"), @@ -653,8 +651,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) { printSetFormValue(settingsScript,PSTR("SOMP"),strip.isMatrix); #ifndef WLED_DISABLE_2D - settingsScript.printf_P(PSTR("maxPanels=%d;"),WLED_MAX_PANELS); - settingsScript.print(F("resetPanels();")); + settingsScript.printf_P(PSTR("maxPanels=%d;resetPanels();"),WLED_MAX_PANELS); if (strip.isMatrix) { if(strip.panels>0){ printSetFormValue(settingsScript,PSTR("PW"),strip.panel[0].width); //Set generator Width and Height to first panel size for convenience @@ -664,11 +661,9 @@ void getSettingsJS(byte subPage, Print& settingsScript) // panels for (unsigned i=0; i Date: Sun, 17 Nov 2024 14:31:23 +0100 Subject: [PATCH 39/90] Bugfix --- wled00/xml.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wled00/xml.cpp b/wled00/xml.cpp index df52b6248..597db73f2 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -660,8 +660,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) printSetFormValue(settingsScript,PSTR("MPC"),strip.panels); // panels for (unsigned i=0; i Date: Thu, 21 Nov 2024 10:52:22 +0100 Subject: [PATCH 40/90] Introduce printSetInputMaxlength to properly set an inputs maxlength variable --- wled00/fcn_declare.h | 1 + wled00/util.cpp | 4 ++++ wled00/xml.cpp | 5 +++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 1855a8b63..91176160f 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -380,6 +380,7 @@ size_t printSetFormValue(Print& settingsScript, const char* key, int val); size_t printSetFormValue(Print& settingsScript, const char* key, const char* val); size_t printSetFormIndex(Print& settingsScript, const char* key, int index); size_t printSetClassElementHTML(Print& settingsScript, const char* key, const int index, const char* val); +size_t printSetInputMaxLength(Print& settingsScript, const char* key, int val); void prepareHostname(char* hostname); bool isAsterisksOnly(const char* str, byte maxLen); bool requestJSONBufferLock(uint8_t module=255); diff --git a/wled00/util.cpp b/wled00/util.cpp index 0b78a4646..1c1282eda 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -109,6 +109,10 @@ size_t printSetClassElementHTML(Print& settingsScript, const char* key, const in return settingsScript.printf_P(PSTR("d.getElementsByClassName(\"%s\")[%d].innerHTML=\"%s\";"), key, index, val); } +size_t printSetInputMaxLength(Print& settingsScript, const char* key, int val) { + return settingsScript.printf_P(PSTR("d.Sf.%s.setAttribute(\"maxlength\", %d);"),key,val); +} + void prepareHostname(char* hostname) diff --git a/wled00/xml.cpp b/wled00/xml.cpp index dc2673271..6f837a9b6 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -465,8 +465,9 @@ void getSettingsJS(byte subPage, Print& settingsScript) printSetFormValue(settingsScript,PSTR("MG"),mqttGroupTopic); printSetFormCheckbox(settingsScript,PSTR("BM"),buttonPublishMqtt); printSetFormCheckbox(settingsScript,PSTR("RT"),retainMqttMsg); - settingsScript.printf_P(PSTR("d.Sf.MD.maxlength=%d;d.Sf.MG.maxlength=%d;d.Sf.MS.maxlength=%d;"), - MQTT_MAX_TOPIC_LEN, MQTT_MAX_TOPIC_LEN, MQTT_MAX_SERVER_LEN); + printSetInputMaxLength(settingsScript, PSTR("MD"), MQTT_MAX_TOPIC_LEN); + printSetInputMaxLength(settingsScript, PSTR("MG"), MQTT_MAX_TOPIC_LEN); + printSetInputMaxLength(settingsScript, PSTR("MS"), MQTT_MAX_SERVER_LEN); #else settingsScript.print(F("toggle('MQTT');")); // hide MQTT settings #endif From 5ac8ba9bae80688ab9c9151e8775447d8e86cbf1 Mon Sep 17 00:00:00 2001 From: Wouter Gritter Date: Thu, 21 Nov 2024 12:02:55 +0100 Subject: [PATCH 41/90] Revert "Introduce printSetInputMaxlength to properly set an inputs maxlength variable" This reverts commit 49fb16e2c6528ddc98cccc352cc8f0d4a5f62a13. --- wled00/fcn_declare.h | 1 - wled00/util.cpp | 4 ---- wled00/xml.cpp | 5 ++--- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 91176160f..1855a8b63 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -380,7 +380,6 @@ size_t printSetFormValue(Print& settingsScript, const char* key, int val); size_t printSetFormValue(Print& settingsScript, const char* key, const char* val); size_t printSetFormIndex(Print& settingsScript, const char* key, int index); size_t printSetClassElementHTML(Print& settingsScript, const char* key, const int index, const char* val); -size_t printSetInputMaxLength(Print& settingsScript, const char* key, int val); void prepareHostname(char* hostname); bool isAsterisksOnly(const char* str, byte maxLen); bool requestJSONBufferLock(uint8_t module=255); diff --git a/wled00/util.cpp b/wled00/util.cpp index 1c1282eda..0b78a4646 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -109,10 +109,6 @@ size_t printSetClassElementHTML(Print& settingsScript, const char* key, const in return settingsScript.printf_P(PSTR("d.getElementsByClassName(\"%s\")[%d].innerHTML=\"%s\";"), key, index, val); } -size_t printSetInputMaxLength(Print& settingsScript, const char* key, int val) { - return settingsScript.printf_P(PSTR("d.Sf.%s.setAttribute(\"maxlength\", %d);"),key,val); -} - void prepareHostname(char* hostname) diff --git a/wled00/xml.cpp b/wled00/xml.cpp index 6f837a9b6..dc2673271 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -465,9 +465,8 @@ void getSettingsJS(byte subPage, Print& settingsScript) printSetFormValue(settingsScript,PSTR("MG"),mqttGroupTopic); printSetFormCheckbox(settingsScript,PSTR("BM"),buttonPublishMqtt); printSetFormCheckbox(settingsScript,PSTR("RT"),retainMqttMsg); - printSetInputMaxLength(settingsScript, PSTR("MD"), MQTT_MAX_TOPIC_LEN); - printSetInputMaxLength(settingsScript, PSTR("MG"), MQTT_MAX_TOPIC_LEN); - printSetInputMaxLength(settingsScript, PSTR("MS"), MQTT_MAX_SERVER_LEN); + settingsScript.printf_P(PSTR("d.Sf.MD.maxlength=%d;d.Sf.MG.maxlength=%d;d.Sf.MS.maxlength=%d;"), + MQTT_MAX_TOPIC_LEN, MQTT_MAX_TOPIC_LEN, MQTT_MAX_SERVER_LEN); #else settingsScript.print(F("toggle('MQTT');")); // hide MQTT settings #endif From 5c8b2ebf7a015983890daecabe0db1cfcc7628d0 Mon Sep 17 00:00:00 2001 From: Wouter Gritter Date: Thu, 21 Nov 2024 12:04:01 +0100 Subject: [PATCH 42/90] maxlength -> maxLength to fix this attribute not being modified correctly --- wled00/xml.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/xml.cpp b/wled00/xml.cpp index dc2673271..0893e5d25 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -465,7 +465,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) printSetFormValue(settingsScript,PSTR("MG"),mqttGroupTopic); printSetFormCheckbox(settingsScript,PSTR("BM"),buttonPublishMqtt); printSetFormCheckbox(settingsScript,PSTR("RT"),retainMqttMsg); - settingsScript.printf_P(PSTR("d.Sf.MD.maxlength=%d;d.Sf.MG.maxlength=%d;d.Sf.MS.maxlength=%d;"), + settingsScript.printf_P(PSTR("d.Sf.MD.maxLength=%d;d.Sf.MG.maxLength=%d;d.Sf.MS.maxLength=%d;"), MQTT_MAX_TOPIC_LEN, MQTT_MAX_TOPIC_LEN, MQTT_MAX_SERVER_LEN); #else settingsScript.print(F("toggle('MQTT');")); // hide MQTT settings From 6790f8af084a4f4fe04672d82c6f55744d6d095d Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 21 Nov 2024 22:16:03 +0100 Subject: [PATCH 43/90] Same MIN_FRAME_DELAY=3 for -C3 and -S2 --- wled00/FX.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 56a0c9bd0..c15500aa3 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -48,8 +48,8 @@ #define FRAMETIME strip.getFrameTime() #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) #define MIN_FRAME_DELAY 2 // minimum wait between repaints, to keep other functions like WiFi alive -#elif defined(CONFIG_IDF_TARGET_ESP32S2) - #define MIN_FRAME_DELAY 4 // S2 is slower than normal esp32, and only has one core +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) + #define MIN_FRAME_DELAY 3 // S2/C3 are slower than normal esp32, and only have one core #else #define MIN_FRAME_DELAY 8 // 8266 legacy MIN_SHOW_DELAY #endif From 548736f432d5c1484b85045816ce1cfbafaa4e46 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 21 Nov 2024 22:50:55 +0100 Subject: [PATCH 44/90] SparkFunDMX fix for possible array bounds violation in DMX.write Align with code in espdmx.cpp --- wled00/src/dependencies/dmx/SparkFunDMX.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/src/dependencies/dmx/SparkFunDMX.cpp b/wled00/src/dependencies/dmx/SparkFunDMX.cpp index dbc9b1590..064b9ff62 100644 --- a/wled00/src/dependencies/dmx/SparkFunDMX.cpp +++ b/wled00/src/dependencies/dmx/SparkFunDMX.cpp @@ -34,8 +34,8 @@ static const int enablePin = -1; // disable the enable pin because it is not ne static const int rxPin = -1; // disable the receiving pin because it is not needed - softhack007: Pin=-1 means "use default" not "disable" static const int txPin = 2; // transmit DMX data over this pin (default is pin 2) -//DMX value array and size. Entry 0 will hold startbyte -static uint8_t dmxData[dmxMaxChannel] = { 0 }; +//DMX value array and size. Entry 0 will hold startbyte, so we need 512+1 elements +static uint8_t dmxData[dmxMaxChannel+1] = { 0 }; static int chanSize = 0; #if !defined(DMX_SEND_ONLY) static int currentChannel = 0; From 32dc54ce7239c9947260db272750fb5c5cfacb19 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Fri, 22 Nov 2024 08:43:45 +0100 Subject: [PATCH 45/90] reverted rotation scale, offset only on static rotation, inverted shift direction - inverting the shift direction in signed int is computationally safe as it is cast into an uint8_t and it matches the original FX in 1D --- wled00/FX.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 47200655d..1463121eb 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1940,7 +1940,7 @@ uint16_t mode_palette() { using angleType = unsigned; constexpr mathType sInt16Scale = 0x7FFF; constexpr mathType maxAngle = 0x8000; - constexpr mathType staticRotationScale = 255; + constexpr mathType staticRotationScale = 256; constexpr mathType animatedRotationScale = 1; constexpr int16_t (*sinFunction)(uint16_t) = &sin16; constexpr int16_t (*cosFunction)(uint16_t) = &cos16; @@ -1949,7 +1949,7 @@ uint16_t mode_palette() { using wideMathType = float; using angleType = float; constexpr mathType sInt16Scale = 1.0f; - constexpr mathType maxAngle = M_PI / 255.0; + constexpr mathType maxAngle = M_PI / 256.0; constexpr mathType staticRotationScale = 1.0f; constexpr mathType animatedRotationScale = M_TWOPI / double(0xFFFF); constexpr float (*sinFunction)(float) = &sin_t; @@ -1961,12 +1961,12 @@ uint16_t mode_palette() { const int inputShift = SEGMENT.speed; const int inputSize = SEGMENT.intensity; - const int inputRotation = SEGMENT.custom1 + 128; + const int inputRotation = SEGMENT.custom1; const bool inputAnimateShift = SEGMENT.check1; 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); @@ -2017,7 +2017,7 @@ uint16_t mode_palette() { } // Finally, shift the palette a bit. const int paletteOffset = (!inputAnimateShift) ? (inputShift) : (((strip.now * ((inputShift >> 3) +1)) & 0xFFFF) >> 8); - colorIndex += paletteOffset; + colorIndex -= paletteOffset; const uint32_t color = SEGMENT.color_wheel((uint8_t)colorIndex); if (isMatrix) { SEGMENT.setPixelColorXY(x, y, color); From 6aef0e145c234cabb1129feed4068830de45a409 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 23 Nov 2024 16:31:07 +0000 Subject: [PATCH 46/90] Remove TOSTRING for releaseString and add quotes to WLED_RELEASE_NAME --- platformio.ini | 42 +++++++++++++++++++++--------------------- wled00/wled.h | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/platformio.ini b/platformio.ini index 6d4aa1dc1..fe02213ff 100644 --- a/platformio.ini +++ b/platformio.ini @@ -345,7 +345,7 @@ platform = ${common.platform_wled_default} platform_packages = ${common.platform_packages} board_build.ldscript = ${common.ldscript_4m1m} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP8266 #-DWLED_DISABLE_2D +build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP8266\" #-DWLED_DISABLE_2D lib_deps = ${esp8266.lib_deps} monitor_filters = esp8266_exception_decoder @@ -354,13 +354,13 @@ extends = env:nodemcuv2 ;; using platform version and build options from WLED 0.14.0 platform = ${esp8266.platform_compat} platform_packages = ${esp8266.platform_packages_compat} -build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=ESP8266_compat #-DWLED_DISABLE_2D +build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=\"ESP8266_compat\" #-DWLED_DISABLE_2D ;; lib_deps = ${esp8266.lib_deps_compat} ;; experimental - use older NeoPixelBus 2.7.9 [env:nodemcuv2_160] extends = env:nodemcuv2 board_build.f_cpu = 160000000L -build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP8266_160 #-DWLED_DISABLE_2D +build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP8266_160\" #-DWLED_DISABLE_2D -D USERMOD_AUDIOREACTIVE [env:esp8266_2m] @@ -369,7 +369,7 @@ platform = ${common.platform_wled_default} platform_packages = ${common.platform_packages} board_build.ldscript = ${common.ldscript_2m512k} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP02 +build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP02\" lib_deps = ${esp8266.lib_deps} [env:esp8266_2m_compat] @@ -377,12 +377,12 @@ extends = env:esp8266_2m ;; using platform version and build options from WLED 0.14.0 platform = ${esp8266.platform_compat} platform_packages = ${esp8266.platform_packages_compat} -build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=ESP02_compat #-DWLED_DISABLE_2D +build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=\"ESP02_compat\" #-DWLED_DISABLE_2D [env:esp8266_2m_160] extends = env:esp8266_2m board_build.f_cpu = 160000000L -build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP02_160 +build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP02_160\" -D USERMOD_AUDIOREACTIVE [env:esp01_1m_full] @@ -391,7 +391,7 @@ platform = ${common.platform_wled_default} platform_packages = ${common.platform_packages} board_build.ldscript = ${common.ldscript_1m128k} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP01 -D WLED_DISABLE_OTA +build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP01\" -D WLED_DISABLE_OTA ; -D WLED_USE_REAL_MATH ;; may fix wrong sunset/sunrise times, at the cost of 7064 bytes FLASH and 975 bytes RAM lib_deps = ${esp8266.lib_deps} @@ -400,12 +400,12 @@ extends = env:esp01_1m_full ;; using platform version and build options from WLED 0.14.0 platform = ${esp8266.platform_compat} platform_packages = ${esp8266.platform_packages_compat} -build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=ESP01_compat -D WLED_DISABLE_OTA #-DWLED_DISABLE_2D +build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=\"ESP01_compat\" -D WLED_DISABLE_OTA #-DWLED_DISABLE_2D [env:esp01_1m_full_160] extends = env:esp01_1m_full board_build.f_cpu = 160000000L -build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP01_160 -D WLED_DISABLE_OTA +build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP01_160\" -D WLED_DISABLE_OTA -D USERMOD_AUDIOREACTIVE ; -D WLED_USE_REAL_MATH ;; may fix wrong sunset/sunrise times, at the cost of 7064 bytes FLASH and 975 bytes RAM @@ -414,7 +414,7 @@ board = esp32dev platform = ${esp32.platform} platform_packages = ${esp32.platform_packages} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=ESP32 #-D WLED_DISABLE_BROWNOUT_DET +build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32\" #-D WLED_DISABLE_BROWNOUT_DET ${esp32.AR_build_flags} lib_deps = ${esp32.lib_deps} ${esp32.AR_lib_deps} @@ -426,7 +426,7 @@ board = esp32dev platform = ${esp32_idf_V4.platform} platform_packages = ${esp32_idf_V4.platform_packages} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=ESP32_8M #-D WLED_DISABLE_BROWNOUT_DET +build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_8M\" #-D WLED_DISABLE_BROWNOUT_DET ${esp32.AR_build_flags} lib_deps = ${esp32_idf_V4.lib_deps} ${esp32.AR_lib_deps} @@ -442,7 +442,7 @@ board = esp32dev platform = ${esp32_idf_V4.platform} platform_packages = ${esp32_idf_V4.platform_packages} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=ESP32_16M #-D WLED_DISABLE_BROWNOUT_DET +build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_16M\" #-D WLED_DISABLE_BROWNOUT_DET ${esp32.AR_build_flags} lib_deps = ${esp32_idf_V4.lib_deps} ${esp32.AR_lib_deps} @@ -458,7 +458,7 @@ board_build.flash_mode = dio ;platform = ${esp32.platform} ;platform_packages = ${esp32.platform_packages} ;build_unflags = ${common.build_unflags} -;build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=ESP32_audioreactive #-D WLED_DISABLE_BROWNOUT_DET +;build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32_audioreactive\" #-D WLED_DISABLE_BROWNOUT_DET ; ${esp32.AR_build_flags} ;lib_deps = ${esp32.lib_deps} ; ${esp32.AR_lib_deps} @@ -473,7 +473,7 @@ platform = ${esp32.platform} platform_packages = ${esp32.platform_packages} upload_speed = 921600 build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=ESP32_Ethernet -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 +build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32_Ethernet\" -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 ; -D WLED_DISABLE_ESPNOW ;; ESP-NOW requires wifi, may crash with ethernet only ${esp32.AR_build_flags} lib_deps = ${esp32.lib_deps} @@ -489,7 +489,7 @@ board_build.f_flash = 80000000L board_build.flash_mode = qio board_build.partitions = ${esp32.extended_partitions} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=ESP32_WROVER +build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_WROVER\" -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue ;; Older ESP32 (rev.<3) need a PSRAM fix (increases static RAM used) https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/external-ram.html -D DATA_PINS=25 ${esp32.AR_build_flags} @@ -503,7 +503,7 @@ platform_packages = ${esp32c3.platform_packages} framework = arduino board = esp32-c3-devkitm-1 board_build.partitions = ${esp32.default_partitions} -build_flags = ${common.build_flags} ${esp32c3.build_flags} -D WLED_RELEASE_NAME=ESP32-C3 +build_flags = ${common.build_flags} ${esp32c3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-C3\" -D WLED_WATCHDOG_TIMEOUT=0 -DLOLIN_WIFI_FIX ; seems to work much better with this -DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB @@ -520,7 +520,7 @@ platform = ${esp32s3.platform} platform_packages = ${esp32s3.platform_packages} upload_speed = 921600 build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_16MB_opi +build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_16MB_opi\" -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 ;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") @@ -543,7 +543,7 @@ platform = ${esp32s3.platform} platform_packages = ${esp32s3.platform_packages} upload_speed = 921600 build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_8MB_opi +build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_8MB_opi\" -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 ;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") @@ -565,7 +565,7 @@ board = esp32s3camlcd ;; this is the only standard board with "opi_opi" board_build.arduino.memory_type = opi_opi upload_speed = 921600 build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_WROOM-2 +build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_WROOM-2\" -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 -D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip ;; -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") @@ -590,7 +590,7 @@ platform = ${esp32s3.platform} platform_packages = ${esp32s3.platform_packages} upload_speed = 921600 build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_4M_qspi +build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_4M_qspi\" -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") -DBOARD_HAS_PSRAM -DLOLIN_WIFI_FIX ; seems to work much better with this @@ -611,7 +611,7 @@ board_build.partitions = ${esp32.default_partitions} board_build.flash_mode = qio board_build.f_flash = 80000000L build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=ESP32-S2 +build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S2\" -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 diff --git a/wled00/wled.h b/wled00/wled.h index 2b3a77d24..163ce6b04 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -269,7 +269,7 @@ using PSRAMDynamicJsonDocument = BasicJsonDocument; // Global Variable definitions WLED_GLOBAL char versionString[] _INIT(TOSTRING(WLED_VERSION)); -WLED_GLOBAL char releaseString[] _INIT(TOSTRING(WLED_RELEASE_NAME)); // somehow this will not work if using "const char releaseString[] +WLED_GLOBAL char releaseString[] _INIT(WLED_RELEASE_NAME); // somehow this will not work if using "const char releaseString[] #define WLED_CODENAME "Kōsen" // AP and OTA default passwords (for maximum security change them!) From 0be1df7ee89d01a53b0043dd4c4b66c0e741ccd4 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 23 Nov 2024 16:46:41 +0000 Subject: [PATCH 47/90] Stip \" from WLED_RELEASE_NAME --- pio-scripts/output_bins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pio-scripts/output_bins.py b/pio-scripts/output_bins.py index 633654008..bdd6fc941 100644 --- a/pio-scripts/output_bins.py +++ b/pio-scripts/output_bins.py @@ -19,7 +19,7 @@ def _create_dirs(dirs=["map", "release", "firmware"]): os.makedirs(os.path.join(OUTPUT_DIR, d), exist_ok=True) def create_release(source): - release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME") + release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME").replace("\\\"", "") if release_name: version = _get_cpp_define_value(env, "WLED_VERSION") release_file = os.path.join(OUTPUT_DIR, "release", f"WLED_{version}_{release_name}.bin") From d53d7aa2e2d22085979e0134fb7ce1c5dd6684df Mon Sep 17 00:00:00 2001 From: Will Miles Date: Sat, 23 Nov 2024 12:29:46 -0500 Subject: [PATCH 48/90] Defer calling begin() on digital buses NeoPixelBus requires that all parallel I2S bus members be constructed before any of them call Begin(). Implement this by deferring the call to the end of bus construction. Fixes #4301. --- wled00/FX_fcn.cpp | 11 +++-------- wled00/bus_manager.cpp | 4 ++-- wled00/bus_manager.h | 3 ++- wled00/bus_wrapper.h | 2 +- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index e706f2b43..7177ca89e 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1286,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; diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 5b948b9c4..8281211c1 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -410,7 +410,7 @@ std::vector BusDigital::getLEDTypes() { }; } -void BusDigital::reinit() { +void BusDigital::begin() { if (!_valid) return; PolyBus::begin(_busPtr, _iType, _pins); } @@ -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..7e6e74d85 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -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; } From 0c77dbb7ea63c0b228d5d0f576d6eb0dcb7daeb1 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sun, 24 Nov 2024 13:55:23 +0000 Subject: [PATCH 49/90] cleanup WLED_RELEASE_NAME only if present --- pio-scripts/output_bins.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pio-scripts/output_bins.py b/pio-scripts/output_bins.py index bdd6fc941..4d1594d84 100644 --- a/pio-scripts/output_bins.py +++ b/pio-scripts/output_bins.py @@ -19,8 +19,9 @@ def _create_dirs(dirs=["map", "release", "firmware"]): os.makedirs(os.path.join(OUTPUT_DIR, d), exist_ok=True) def create_release(source): - release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME").replace("\\\"", "") - if release_name: + release_name_def = _get_cpp_define_value(env, "WLED_RELEASE_NAME") + if release_name_def: + release_name = release_name_def.replace("\\\"", "") version = _get_cpp_define_value(env, "WLED_VERSION") release_file = os.path.join(OUTPUT_DIR, "release", f"WLED_{version}_{release_name}.bin") release_gz_file = release_file + ".gz" From 20f8d3c8a9cc0812261089714baaf08538aabb19 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sun, 24 Nov 2024 15:26:30 +0000 Subject: [PATCH 50/90] Builds without WLED_RELEASE_NAME should be called Custom --- wled00/wled.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/wled.h b/wled00/wled.h index 163ce6b04..bb647340b 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -264,7 +264,7 @@ using PSRAMDynamicJsonDocument = BasicJsonDocument; #define WLED_VERSION dev #endif #ifndef WLED_RELEASE_NAME - #define WLED_RELEASE_NAME dev_release + #define WLED_RELEASE_NAME "Custom" #endif // Global Variable definitions From 5b989adebc666f5d6314e0ece81c1141a0ae454f Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:27:53 +0100 Subject: [PATCH 51/90] Allow TV Simulator on single LED segments I've checked the code - nothing preventing the effect to run with SEGLEN=1 --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 947788fee..80be13c62 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4631,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"; /* From dd533a9ab4f37c8bc271f4a7cdbd7c0fe51456a3 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Mon, 25 Nov 2024 23:00:31 +0000 Subject: [PATCH 52/90] Update sample WLED_RELEASE_NAME --- platformio_override.sample.ini | 2 +- wled00/wled.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio_override.sample.ini b/platformio_override.sample.ini index 8e5fdf003..a4dea6677 100644 --- a/platformio_override.sample.ini +++ b/platformio_override.sample.ini @@ -37,7 +37,7 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} ; *** To use the below defines/overrides, copy and paste each onto it's own line just below build_flags in the section above. ; ; Set a release name that may be used to distinguish required binary for flashing -; -D WLED_RELEASE_NAME=ESP32_MULTI_USREMODS +; -D WLED_RELEASE_NAME=\"ESP32_MULTI_USREMODS\" ; ; disable specific features ; -D WLED_DISABLE_OTA diff --git a/wled00/wled.h b/wled00/wled.h index bb647340b..fcbc11978 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -269,7 +269,7 @@ using PSRAMDynamicJsonDocument = BasicJsonDocument; // Global Variable definitions WLED_GLOBAL char versionString[] _INIT(TOSTRING(WLED_VERSION)); -WLED_GLOBAL char releaseString[] _INIT(WLED_RELEASE_NAME); // somehow this will not work if using "const char releaseString[] +WLED_GLOBAL char releaseString[] _INIT(WLED_RELEASE_NAME); // must include the quotes when defining, e.g -D WLED_RELEASE_NAME=\"ESP32_MULTI_USREMODS\" #define WLED_CODENAME "Kōsen" // AP and OTA default passwords (for maximum security change them!) From d87c5035dd0ac1c908c6a4680640999ab52bbddd Mon Sep 17 00:00:00 2001 From: AlDIY <87589371+dosipod@users.noreply.github.com> Date: Tue, 26 Nov 2024 19:33:22 +0300 Subject: [PATCH 53/90] Update settings_sec.htm --- wled00/data/settings_sec.htm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wled00/data/settings_sec.htm b/wled00/data/settings_sec.htm index fa75882c0..7fe0fe62e 100644 --- a/wled00/data/settings_sec.htm +++ b/wled00/data/settings_sec.htm @@ -60,8 +60,8 @@

Backup & Restore

⚠ Restoring presets/configuration will OVERWRITE your current presets/configuration.
- Incorrect upload or configuration may require a factory reset or re-flashing of your ESP.
- For security reasons, passwords are not backed up. + Incorrect upload or configuration may require a factory reset or re-flashing of your ESP.
+ For security reasons, passwords are not backed up. Backup presets
Restore presets


Backup configuration
@@ -78,4 +78,4 @@ - \ No newline at end of file + From cd1c13b4b1e242e736cad086abcb7a9dcc727b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Tue, 26 Nov 2024 19:35:15 +0100 Subject: [PATCH 54/90] Fix for #4300 --- wled00/set.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/wled00/set.cpp b/wled00/set.cpp index 712e5f254..2a6fdd3fb 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -215,6 +215,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) //doInitBusses = busesChanged; // we will do that below to ensure all input data is processed // we will not bother with pre-allocating ColorOrderMappings vector + BusManager::getColorOrderMap().reset(); for (int s = 0; s < WLED_MAX_COLOR_ORDER_MAPPINGS; s++) { int offset = s < 10 ? 48 : 55; char xs[4] = "XS"; xs[2] = offset+s; xs[3] = 0; //start LED From 1a8aaa3b26feba106259b6842ad9f8998fb3233d Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Tue, 26 Nov 2024 20:32:39 +0100 Subject: [PATCH 55/90] Speed improvements, commented legacy _t trig functions - speed improvement: by default M_TWOPI is treated as a double float - directly calling sin16_t in cos_approx() saves a lot of overhead --- wled00/wled_math.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/wled00/wled_math.cpp b/wled00/wled_math.cpp index a191968e1..583381d66 100644 --- a/wled00/wled_math.cpp +++ b/wled00/wled_math.cpp @@ -10,14 +10,17 @@ //#define WLED_DEBUG_MATH -#define modd(x, y) ((x) - (int)((x) / (y)) * (y)) - -// Note: cos_t, sin_t and tan_t are very accurate but may be slow +// Note: cos_t, sin_t and tan_t are very accurate but slow // the math.h functions use several kB of flash and are to be avoided if possible // sin16_t / cos16_t are faster and much more accurate than the fastled variants // sin_approx and cos_approx are float wrappers for sin16_t/cos16_t and have an accuracy better than +/-0.0015 compared to sinf() // sin8_t / cos8_t are fastled replacements and use sin16_t / cos16_t. Slightly slower than fastled version but very accurate + +// Taylor series approximations, replaced with Bhaskara I's approximation +/* +#define modd(x, y) ((x) - (int)((x) / (y)) * (y)) + float cos_t(float phi) { float x = modd(phi, M_TWOPI); @@ -54,6 +57,7 @@ float tan_t(float x) { #endif return res; } +*/ // 16-bit, integer based Bhaskara I's sine approximation: 16*x*(pi - x) / (5*pi^2 - 4*x*(pi - x)) // input is 16bit unsigned (0-65535), output is 16bit signed (-32767 to +32767) @@ -85,17 +89,18 @@ uint8_t cos8_t(uint8_t theta) { return sin8_t(theta + 64); //cos(x) = sin(x+pi/2) } -float sin_approx(float theta) -{ - uint16_t scaled_theta = (int)(theta * (0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) +float sin_approx(float theta) { + uint16_t scaled_theta = (int)(theta * (float)(0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) int32_t result = sin16_t(scaled_theta); float sin = float(result) / 0x7FFF; return sin; } -float cos_approx(float theta) -{ - return sin_approx(theta + M_PI_2); +float cos_approx(float theta) { + uint16_t scaled_theta = (int)(theta * (float)(0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) + int32_t result = sin16_t(scaled_theta + 16384); + float cos = float(result) / 0x7FFF; + return cos; } float tan_approx(float x) { From ca176c7549f92ae6ba611b9b6f9e9edbf13bad15 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 27 Nov 2024 10:31:41 +0000 Subject: [PATCH 56/90] rename workflow ready for workflow refactor --- .github/workflows/{wled-ci.yml => build.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{wled-ci.yml => build.yml} (100%) diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/build.yml similarity index 100% rename from .github/workflows/wled-ci.yml rename to .github/workflows/build.yml From feab27295db32f9ad367ec3a68d3d7ad9b3779eb Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 27 Nov 2024 10:33:44 +0000 Subject: [PATCH 57/90] workflow refactor to used shared build file --- .github/workflows/build.yml | 8 +++++--- .github/workflows/wled-ci.yml | 11 +++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/wled-ci.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1dcab26ab..80fce38c3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,9 @@ -name: WLED CI - -on: [push, pull_request] +name: WLED Build +# Only included into other workflows +on: + workflow_call: + jobs: get_default_envs: diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/wled-ci.yml new file mode 100644 index 000000000..3c862c185 --- /dev/null +++ b/.github/workflows/wled-ci.yml @@ -0,0 +1,11 @@ +name: WLED CI + +on: + push: + branches: + - '*' + pull_request: + +jobs: + wled_build: + uses: ./.github/workflows/build.yml From 95718ab6ecb830b57f74d7cbed0b142d70b33c63 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 27 Nov 2024 10:35:04 +0000 Subject: [PATCH 58/90] Dedicated release workflow --- .github/workflows/build.yml | 16 ---------------- .github/workflows/release.yml | 28 ++++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 80fce38c3..e5fdfc5a3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,22 +64,6 @@ jobs: path: | build_output/release/*.bin build_output/release/*_ESP02*.bin.gz - release: - name: Create Release - runs-on: ubuntu-latest - needs: build - if: startsWith(github.ref, 'refs/tags/') - steps: - - uses: actions/download-artifact@v4 - with: - merge-multiple: true - - name: Create draft release - uses: softprops/action-gh-release@v1 - with: - draft: True - files: | - *.bin - *.bin.gz testCdata: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..27beec99c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,28 @@ +name: WLED Release CI + +on: + push: + tags: + - '*' + +jobs: + + wled_build: + uses: ./.github/workflows/build.yml + + release: + name: Create Release + runs-on: ubuntu-latest + needs: wled_build + steps: + - uses: actions/download-artifact@v4 + with: + merge-multiple: true + - name: Create draft release + uses: softprops/action-gh-release@v1 + with: + draft: True + files: | + *.bin + *.bin.gz + From cc55f6015dfff436cb4ff3f595ae53695393f8b3 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 27 Nov 2024 10:56:53 +0000 Subject: [PATCH 59/90] Cache always misses for tags, so save space and do not save back --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e5fdfc5a3..ac1db6445 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,6 +42,7 @@ jobs: - run: npm ci - name: Cache PlatformIO uses: actions/cache@v4 + if: !startsWith(github.ref, 'refs/tags/') with: path: | ~/.platformio/.cache From 6cbdd825eb6cea9c2cc5c6219f4fd7db567cd8ff Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 27 Nov 2024 10:59:23 +0000 Subject: [PATCH 60/90] Revert "Cache always misses for tags, so save space and do not save back" This reverts commit cc55f6015dfff436cb4ff3f595ae53695393f8b3. --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ac1db6445..e5fdfc5a3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,7 +42,6 @@ jobs: - run: npm ci - name: Cache PlatformIO uses: actions/cache@v4 - if: !startsWith(github.ref, 'refs/tags/') with: path: | ~/.platformio/.cache From acc8b9cdbc22086762d5c05e6d2ff419c96fc074 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Wed, 27 Nov 2024 09:00:25 -0500 Subject: [PATCH 61/90] BusDigital::begin: Pass clock rate argument Fixes bug introduced by #4312. --- wled00/bus_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 8281211c1..715470800 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -412,7 +412,7 @@ std::vector BusDigital::getLEDTypes() { void BusDigital::begin() { if (!_valid) return; - PolyBus::begin(_busPtr, _iType, _pins); + PolyBus::begin(_busPtr, _iType, _pins, _frequencykHz); } void BusDigital::cleanup() { From dcba1aad109c29b9594973d99270f62006dd0289 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Wed, 27 Nov 2024 09:05:10 -0500 Subject: [PATCH 62/90] PolyBus: Clarify use of clock_kHz While not used by most bus types, it's not an optional parameter. --- wled00/bus_manager.cpp | 2 +- wled00/bus_wrapper.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 715470800..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); } diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index 7e6e74d85..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 From b1dd27b516fa93919edd967c85bd8b287b9b914d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Wed, 27 Nov 2024 16:08:10 +0100 Subject: [PATCH 63/90] Fix for #4321 --- wled00/data/settings_leds.htm | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 6be5becd1..baf80a5d7 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -42,15 +42,14 @@ if (loc) d.Sf.action = getURL('/settings/leds'); } function bLimits(b,v,p,m,l,o=5,d=2,a=6) { - // maxB - max buses (can be changed if using ESP32 parallel I2S) - // maxD - max digital channels (can be changed if using ESP32 parallel I2S) - // maxA - max analog channels - // maxV - min virtual buses - // maxPB - max LEDs per bus - // maxM - max LED memory - // maxL - max LEDs (will serve to determine ESP >1664 == ESP32) - // maxCO - max Color Order mappings - oMaxB = maxB = b; maxD = d, maxA = a, maxV = v; maxM = m; maxPB = p; maxL = l; maxCO = o; + oMaxB = maxB = b; // maxB - max buses (can be changed if using ESP32 parallel I2S) + maxD = d; // maxD - max digital channels (can be changed if using ESP32 parallel I2S) + maxA = a; // maxA - max analog channels + maxV = v; // maxV - min virtual buses + maxPB = p; // maxPB - max LEDs per bus + maxM = m; // maxM - max LED memory + maxL = l; // maxL - max LEDs (will serve to determine ESP >1664 == ESP32) + maxCO = o; // maxCO - max Color Order mappings } function pinsOK() { var ok = true; From 4cd0563a9398812f65f8dbbe22d0ab48799f4de8 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Wed, 27 Nov 2024 21:53:32 +0100 Subject: [PATCH 64/90] =?UTF-8?q?changed=2090=C2=B0=20offset=20to=20hex,?= =?UTF-8?q?=20fixed=20potential=20bug=20in=20FX=20using=20sin/cos=20with?= =?UTF-8?q?=20incrementing=20number?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - sin/cos calls with incrementing numbers can lead to bad outcomes, the functions (_approx or original sinf/cosf) return bad values for very large float inputs --- wled00/FX.cpp | 5 +++-- wled00/wled_math.cpp | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 5b4513dc7..da2967a3c 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -5314,8 +5314,8 @@ uint16_t mode_2DJulia(void) { // An animated Julia set reAl = -0.94299f; // PixelBlaze example imAg = 0.3162f; - reAl += sin_t((float)strip.now/305.f)/20.f; - imAg += sin_t((float)strip.now/405.f)/20.f; + reAl += (float)sin16_t(strip.now * 34) / 655340.f; + imAg += (float)sin16_t(strip.now * 26) / 655340.f; dx = (xmax - xmin) / (cols); // Scale the delta x and y values to our matrix size. dy = (ymax - ymin) / (rows); @@ -6279,6 +6279,7 @@ uint16_t mode_2Dplasmarotozoom() { } } *a -= 0.03f + float(SEGENV.speed-128)*0.0002f; // rotation speed + if(*a < -6283.18530718f) *a += 6283.18530718f; // 1000*2*PI, protect sin/cos from very large input float values (will give wrong results) return FRAMETIME; } diff --git a/wled00/wled_math.cpp b/wled00/wled_math.cpp index 583381d66..a8ec55400 100644 --- a/wled00/wled_math.cpp +++ b/wled00/wled_math.cpp @@ -76,7 +76,7 @@ int16_t sin16_t(uint16_t theta) { } int16_t cos16_t(uint16_t theta) { - return sin16_t(theta + 16384); //cos(x) = sin(x+pi/2) + return sin16_t(theta + 0x4000); //cos(x) = sin(x+pi/2) } uint8_t sin8_t(uint8_t theta) { @@ -98,7 +98,7 @@ float sin_approx(float theta) { float cos_approx(float theta) { uint16_t scaled_theta = (int)(theta * (float)(0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) - int32_t result = sin16_t(scaled_theta + 16384); + int32_t result = sin16_t(scaled_theta + 0x4000); float cos = float(result) / 0x7FFF; return cos; } From fa4c23b76ec7843aff6a8f3e5b9bc7a46a41858e Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Wed, 27 Nov 2024 22:23:48 +0100 Subject: [PATCH 65/90] minor improvement --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index a2ceb591a..a0d080818 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -7737,9 +7737,9 @@ 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 = int(40.7436f * atan2_t((y - C_Y), (x - C_X))); // avoid 128*atan2()/PI int dx = (x - C_X); int dy = (y - C_Y); + rMap[XY(x, y)].angle = int(40.7436f * atan2_t(dy, dx)); // avoid 128*atan2()/PI rMap[XY(x, y)].radius = sqrtf(dx * dx + dy * dy) * mapp; //thanks Sutaburosu } } From 8b1d712e1e04a696086b7e5b9df06a4dff97b289 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Sun, 1 Dec 2024 13:00:37 -0500 Subject: [PATCH 66/90] settings_leds: Initialize current limiter field When adding a new bus, the numeric current limit field was not being initialized; this was causing it to save 0 when saved instead of the default 55mA value. --- wled00/data/settings_leds.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index baf80a5d7..ff5087aed 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -422,7 +422,7 @@ mA/LED:
- +
PSU: mA
Color Order: From ae8c3b02d04064cb809af2f3f10413563fae2dd7 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 2 Dec 2024 21:35:48 +0100 Subject: [PATCH 67/90] blends FX - hotfix for black pixels fixing an off-by-one error to solve #4335 --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index a0d080818..61d7a66a8 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4497,7 +4497,7 @@ uint16_t mode_blends(void) { unsigned offset = 0; for (unsigned i = 0; i < SEGLEN; i++) { SEGMENT.setPixelColor(i, pixels[offset++]); - if (offset > pixelLen) offset = 0; + if (offset >= pixelLen) offset = 0; } return FRAMETIME; From 8db8ecfef3cbbf8cd70862d856742874e2a9306f Mon Sep 17 00:00:00 2001 From: Will Miles Date: Mon, 2 Dec 2024 21:50:29 +0000 Subject: [PATCH 68/90] settings_leds: Fix quotes on LA value --- wled00/data/settings_leds.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index ff5087aed..ce9c8ceed 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -422,7 +422,7 @@ mA/LED:
- +
PSU: mA
Color Order: From d620930f10f06bce563d95c94e6513739959a012 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Mon, 2 Dec 2024 21:52:41 +0000 Subject: [PATCH 69/90] settings_leds: Remove unused variables Remove a couple of leftover variables from previous revisions. --- wled00/data/settings_leds.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index ce9c8ceed..71fec2798 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -6,7 +6,7 @@ LED Settings