diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4dad83d9b..c570ac1f7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
## WLED changelog
+#### Build 2410270
+- WLED 0.15.0-b7 release
+- Re-license the WLED project from MIT to EUPL (#4194 by @Aircoookie)
+- Fix alexa devices invisible/uncontrollable (#4214 by @Svennte)
+- Add visual expand button on hover (#4172)
+- Usermod: Audioreactive tuning and performance enhancements (by @softhack007)
+- `/json/live` (JSON live data/peek) only enabled when WebSockets are disabled
+- Various bugfixes and optimisations: #4179, #4215, #4219, #4222, #4223, #4224, #4228, #4230
+
#### Build 2410140
- WLED 0.15.0-b6 release
- Added BRT timezone (#4188 by @LuisFadini)
diff --git a/package-lock.json b/package-lock.json
index e85857017..db709485c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "wled",
- "version": "0.15.0-b6",
+ "version": "0.15.0-b7",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "wled",
- "version": "0.15.0-b6",
+ "version": "0.15.0-b7",
"license": "ISC",
"dependencies": {
"clean-css": "^5.3.3",
diff --git a/package.json b/package.json
index d76d87687..a11a13553 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "wled",
- "version": "0.15.0-b6",
+ "version": "0.15.0-b7",
"description": "Tools for WLED project",
"main": "tools/cdata.js",
"directories": {
@@ -27,5 +27,8 @@
"html-minifier-terser": "^7.2.0",
"inliner": "^1.13.1",
"nodemon": "^3.1.7"
+ },
+ "engines": {
+ "node": ">=20.0.0"
}
}
diff --git a/platformio.ini b/platformio.ini
index 3005ba220..6d4aa1dc1 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -197,6 +197,7 @@ build_flags =
; decrease code cache size and increase IRAM to fit all pixel functions
-D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48 ;; in case of linker errors like "section `.text1' will not fit in region `iram1_0_seg'"
; -D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED ;; (experimental) adds some extra heap, but may cause slowdown
+ -D NON32XFER_HANDLER ;; ask forgiveness for PROGMEM misuse
lib_deps =
#https://github.com/lorol/LITTLEFS.git
@@ -259,7 +260,8 @@ lib_deps =
https://github.com/pbolduc/AsyncTCP.git @ 1.2.0
${env.lib_deps}
# additional build flags for audioreactive
-AR_build_flags = -D USERMOD_AUDIOREACTIVE
+AR_build_flags = -D USERMOD_AUDIOREACTIVE
+ -D sqrt_internal=sqrtf ;; -fsingle-precision-constant ;; forces ArduinoFFT to use float math (2x faster)
AR_lib_deps = kosme/arduinoFFT @ 2.0.1
[esp32_idf_V4]
@@ -554,6 +556,33 @@ board_build.f_flash = 80000000L
board_build.flash_mode = qio
monitor_filters = esp32_exception_decoder
+[env:esp32S3_wroom2]
+;; For ESP32-S3 WROOM-2, a.k.a. ESP32-S3 DevKitC-1 v1.1
+;; with >= 16MB FLASH and >= 8MB PSRAM (memory_type: opi_opi)
+platform = ${esp32s3.platform}
+platform_packages = ${esp32s3.platform_packages}
+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
+ -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")
+ -DBOARD_HAS_PSRAM
+ -D LEDPIN=38 -D DATA_PINS=38 ;; buildin WS2812b LED
+ -D BTNPIN=0 -D RLYPIN=16 -D IRPIN=17 -D AUDIOPIN=-1
+ -D WLED_DEBUG
+ ${esp32.AR_build_flags}
+ -D SR_DMTYPE=1 -D I2S_SDPIN=13 -D I2S_CKPIN=14 -D I2S_WSPIN=15 -D MCLK_PIN=4 ;; I2S mic
+lib_deps = ${esp32s3.lib_deps}
+ ${esp32.AR_lib_deps}
+
+board_build.partitions = ${esp32.extreme_partitions}
+board_upload.flash_size = 16MB
+board_upload.maximum_size = 16777216
+monitor_filters = esp32_exception_decoder
+
[env:esp32s3_4M_qspi]
;; ESP32-S3, with 4MB FLASH and <= 4MB PSRAM (memory_type: qio_qspi)
board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM
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,
diff --git a/usermods/Animated_Staircase/Animated_Staircase.h b/usermods/Animated_Staircase/Animated_Staircase.h
index d1ec9bb7f..54a9b3331 100644
--- a/usermods/Animated_Staircase/Animated_Staircase.h
+++ b/usermods/Animated_Staircase/Animated_Staircase.h
@@ -425,10 +425,10 @@ class Animated_Staircase : public Usermod {
}
void appendConfigData() {
- //oappend(SET_F("dd=addDropdown('staircase','selectfield');"));
- //oappend(SET_F("addOption(dd,'1st value',0);"));
- //oappend(SET_F("addOption(dd,'2nd value',1);"));
- //oappend(SET_F("addInfo('staircase:selectfield',1,'additional info');")); // 0 is field type, 1 is actual field
+ //oappend(F("dd=addDropdown('staircase','selectfield');"));
+ //oappend(F("addOption(dd,'1st value',0);"));
+ //oappend(F("addOption(dd,'2nd value',1);"));
+ //oappend(F("addInfo('staircase:selectfield',1,'additional info');")); // 0 is field type, 1 is actual field
}
diff --git a/usermods/BME68X_v2/usermod_bme68x.h b/usermods/BME68X_v2/usermod_bme68x.h
index 8e360515a..aca24d0a2 100644
--- a/usermods/BME68X_v2/usermod_bme68x.h
+++ b/usermods/BME68X_v2/usermod_bme68x.h
@@ -767,22 +767,22 @@ void UsermodBME68X::appendConfigData() {
// snprintf_P(charbuffer, 127, PSTR("addInfo('%s:%s',1,'*) Set to minus to deactivate (all sensors)');"), UMOD_NAME, _nameTemp); oappend(charbuffer);
/* Dropdown for Celsius/Fahrenheit*/
- oappend(SET_F("dd=addDropdown('"));
+ oappend(F("dd=addDropdown('"));
oappend(UMOD_NAME);
- oappend(SET_F("','"));
+ oappend(F("','"));
oappend(_nameTempScale);
- oappend(SET_F("');"));
- oappend(SET_F("addOption(dd,'Celsius',0);"));
- oappend(SET_F("addOption(dd,'Fahrenheit',1);"));
+ oappend(F("');"));
+ oappend(F("addOption(dd,'Celsius',0);"));
+ oappend(F("addOption(dd,'Fahrenheit',1);"));
/* i²C Address*/
- oappend(SET_F("dd=addDropdown('"));
+ oappend(F("dd=addDropdown('"));
oappend(UMOD_NAME);
- oappend(SET_F("','"));
+ oappend(F("','"));
oappend(_nameI2CAdr);
- oappend(SET_F("');"));
- oappend(SET_F("addOption(dd,'0x76',0x76);"));
- oappend(SET_F("addOption(dd,'0x77',0x77);"));
+ oappend(F("');"));
+ oappend(F("addOption(dd,'0x76',0x76);"));
+ oappend(F("addOption(dd,'0x77',0x77);"));
}
/**
diff --git a/usermods/Battery/usermod_v2_Battery.h b/usermods/Battery/usermod_v2_Battery.h
index e91de850c..b36c5f4d6 100644
--- a/usermods/Battery/usermod_v2_Battery.h
+++ b/usermods/Battery/usermod_v2_Battery.h
@@ -478,29 +478,29 @@ class UsermodBattery : public Usermod
void appendConfigData()
{
// Total: 462 Bytes
- oappend(SET_F("td=addDropdown('Battery','type');")); // 34 Bytes
- oappend(SET_F("addOption(td,'Unkown','0');")); // 28 Bytes
- oappend(SET_F("addOption(td,'LiPo','1');")); // 26 Bytes
- oappend(SET_F("addOption(td,'LiOn','2');")); // 26 Bytes
- oappend(SET_F("addInfo('Battery:type',1,'requires reboot');")); // 81 Bytes
- oappend(SET_F("addInfo('Battery:min-voltage',1,'v');")); // 38 Bytes
- oappend(SET_F("addInfo('Battery:max-voltage',1,'v');")); // 38 Bytes
- oappend(SET_F("addInfo('Battery:interval',1,'ms');")); // 36 Bytes
- oappend(SET_F("addInfo('Battery:HA-discovery',1,'');")); // 38 Bytes
- oappend(SET_F("addInfo('Battery:auto-off:threshold',1,'%');")); // 45 Bytes
- oappend(SET_F("addInfo('Battery:indicator:threshold',1,'%');")); // 46 Bytes
- oappend(SET_F("addInfo('Battery:indicator:duration',1,'s');")); // 45 Bytes
+ oappend(F("td=addDropdown('Battery','type');")); // 34 Bytes
+ oappend(F("addOption(td,'Unkown','0');")); // 28 Bytes
+ oappend(F("addOption(td,'LiPo','1');")); // 26 Bytes
+ oappend(F("addOption(td,'LiOn','2');")); // 26 Bytes
+ oappend(F("addInfo('Battery:type',1,'requires reboot');")); // 81 Bytes
+ oappend(F("addInfo('Battery:min-voltage',1,'v');")); // 38 Bytes
+ oappend(F("addInfo('Battery:max-voltage',1,'v');")); // 38 Bytes
+ oappend(F("addInfo('Battery:interval',1,'ms');")); // 36 Bytes
+ oappend(F("addInfo('Battery:HA-discovery',1,'');")); // 38 Bytes
+ oappend(F("addInfo('Battery:auto-off:threshold',1,'%');")); // 45 Bytes
+ oappend(F("addInfo('Battery:indicator:threshold',1,'%');")); // 46 Bytes
+ oappend(F("addInfo('Battery:indicator:duration',1,'s');")); // 45 Bytes
// this option list would exeed the oappend() buffer
// a list of all presets to select one from
- // oappend(SET_F("bd=addDropdown('Battery:low-power-indicator', 'preset');"));
- // the loop generates: oappend(SET_F("addOption(bd, 'preset name', preset id);"));
+ // oappend(F("bd=addDropdown('Battery:low-power-indicator', 'preset');"));
+ // the loop generates: oappend(F("addOption(bd, 'preset name', preset id);"));
// for(int8_t i=1; i < 42; i++) {
- // oappend(SET_F("addOption(bd, 'Preset#"));
+ // oappend(F("addOption(bd, 'Preset#"));
// oappendi(i);
- // oappend(SET_F("',"));
+ // oappend(F("',"));
// oappendi(i);
- // oappend(SET_F(");"));
+ // oappend(F(");"));
// }
}
diff --git a/usermods/EXAMPLE_v2/usermod_v2_example.h b/usermods/EXAMPLE_v2/usermod_v2_example.h
index 3d562b585..df05f3e3d 100644
--- a/usermods/EXAMPLE_v2/usermod_v2_example.h
+++ b/usermods/EXAMPLE_v2/usermod_v2_example.h
@@ -287,11 +287,11 @@ class MyExampleUsermod : public Usermod {
*/
void appendConfigData() override
{
- oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":great")); oappend(SET_F("',1,'(this is a great config value)');"));
- oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":testString")); oappend(SET_F("',1,'enter any string you want');"));
- oappend(SET_F("dd=addDropdown('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F("','testInt');"));
- oappend(SET_F("addOption(dd,'Nothing',0);"));
- oappend(SET_F("addOption(dd,'Everything',42);"));
+ oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":great")); oappend(F("',1,'(this is a great config value)');"));
+ oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":testString")); oappend(F("',1,'enter any string you want');"));
+ oappend(F("dd=addDropdown('")); oappend(String(FPSTR(_name)).c_str()); oappend(F("','testInt');"));
+ oappend(F("addOption(dd,'Nothing',0);"));
+ oappend(F("addOption(dd,'Everything',42);"));
}
diff --git a/usermods/Internal_Temperature_v2/usermod_internal_temperature.h b/usermods/Internal_Temperature_v2/usermod_internal_temperature.h
index 2236bfeab..c24b4c628 100644
--- a/usermods/Internal_Temperature_v2/usermod_internal_temperature.h
+++ b/usermods/Internal_Temperature_v2/usermod_internal_temperature.h
@@ -149,11 +149,11 @@ public:
void appendConfigData()
{
// Display 'ms' next to the 'Loop Interval' setting
- oappend(SET_F("addInfo('Internal Temperature:Loop Interval', 1, 'ms');"));
+ oappend(F("addInfo('Internal Temperature:Loop Interval', 1, 'ms');"));
// Display '°C' next to the 'Activation Threshold' setting
- oappend(SET_F("addInfo('Internal Temperature:Activation Threshold', 1, '°C');"));
+ oappend(F("addInfo('Internal Temperature:Activation Threshold', 1, '°C');"));
// Display '0 = Disabled' next to the 'Preset To Activate' setting
- oappend(SET_F("addInfo('Internal Temperature:Preset To Activate', 1, '0 = unused');"));
+ oappend(F("addInfo('Internal Temperature:Preset To Activate', 1, '0 = unused');"));
}
bool readFromConfig(JsonObject &root)
diff --git a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
index 29070cf84..0deda181c 100644
--- a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
+++ b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
@@ -511,8 +511,8 @@ void PIRsensorSwitch::addToConfig(JsonObject &root)
void PIRsensorSwitch::appendConfigData()
{
- oappend(SET_F("addInfo('PIRsensorSwitch:HA-discovery',1,'HA=Home Assistant');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('PIRsensorSwitch:override',1,'Cancel timer on change');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('PIRsensorSwitch:HA-discovery',1,'HA=Home Assistant');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('PIRsensorSwitch:override',1,'Cancel timer on change');")); // 0 is field type, 1 is actual field
for (int i = 0; i < PIR_SENSOR_MAX_SENSORS; i++) {
char str[128];
sprintf_P(str, PSTR("addInfo('PIRsensorSwitch:pin[]',%d,'','#%d');"), i, i);
diff --git a/usermods/ST7789_display/ST7789_display.h b/usermods/ST7789_display/ST7789_display.h
index 0dbada382..65f4cae5d 100644
--- a/usermods/ST7789_display/ST7789_display.h
+++ b/usermods/ST7789_display/ST7789_display.h
@@ -377,10 +377,10 @@ class St7789DisplayUsermod : public Usermod {
void appendConfigData() override {
- oappend(SET_F("addInfo('ST7789:pin[]',0,'','SPI CS');"));
- oappend(SET_F("addInfo('ST7789:pin[]',1,'','SPI DC');"));
- oappend(SET_F("addInfo('ST7789:pin[]',2,'','SPI RST');"));
- oappend(SET_F("addInfo('ST7789:pin[]',3,'','SPI BL');"));
+ oappend(F("addInfo('ST7789:pin[]',0,'','SPI CS');"));
+ oappend(F("addInfo('ST7789:pin[]',1,'','SPI DC');"));
+ oappend(F("addInfo('ST7789:pin[]',2,'','SPI RST');"));
+ oappend(F("addInfo('ST7789:pin[]',3,'','SPI BL');"));
}
/*
diff --git a/usermods/Temperature/usermod_temperature.h b/usermods/Temperature/usermod_temperature.h
index ad755eaee..178bc05a0 100644
--- a/usermods/Temperature/usermod_temperature.h
+++ b/usermods/Temperature/usermod_temperature.h
@@ -435,10 +435,10 @@ bool UsermodTemperature::readFromConfig(JsonObject &root) {
}
void UsermodTemperature::appendConfigData() {
- oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":")); oappend(String(FPSTR(_parasite)).c_str());
- oappend(SET_F("',1,'(if no Vcc connected)');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":")); oappend(String(FPSTR(_parasitePin)).c_str());
- oappend(SET_F("',1,'(for external MOSFET)');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":")); oappend(String(FPSTR(_parasite)).c_str());
+ oappend(F("',1,'(if no Vcc connected)');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":")); oappend(String(FPSTR(_parasitePin)).c_str());
+ oappend(F("',1,'(for external MOSFET)');")); // 0 is field type, 1 is actual field
}
float UsermodTemperature::getTemperature() {
diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h
index fde7afded..ad449fc83 100644
--- a/usermods/audioreactive/audio_reactive.h
+++ b/usermods/audioreactive/audio_reactive.h
@@ -191,8 +191,8 @@ constexpr uint16_t samplesFFT_2 = 256; // meaningfull part of FFT resul
#define LOG_256 5.54517744f // log(256)
// These are the input and output vectors. Input vectors receive computed results from FFT.
-static float vReal[samplesFFT] = {0.0f}; // FFT sample inputs / freq output - these are our raw result bins
-static float vImag[samplesFFT] = {0.0f}; // imaginary parts
+static float* vReal = nullptr; // FFT sample inputs / freq output - these are our raw result bins
+static float* vImag = nullptr; // imaginary parts
// Create FFT object
// lib_deps += https://github.com/kosme/arduinoFFT#develop @ 1.9.2
@@ -200,14 +200,9 @@ static float vImag[samplesFFT] = {0.0f}; // imaginary parts
// #define FFT_SPEED_OVER_PRECISION // enables use of reciprocals (1/x etc) - not faster on ESP32
// #define FFT_SQRT_APPROXIMATION // enables "quake3" style inverse sqrt - slower on ESP32
// Below options are forcing ArduinoFFT to use sqrtf() instead of sqrt()
-#define sqrt(x) sqrtf(x) // little hack that reduces FFT time by 10-50% on ESP32
-#define sqrt_internal sqrtf // see https://github.com/kosme/arduinoFFT/pull/83
-
-#include
-
-/* Create FFT object with weighing factor storage */
-static ArduinoFFT FFT = ArduinoFFT( vReal, vImag, samplesFFT, SAMPLE_RATE, true);
+// #define sqrt_internal sqrtf // see https://github.com/kosme/arduinoFFT/pull/83 - since v2.0.0 this must be done in build_flags
+#include // FFT object is created in FFTcode
// Helper functions
// compute average of several FFT result bins
@@ -226,6 +221,18 @@ void FFTcode(void * parameter)
{
DEBUGSR_PRINT("FFT started on core: "); DEBUGSR_PRINTLN(xPortGetCoreID());
+ // allocate FFT buffers on first call
+ if (vReal == nullptr) vReal = (float*) calloc(sizeof(float), samplesFFT);
+ if (vImag == nullptr) vImag = (float*) calloc(sizeof(float), samplesFFT);
+ if ((vReal == nullptr) || (vImag == nullptr)) {
+ // something went wrong
+ if (vReal) free(vReal); vReal = nullptr;
+ if (vImag) free(vImag); vImag = nullptr;
+ return;
+ }
+ // Create FFT object with weighing factor storage
+ ArduinoFFT FFT = ArduinoFFT( vReal, vImag, samplesFFT, SAMPLE_RATE, true);
+
// see https://www.freertos.org/vtaskdelayuntil.html
const TickType_t xFrequency = FFT_MIN_CYCLE * portTICK_PERIOD_MS;
@@ -247,6 +254,7 @@ void FFTcode(void * parameter)
// get a fresh batch of samples from I2S
if (audioSource) audioSource->getSamples(vReal, samplesFFT);
+ memset(vImag, 0, samplesFFT * sizeof(float)); // set imaginary parts to 0
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
if (start < esp_timer_get_time()) { // filter out overflows
@@ -265,8 +273,6 @@ void FFTcode(void * parameter)
// find highest sample in the batch
float maxSample = 0.0f; // max sample from FFT batch
for (int i=0; i < samplesFFT; i++) {
- // set imaginary parts to 0
- vImag[i] = 0;
// pick our our current mic sample - we take the max value from all samples that go into FFT
if ((vReal[i] <= (INT16_MAX - 1024)) && (vReal[i] >= (INT16_MIN + 1024))) //skip extreme values - normally these are artefacts
if (fabsf((float)vReal[i]) > maxSample) maxSample = fabsf((float)vReal[i]);
@@ -297,7 +303,7 @@ void FFTcode(void * parameter)
#endif
} else { // noise gate closed - only clear results as FFT was skipped. MIC samples are still valid when we do this.
- memset(vReal, 0, sizeof(vReal));
+ memset(vReal, 0, samplesFFT * sizeof(float));
FFT_MajorPeak = 1;
FFT_Magnitude = 0.001;
}
@@ -1879,57 +1885,59 @@ class AudioReactive : public Usermod {
}
- void appendConfigData() override
+ void appendConfigData(Print& uiScript) override
{
-#ifdef ARDUINO_ARCH_ESP32
- oappend(SET_F("dd=addDropdown('AudioReactive','digitalmic:type');"));
+ uiScript.print(F("ux='AudioReactive';")); // ux = shortcut for Audioreactive - fingers crossed that "ux" isn't already used as JS var, html post parameter or css style
+#ifdef ARDUINO_ARCH_ESP32
+ uiScript.print(F("uxp=ux+':digitalmic:pin[]';")); // uxp = shortcut for AudioReactive:digitalmic:pin[]
+ uiScript.print(F("dd=addDropdown(ux,'digitalmic:type');"));
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
- oappend(SET_F("addOption(dd,'Generic Analog',0);"));
+ uiScript.print(F("addOption(dd,'Generic Analog',0);"));
#endif
- oappend(SET_F("addOption(dd,'Generic I2S',1);"));
- oappend(SET_F("addOption(dd,'ES7243',2);"));
- oappend(SET_F("addOption(dd,'SPH0654',3);"));
- oappend(SET_F("addOption(dd,'Generic I2S with Mclk',4);"));
+ uiScript.print(F("addOption(dd,'Generic I2S',1);"));
+ uiScript.print(F("addOption(dd,'ES7243',2);"));
+ uiScript.print(F("addOption(dd,'SPH0654',3);"));
+ uiScript.print(F("addOption(dd,'Generic I2S with Mclk',4);"));
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
- oappend(SET_F("addOption(dd,'Generic I2S PDM',5);"));
+ uiScript.print(F("addOption(dd,'Generic I2S PDM',5);"));
#endif
- oappend(SET_F("addOption(dd,'ES8388',6);"));
+ uiScript.print(F("addOption(dd,'ES8388',6);"));
- oappend(SET_F("dd=addDropdown('AudioReactive','config:AGC');"));
- oappend(SET_F("addOption(dd,'Off',0);"));
- oappend(SET_F("addOption(dd,'Normal',1);"));
- oappend(SET_F("addOption(dd,'Vivid',2);"));
- oappend(SET_F("addOption(dd,'Lazy',3);"));
+ uiScript.print(F("dd=addDropdown(ux,'config:AGC');"));
+ uiScript.print(F("addOption(dd,'Off',0);"));
+ uiScript.print(F("addOption(dd,'Normal',1);"));
+ uiScript.print(F("addOption(dd,'Vivid',2);"));
+ uiScript.print(F("addOption(dd,'Lazy',3);"));
- oappend(SET_F("dd=addDropdown('AudioReactive','dynamics:limiter');"));
- oappend(SET_F("addOption(dd,'Off',0);"));
- oappend(SET_F("addOption(dd,'On',1);"));
- oappend(SET_F("addInfo('AudioReactive:dynamics:limiter',0,' On ');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('AudioReactive:dynamics:rise',1,'ms (♪ effects only)');"));
- oappend(SET_F("addInfo('AudioReactive:dynamics:fall',1,'ms (♪ effects only)');"));
+ uiScript.print(F("dd=addDropdown(ux,'dynamics:limiter');"));
+ uiScript.print(F("addOption(dd,'Off',0);"));
+ uiScript.print(F("addOption(dd,'On',1);"));
+ uiScript.print(F("addInfo(ux+':dynamics:limiter',0,' On ');")); // 0 is field type, 1 is actual field
+ uiScript.print(F("addInfo(ux+':dynamics:rise',1,'ms (♪ effects only)');"));
+ uiScript.print(F("addInfo(ux+':dynamics:fall',1,'ms (♪ effects only)');"));
- oappend(SET_F("dd=addDropdown('AudioReactive','frequency:scale');"));
- oappend(SET_F("addOption(dd,'None',0);"));
- oappend(SET_F("addOption(dd,'Linear (Amplitude)',2);"));
- oappend(SET_F("addOption(dd,'Square Root (Energy)',3);"));
- oappend(SET_F("addOption(dd,'Logarithmic (Loudness)',1);"));
+ uiScript.print(F("dd=addDropdown(ux,'frequency:scale');"));
+ uiScript.print(F("addOption(dd,'None',0);"));
+ uiScript.print(F("addOption(dd,'Linear (Amplitude)',2);"));
+ uiScript.print(F("addOption(dd,'Square Root (Energy)',3);"));
+ uiScript.print(F("addOption(dd,'Logarithmic (Loudness)',1);"));
#endif
- oappend(SET_F("dd=addDropdown('AudioReactive','sync:mode');"));
- oappend(SET_F("addOption(dd,'Off',0);"));
+ uiScript.print(F("dd=addDropdown(ux,'sync:mode');"));
+ uiScript.print(F("addOption(dd,'Off',0);"));
#ifdef ARDUINO_ARCH_ESP32
- oappend(SET_F("addOption(dd,'Send',1);"));
+ uiScript.print(F("addOption(dd,'Send',1);"));
#endif
- oappend(SET_F("addOption(dd,'Receive',2);"));
+ uiScript.print(F("addOption(dd,'Receive',2);"));
#ifdef ARDUINO_ARCH_ESP32
- oappend(SET_F("addInfo('AudioReactive:digitalmic:type',1,'requires reboot!');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',0,'sd/data/dout','I2S SD');"));
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',1,'ws/clk/lrck','I2S WS');"));
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',2,'sck/bclk','I2S SCK');"));
+ uiScript.print(F("addInfo(ux+':digitalmic:type',1,'requires reboot!');")); // 0 is field type, 1 is actual field
+ uiScript.print(F("addInfo(uxp,0,'sd/data/dout','I2S SD');"));
+ uiScript.print(F("addInfo(uxp,1,'ws/clk/lrck','I2S WS');"));
+ uiScript.print(F("addInfo(uxp,2,'sck/bclk','I2S SCK');"));
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',3,'only use -1, 0, 1 or 3','I2S MCLK');"));
+ uiScript.print(F("addInfo(uxp,3,'only use -1, 0, 1 or 3','I2S MCLK');"));
#else
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',3,'master clock','I2S MCLK');"));
+ uiScript.print(F("addInfo(uxp,3,'master clock','I2S MCLK');"));
#endif
#endif
}
diff --git a/usermods/audioreactive/readme.md b/usermods/audioreactive/readme.md
index 4668ca881..aad269c67 100644
--- a/usermods/audioreactive/readme.md
+++ b/usermods/audioreactive/readme.md
@@ -30,7 +30,7 @@ There are however plans to create a lightweight audioreactive for the 8266, with
### using latest _arduinoFFT_ library version 2.x
The latest arduinoFFT release version should be used for audioreactive.
-* `build_flags` = `-D USERMOD_AUDIOREACTIVE`
+* `build_flags` = `-D USERMOD_AUDIOREACTIVE -D sqrt_internal=sqrtf`
* `lib_deps`= `kosme/arduinoFFT @ 2.0.1`
## Configuration
diff --git a/usermods/boblight/boblight.h b/usermods/boblight/boblight.h
index 916f7da98..b04b78fac 100644
--- a/usermods/boblight/boblight.h
+++ b/usermods/boblight/boblight.h
@@ -305,14 +305,14 @@ class BobLightUsermod : public Usermod {
}
void appendConfigData() override {
- //oappend(SET_F("dd=addDropdown('usermod','selectfield');"));
- //oappend(SET_F("addOption(dd,'1st value',0);"));
- //oappend(SET_F("addOption(dd,'2nd value',1);"));
- oappend(SET_F("addInfo('BobLight:top',1,'LEDs');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('BobLight:bottom',1,'LEDs');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('BobLight:left',1,'LEDs');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('BobLight:right',1,'LEDs');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('BobLight:pct',1,'Depth of scan [%]');")); // 0 is field type, 1 is actual field
+ //oappend(F("dd=addDropdown('usermod','selectfield');"));
+ //oappend(F("addOption(dd,'1st value',0);"));
+ //oappend(F("addOption(dd,'2nd value',1);"));
+ oappend(F("addInfo('BobLight:top',1,'LEDs');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('BobLight:bottom',1,'LEDs');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('BobLight:left',1,'LEDs');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('BobLight:right',1,'LEDs');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('BobLight:pct',1,'Depth of scan [%]');")); // 0 is field type, 1 is actual field
}
void addToConfig(JsonObject& root) override {
diff --git a/usermods/multi_relay/usermod_multi_relay.h b/usermods/multi_relay/usermod_multi_relay.h
index 33a6cf85e..c4446c7a2 100644
--- a/usermods/multi_relay/usermod_multi_relay.h
+++ b/usermods/multi_relay/usermod_multi_relay.h
@@ -264,7 +264,7 @@ void MultiRelay::handleOffTimer() {
void MultiRelay::InitHtmlAPIHandle() { // https://github.com/me-no-dev/ESPAsyncWebServer
DEBUG_PRINTLN(F("Relays: Initialize HTML API"));
- server.on(SET_F("/relays"), HTTP_GET, [this](AsyncWebServerRequest *request) {
+ server.on(F("/relays"), HTTP_GET, [this](AsyncWebServerRequest *request) {
DEBUG_PRINTLN(F("Relays: HTML API"));
String janswer;
String error = "";
@@ -765,10 +765,10 @@ void MultiRelay::addToConfig(JsonObject &root) {
}
void MultiRelay::appendConfigData() {
- oappend(SET_F("addInfo('MultiRelay:PCF8574-address',1,'(not hex!)');"));
- oappend(SET_F("addInfo('MultiRelay:broadcast-sec',1,'(MQTT message)');"));
- //oappend(SET_F("addInfo('MultiRelay:relay-0:pin',1,'(use -1 for PCF8574)');"));
- oappend(SET_F("d.extra.push({'MultiRelay':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});"));
+ oappend(F("addInfo('MultiRelay:PCF8574-address',1,'(not hex!)');"));
+ oappend(F("addInfo('MultiRelay:broadcast-sec',1,'(MQTT message)');"));
+ //oappend(F("addInfo('MultiRelay:relay-0:pin',1,'(use -1 for PCF8574)');"));
+ oappend(F("d.extra.push({'MultiRelay':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});"));
}
/**
diff --git a/usermods/pixels_dice_tray/pixels_dice_tray.h b/usermods/pixels_dice_tray/pixels_dice_tray.h
index a1e45ba33..61348ebb8 100644
--- a/usermods/pixels_dice_tray/pixels_dice_tray.h
+++ b/usermods/pixels_dice_tray/pixels_dice_tray.h
@@ -387,23 +387,23 @@ class PixelsDiceTrayUsermod : public Usermod {
// To work around this, add info text to the end of the preceding item.
//
// See addInfo in wled00/data/settings_um.htm for details on what this function does.
- oappend(SET_F(
+ oappend(F(
"addInfo('DiceTray:ble_scan_duration',1,'
Set to \"*\" to "
"connect to any die.
Leave Blank to disable.
Saving will replace \"*\" with die names.','');"));
#if USING_TFT_DISPLAY
- oappend(SET_F("ddr=addDropdown('DiceTray','rotation');"));
- oappend(SET_F("addOption(ddr,'0 deg',0);"));
- oappend(SET_F("addOption(ddr,'90 deg',1);"));
- oappend(SET_F("addOption(ddr,'180 deg',2);"));
- oappend(SET_F("addOption(ddr,'270 deg',3);"));
- oappend(SET_F(
+ oappend(F("ddr=addDropdown('DiceTray','rotation');"));
+ oappend(F("addOption(ddr,'0 deg',0);"));
+ oappend(F("addOption(ddr,'90 deg',1);"));
+ oappend(F("addOption(ddr,'180 deg',2);"));
+ oappend(F("addOption(ddr,'270 deg',3);"));
+ oappend(F(
"addInfo('DiceTray:rotation',1,'
DO NOT CHANGE "
"SPI PINS.
CHANGES ARE IGNORED.','');"));
- oappend(SET_F("addInfo('TFT:pin[]',0,'','SPI CS');"));
- oappend(SET_F("addInfo('TFT:pin[]',1,'','SPI DC');"));
- oappend(SET_F("addInfo('TFT:pin[]',2,'','SPI RST');"));
- oappend(SET_F("addInfo('TFT:pin[]',3,'','SPI BL');"));
+ oappend(F("addInfo('TFT:pin[]',0,'','SPI CS');"));
+ oappend(F("addInfo('TFT:pin[]',1,'','SPI DC');"));
+ oappend(F("addInfo('TFT:pin[]',2,'','SPI RST');"));
+ oappend(F("addInfo('TFT:pin[]',3,'','SPI BL');"));
#endif
}
diff --git a/usermods/sht/usermod_sht.h b/usermods/sht/usermod_sht.h
index c6e17221b..f10c78a25 100644
--- a/usermods/sht/usermod_sht.h
+++ b/usermods/sht/usermod_sht.h
@@ -310,22 +310,22 @@ void ShtUsermod::onMqttConnect(bool sessionPresent) {
* @return void
*/
void ShtUsermod::appendConfigData() {
- oappend(SET_F("dd=addDropdown('"));
+ oappend(F("dd=addDropdown('"));
oappend(_name);
- oappend(SET_F("','"));
+ oappend(F("','"));
oappend(_shtType);
- oappend(SET_F("');"));
- oappend(SET_F("addOption(dd,'SHT30',0);"));
- oappend(SET_F("addOption(dd,'SHT31',1);"));
- oappend(SET_F("addOption(dd,'SHT35',2);"));
- oappend(SET_F("addOption(dd,'SHT85',3);"));
- oappend(SET_F("dd=addDropdown('"));
+ oappend(F("');"));
+ oappend(F("addOption(dd,'SHT30',0);"));
+ oappend(F("addOption(dd,'SHT31',1);"));
+ oappend(F("addOption(dd,'SHT35',2);"));
+ oappend(F("addOption(dd,'SHT85',3);"));
+ oappend(F("dd=addDropdown('"));
oappend(_name);
- oappend(SET_F("','"));
+ oappend(F("','"));
oappend(_unitOfTemp);
- oappend(SET_F("');"));
- oappend(SET_F("addOption(dd,'Celsius',0);"));
- oappend(SET_F("addOption(dd,'Fahrenheit',1);"));
+ oappend(F("');"));
+ oappend(F("addOption(dd,'Celsius',0);"));
+ oappend(F("addOption(dd,'Fahrenheit',1);"));
}
/**
diff --git a/usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h b/usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h
index f712316b8..707479df1 100644
--- a/usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h
+++ b/usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h
@@ -96,7 +96,7 @@ void setup() {
jsonTransitionOnce = true;
strip.setTransition(0); //no transition
effectCurrent = FX_MODE_COLOR_WIPE;
- resetTimebase(); //make sure wipe starts from beginning
+ strip.resetTimebase(); //make sure wipe starts from beginning
//set wipe direction
Segment& seg = strip.getSegment(0);
diff --git a/usermods/stairway_wipe_basic/wled06_usermod.ino b/usermods/stairway_wipe_basic/wled06_usermod.ino
index c1264ebfb..dc2159ee9 100644
--- a/usermods/stairway_wipe_basic/wled06_usermod.ino
+++ b/usermods/stairway_wipe_basic/wled06_usermod.ino
@@ -86,7 +86,7 @@ void startWipe()
bri = briLast; //turn on
transitionDelayTemp = 0; //no transition
effectCurrent = FX_MODE_COLOR_WIPE;
- resetTimebase(); //make sure wipe starts from beginning
+ strip.resetTimebase(); //make sure wipe starts from beginning
//set wipe direction
Segment& seg = strip.getSegment(0);
diff --git a/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h b/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h
index dfab7e6ff..684dd86e4 100644
--- a/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h
+++ b/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h
@@ -1202,21 +1202,21 @@ void FourLineDisplayUsermod::onUpdateBegin(bool init) {
//}
void FourLineDisplayUsermod::appendConfigData() {
- oappend(SET_F("dd=addDropdown('4LineDisplay','type');"));
- oappend(SET_F("addOption(dd,'None',0);"));
- oappend(SET_F("addOption(dd,'SSD1306',1);"));
- oappend(SET_F("addOption(dd,'SH1106',2);"));
- oappend(SET_F("addOption(dd,'SSD1306 128x64',3);"));
- oappend(SET_F("addOption(dd,'SSD1305',4);"));
- oappend(SET_F("addOption(dd,'SSD1305 128x64',5);"));
- oappend(SET_F("addOption(dd,'SSD1309 128x64',9);"));
- oappend(SET_F("addOption(dd,'SSD1306 SPI',6);"));
- oappend(SET_F("addOption(dd,'SSD1306 SPI 128x64',7);"));
- oappend(SET_F("addOption(dd,'SSD1309 SPI 128x64',8);"));
- oappend(SET_F("addInfo('4LineDisplay:type',1,'
Change may require reboot','');"));
- oappend(SET_F("addInfo('4LineDisplay:pin[]',0,'','SPI CS');"));
- oappend(SET_F("addInfo('4LineDisplay:pin[]',1,'','SPI DC');"));
- oappend(SET_F("addInfo('4LineDisplay:pin[]',2,'','SPI RST');"));
+ oappend(F("dd=addDropdown('4LineDisplay','type');"));
+ oappend(F("addOption(dd,'None',0);"));
+ oappend(F("addOption(dd,'SSD1306',1);"));
+ oappend(F("addOption(dd,'SH1106',2);"));
+ oappend(F("addOption(dd,'SSD1306 128x64',3);"));
+ oappend(F("addOption(dd,'SSD1305',4);"));
+ oappend(F("addOption(dd,'SSD1305 128x64',5);"));
+ oappend(F("addOption(dd,'SSD1309 128x64',9);"));
+ oappend(F("addOption(dd,'SSD1306 SPI',6);"));
+ oappend(F("addOption(dd,'SSD1306 SPI 128x64',7);"));
+ oappend(F("addOption(dd,'SSD1309 SPI 128x64',8);"));
+ oappend(F("addInfo('4LineDisplay:type',1,'
Change may require reboot','');"));
+ oappend(F("addInfo('4LineDisplay:pin[]',0,'','SPI CS');"));
+ oappend(F("addInfo('4LineDisplay:pin[]',1,'','SPI DC');"));
+ oappend(F("addInfo('4LineDisplay:pin[]',2,'','SPI RST');"));
}
/*
diff --git a/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h b/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h
index 55715b7c7..383c1193e 100644
--- a/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h
+++ b/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h
@@ -1090,8 +1090,8 @@ void RotaryEncoderUIUsermod::addToConfig(JsonObject &root) {
}
void RotaryEncoderUIUsermod::appendConfigData() {
- oappend(SET_F("addInfo('Rotary-Encoder:PCF8574-address',1,'(not hex!)');"));
- oappend(SET_F("d.extra.push({'Rotary-Encoder':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});"));
+ oappend(F("addInfo('Rotary-Encoder:PCF8574-address',1,'(not hex!)');"));
+ oappend(F("d.extra.push({'Rotary-Encoder':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});"));
}
/**
diff --git a/usermods/usermod_v2_word_clock/usermod_v2_word_clock.h b/usermods/usermod_v2_word_clock/usermod_v2_word_clock.h
index b66be290a..7ecec08e5 100644
--- a/usermods/usermod_v2_word_clock/usermod_v2_word_clock.h
+++ b/usermods/usermod_v2_word_clock/usermod_v2_word_clock.h
@@ -433,8 +433,8 @@ class WordClockUsermod : public Usermod
void appendConfigData()
{
- oappend(SET_F("addInfo('WordClockUsermod:ledOffset', 1, 'Number of LEDs before the letters');"));
- oappend(SET_F("addInfo('WordClockUsermod:Norddeutsch', 1, 'Viertel vor instead of Dreiviertel');"));
+ oappend(F("addInfo('WordClockUsermod:ledOffset', 1, 'Number of LEDs before the letters');"));
+ oappend(F("addInfo('WordClockUsermod:Norddeutsch', 1, 'Viertel vor instead of Dreiviertel');"));
}
/*
diff --git a/usermods/wireguard/wireguard.h b/usermods/wireguard/wireguard.h
index 8c88d0001..8656a704a 100644
--- a/usermods/wireguard/wireguard.h
+++ b/usermods/wireguard/wireguard.h
@@ -54,13 +54,13 @@ class WireguardUsermod : public Usermod {
}
void appendConfigData() {
- oappend(SET_F("addInfo('WireGuard:host',1,'Server Hostname');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:port',1,'Server Port');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:ip',1,'Device IP');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:psk',1,'Pre Shared Key (optional)');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:pem',1,'Private Key');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:pub',1,'Public Key');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('WireGuard:tz',1,'POSIX timezone string');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('WireGuard:host',1,'Server Hostname');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('WireGuard:port',1,'Server Port');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('WireGuard:ip',1,'Device IP');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('WireGuard:psk',1,'Pre Shared Key (optional)');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('WireGuard:pem',1,'Private Key');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('WireGuard:pub',1,'Public Key');")); // 0 is field type, 1 is actual field
+ oappend(F("addInfo('WireGuard:tz',1,'POSIX timezone string');")); // 0 is field type, 1 is actual field
}
void addToConfig(JsonObject& root) {
diff --git a/wled00/FX.cpp b/wled00/FX.cpp
index d4b83de6c..2f24f745a 100644
--- a/wled00/FX.cpp
+++ b/wled00/FX.cpp
@@ -2506,9 +2506,9 @@ static uint16_t ripple_base() {
#endif
{
int left = rippleorigin - propI -1;
- int right = rippleorigin + propI +3;
+ int right = rippleorigin + propI +2;
for (int v = 0; v < 4; v++) {
- unsigned mag = scale8(cubicwave8((propF>>2)+(v-left)*64), amp);
+ unsigned mag = scale8(cubicwave8((propF>>2) + v * 64), amp);
SEGMENT.setPixelColor(left + v, color_blend(SEGMENT.getPixelColor(left + v), col, mag)); // TODO
SEGMENT.setPixelColor(right - v, color_blend(SEGMENT.getPixelColor(right - v), col, mag)); // TODO
}
diff --git a/wled00/FX.h b/wled00/FX.h
index 385c52476..545161546 100644
--- a/wled00/FX.h
+++ b/wled00/FX.h
@@ -47,6 +47,15 @@
#define FRAMETIME_FIXED (1000/WLED_FPS)
#define FRAMETIME strip.getFrameTime()
+// FPS calculation (can be defined as compile flag for debugging)
+#ifndef FPS_CALC_AVG
+#define FPS_CALC_AVG 7 // average FPS calculation over this many frames (moving average)
+#endif
+#ifndef FPS_MULTIPLIER
+#define FPS_MULTIPLIER 1 // dev option: multiplier to get sub-frame FPS without floats
+#endif
+#define FPS_CALC_SHIFT 7 // bit shift for fixed point math
+
/* each segment uses 82 bytes of SRAM memory, so if you're application fails because of
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
#ifdef ESP8266
@@ -525,12 +534,12 @@ typedef struct Segment {
inline static const CRGBPalette16 &getCurrentPalette() { return Segment::_currentPalette; }
void setUp(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1);
- bool setColor(uint8_t slot, uint32_t c); //returns true if changed
- void setCCT(uint16_t k);
- void setOpacity(uint8_t o);
- void setOption(uint8_t n, bool val);
- void setMode(uint8_t fx, bool loadDefaults = false);
- void setPalette(uint8_t pal);
+ Segment &setColor(uint8_t slot, uint32_t c);
+ Segment &setCCT(uint16_t k);
+ Segment &setOpacity(uint8_t o);
+ Segment &setOption(uint8_t n, bool val);
+ Segment &setMode(uint8_t fx, bool loadDefaults = false);
+ Segment &setPalette(uint8_t pal);
uint8_t differs(Segment& b) const;
void refreshLightCapabilities();
@@ -545,7 +554,7 @@ typedef struct Segment {
* Call resetIfRequired before calling the next effect function.
* Safe to call from interrupts and network requests.
*/
- inline void markForReset() { reset = true; } // setOption(SEG_OPTION_RESET, true)
+ inline Segment &markForReset() { reset = true; return *this; } // setOption(SEG_OPTION_RESET, true)
// transition functions
void startTransition(uint16_t dur); // transition has to start before actual segment values change
@@ -599,9 +608,15 @@ typedef struct Segment {
}
// 2D matrix
- [[gnu::hot]] uint16_t virtualWidth() const; // segment width in virtual pixels (accounts for groupping and spacing)
- [[gnu::hot]] uint16_t virtualHeight() const; // segment height in virtual pixels (accounts for groupping and spacing)
- uint16_t nrOfVStrips() const; // returns number of virtual vertical strips in 2D matrix (used to expand 1D effects into 2D)
+ [[gnu::hot]] unsigned virtualWidth() const; // segment width in virtual pixels (accounts for groupping and spacing)
+ [[gnu::hot]] unsigned virtualHeight() const; // segment height in virtual pixels (accounts for groupping and spacing)
+ inline unsigned nrOfVStrips() const { // returns number of virtual vertical strips in 2D matrix (used to expand 1D effects into 2D)
+ #ifndef WLED_DISABLE_2D
+ return (is2D() && map1D2D == M12_pBar) ? virtualWidth() : 1;
+ #else
+ return 1;
+ #endif
+ }
#ifndef WLED_DISABLE_2D
[[gnu::hot]] uint16_t XY(int x, int y); // support function to get relative index within segment
[[gnu::hot]] void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
@@ -723,7 +738,7 @@ class WS2812FX { // 96 bytes
_transitionDur(750),
_targetFps(WLED_FPS),
_frametime(FRAMETIME_FIXED),
- _cumulativeFps(2),
+ _cumulativeFps(50 << FPS_CALC_SHIFT),
_isServicing(false),
_isOffRefreshRequired(false),
_hasWhiteChannel(false),
@@ -778,7 +793,8 @@ class WS2812FX { // 96 bytes
setTargetFps(uint8_t fps),
setupEffectData(); // add default effects to the list; defined in FX.cpp
- inline void restartRuntime() { for (Segment &seg : _segments) seg.markForReset(); }
+ inline void resetTimebase() { timebase = 0UL - millis(); }
+ inline void restartRuntime() { for (Segment &seg : _segments) { seg.markForReset().resetIfRequired(); } }
inline void setTransitionMode(bool t) { for (Segment &seg : _segments) seg.startTransition(t ? _transitionDur : 0); }
inline void setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setColor(slot, RGBW32(r,g,b,w)); }
inline void setPixelColor(unsigned n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); }
@@ -834,10 +850,8 @@ class WS2812FX { // 96 bytes
inline uint16_t getLength() const { return _length; } // returns actual amount of LEDs on a strip (2D matrix may have less LEDs than W*H)
inline uint16_t getTransition() const { return _transitionDur; } // returns currently set transition time (in ms)
- uint32_t
- now,
- timebase,
- getPixelColor(uint16_t) const;
+ unsigned long now, timebase;
+ uint32_t getPixelColor(unsigned) const;
inline uint32_t getLastShow() const { return _lastShow; } // returns millis() timestamp of last strip.show() call
inline uint32_t segColor(uint8_t i) const { return _colors_t[i]; } // returns currently valid color (for slot i) AKA SEGCOLOR(); may be blended between two colors while in transition
diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp
index e38602ebc..7c1ae366b 100644
--- a/wled00/FX_2Dfcn.cpp
+++ b/wled00/FX_2Dfcn.cpp
@@ -156,7 +156,7 @@ uint16_t IRAM_ATTR_YN Segment::XY(int x, int y)
void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col)
{
if (!isActive()) return; // not active
- if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
+ if ((unsigned)x >= virtualWidth() || (unsigned)y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
uint8_t _bri_t = currentBri();
if (_bri_t < 255) {
@@ -251,7 +251,7 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
// returns RGBW values of pixel
uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const {
if (!isActive()) return 0; // not active
- if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit
+ if ((unsigned)x >= virtualWidth() || (unsigned)y >= virtualHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit
if (reverse ) x = virtualWidth() - x - 1;
if (reverse_y) y = virtualHeight() - y - 1;
if (transpose) { std::swap(x,y); } // swap X & Y if segment transposed
diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp
index 79189ef57..e706f2b43 100644
--- a/wled00/FX_fcn.cpp
+++ b/wled00/FX_fcn.cpp
@@ -509,46 +509,53 @@ void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t
}
-bool Segment::setColor(uint8_t slot, uint32_t c) { //returns true if changed
- if (slot >= NUM_COLORS || c == colors[slot]) return false;
+Segment &Segment::setColor(uint8_t slot, uint32_t c) {
+ if (slot >= NUM_COLORS || c == colors[slot]) return *this;
if (!_isRGB && !_hasW) {
- if (slot == 0 && c == BLACK) return false; // on/off segment cannot have primary color black
- if (slot == 1 && c != BLACK) return false; // on/off segment cannot have secondary color non black
+ if (slot == 0 && c == BLACK) return *this; // on/off segment cannot have primary color black
+ if (slot == 1 && c != BLACK) return *this; // on/off segment cannot have secondary color non black
}
if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change
colors[slot] = c;
stateChanged = true; // send UDP/WS broadcast
- return true;
+ return *this;
}
-void Segment::setCCT(uint16_t k) {
+Segment &Segment::setCCT(uint16_t k) {
if (k > 255) { //kelvin value, convert to 0-255
if (k < 1900) k = 1900;
if (k > 10091) k = 10091;
k = (k - 1900) >> 5;
}
- if (cct == k) return;
- if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change
- cct = k;
- stateChanged = true; // send UDP/WS broadcast
+ if (cct != k) {
+ //DEBUGFX_PRINTF_P(PSTR("- Starting CCT transition: %d\n"), k);
+ startTransition(strip.getTransition()); // start transition prior to change
+ cct = k;
+ stateChanged = true; // send UDP/WS broadcast
+ }
+ return *this;
}
-void Segment::setOpacity(uint8_t o) {
- if (opacity == o) return;
- if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change
- opacity = o;
- stateChanged = true; // send UDP/WS broadcast
+Segment &Segment::setOpacity(uint8_t o) {
+ if (opacity != o) {
+ //DEBUGFX_PRINTF_P(PSTR("- Starting opacity transition: %d\n"), o);
+ startTransition(strip.getTransition()); // start transition prior to change
+ opacity = o;
+ stateChanged = true; // send UDP/WS broadcast
+ }
+ return *this;
}
-void Segment::setOption(uint8_t n, bool val) {
+Segment &Segment::setOption(uint8_t n, bool val) {
bool prevOn = on;
if (fadeTransition && n == SEG_OPTION_ON && val != prevOn) startTransition(strip.getTransition()); // start transition prior to change
if (val) options |= 0x01 << n;
else options &= ~(0x01 << n);
if (!(n == SEG_OPTION_SELECTED || n == SEG_OPTION_RESET)) stateChanged = true; // send UDP/WS broadcast
+ return *this;
}
-void Segment::setMode(uint8_t fx, bool loadDefaults) {
+Segment &Segment::setMode(uint8_t fx, bool loadDefaults) {
// skip reserved
while (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4) == 0) fx++;
if (fx >= strip.getModeCount()) fx = 0; // set solid mode
@@ -580,9 +587,10 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
markForReset();
stateChanged = true; // send UDP/WS broadcast
}
+ return *this;
}
-void Segment::setPalette(uint8_t pal) {
+Segment &Segment::setPalette(uint8_t pal) {
if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes
if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // custom palettes
if (pal != palette) {
@@ -590,37 +598,24 @@ void Segment::setPalette(uint8_t pal) {
palette = pal;
stateChanged = true; // send UDP/WS broadcast
}
+ return *this;
}
// 2D matrix
-uint16_t IRAM_ATTR Segment::virtualWidth() const {
+unsigned IRAM_ATTR Segment::virtualWidth() const {
unsigned groupLen = groupLength();
unsigned vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen;
if (mirror) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED
return vWidth;
}
-uint16_t IRAM_ATTR Segment::virtualHeight() const {
+unsigned IRAM_ATTR Segment::virtualHeight() const {
unsigned groupLen = groupLength();
unsigned vHeight = ((transpose ? width() : height()) + groupLen - 1) / groupLen;
if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
return vHeight;
}
-uint16_t IRAM_ATTR_YN Segment::nrOfVStrips() const {
- unsigned vLen = 1;
-#ifndef WLED_DISABLE_2D
- if (is2D()) {
- switch (map1D2D) {
- case M12_pBar:
- vLen = virtualWidth();
- break;
- }
- }
-#endif
- return vLen;
-}
-
// Constants for mapping mode "Pinwheel"
#ifndef WLED_DISABLE_2D
constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16
@@ -1187,10 +1182,7 @@ uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_
//do not call this method from system context (network callback)
void WS2812FX::finalizeInit() {
//reset segment runtimes
- for (segment &seg : _segments) {
- seg.markForReset();
- seg.resetIfRequired();
- }
+ restartRuntime();
// for the lack of better place enumerate ledmaps here
// if we do it in json.cpp (serializeInfo()) we are getting flashes on LEDs
@@ -1337,7 +1329,7 @@ void WS2812FX::service() {
if (nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC))
{
doShow = true;
- unsigned delay = FRAMETIME;
+ unsigned frameDelay = FRAMETIME;
if (!seg.freeze) { //only run effect function if not frozen
int oldCCT = BusManager::getSegmentCCT(); // store original CCT value (actually it is not Segment based)
@@ -1357,7 +1349,7 @@ void WS2812FX::service() {
// overwritten by later effect. To enable seamless blending for every effect, additional LED buffer
// would need to be allocated for each effect and then blended together for each pixel.
[[maybe_unused]] uint8_t tmpMode = seg.currentMode(); // this will return old mode while in transition
- delay = (*_mode[seg.mode])(); // run new/current mode
+ frameDelay = (*_mode[seg.mode])(); // run new/current mode
#ifndef WLED_DISABLE_MODE_BLEND
if (modeBlending && seg.mode != tmpMode) {
Segment::tmpsegd_t _tmpSegData;
@@ -1366,16 +1358,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++;
}
@@ -1402,7 +1394,7 @@ void IRAM_ATTR WS2812FX::setPixelColor(unsigned i, uint32_t col) {
BusManager::setPixelColor(i, col);
}
-uint32_t IRAM_ATTR WS2812FX::getPixelColor(uint16_t i) const {
+uint32_t IRAM_ATTR WS2812FX::getPixelColor(unsigned i) const {
i = getMappedPixelIndex(i);
if (i >= _length) return 0;
return BusManager::getPixelColor(i);
@@ -1420,10 +1412,12 @@ void WS2812FX::show() {
unsigned long showNow = millis();
size_t diff = showNow - _lastShow;
- size_t fpsCurr = 200;
- if (diff > 0) fpsCurr = 1000 / diff;
- _cumulativeFps = (3 * _cumulativeFps + fpsCurr +2) >> 2; // "+2" for proper rounding (2/4 = 0.5)
- _lastShow = showNow;
+
+ if (diff > 0) { // skip calculation if no time has passed
+ size_t fpsCurr = (1000 << FPS_CALC_SHIFT) / diff; // fixed point math
+ _cumulativeFps = (FPS_CALC_AVG * _cumulativeFps + fpsCurr + FPS_CALC_AVG / 2) / (FPS_CALC_AVG + 1); // "+FPS_CALC_AVG/2" for proper rounding
+ _lastShow = showNow;
+ }
}
/**
@@ -1440,7 +1434,7 @@ bool WS2812FX::isUpdating() const {
*/
uint16_t WS2812FX::getFps() const {
if (millis() - _lastShow > 2000) return 0;
- return _cumulativeFps +1;
+ return (FPS_MULTIPLIER * _cumulativeFps) >> FPS_CALC_SHIFT; // _cumulativeFps is stored in fixed point
}
void WS2812FX::setTargetFps(uint8_t fps) {
diff --git a/wled00/button.cpp b/wled00/button.cpp
index f02ed3d6d..4d6f954f6 100644
--- a/wled00/button.cpp
+++ b/wled00/button.cpp
@@ -215,6 +215,7 @@ void handleAnalog(uint8_t b)
briLast = bri;
bri = 0;
} else {
+ if (bri == 0) strip.restartRuntime();
bri = aRead;
}
} else if (macroDoublePress[b] == 249) {
diff --git a/wled00/const.h b/wled00/const.h
index 14ec23b58..07873deca 100644
--- a/wled00/const.h
+++ b/wled00/const.h
@@ -53,7 +53,7 @@
#else
#define WLED_MAX_ANALOG_CHANNELS (LEDC_CHANNEL_MAX*LEDC_SPEED_MODE_MAX)
#if defined(CONFIG_IDF_TARGET_ESP32C3) // 2 RMT, 6 LEDC, only has 1 I2S but NPB does not support it ATM
- #define WLED_MAX_BUSSES 4 // will allow 2 digital & 2 analog RGB
+ #define WLED_MAX_BUSSES 6 // will allow 2 digital & 2 analog RGB or 6 PWM white
#define WLED_MAX_DIGITAL_CHANNELS 2
//#define WLED_MAX_ANALOG_CHANNELS 6
#define WLED_MIN_VIRTUAL_BUSSES 3
diff --git a/wled00/data/index.css b/wled00/data/index.css
index 2ae17ffe5..31e2daa92 100644
--- a/wled00/data/index.css
+++ b/wled00/data/index.css
@@ -1041,7 +1041,7 @@ textarea {
.segname .flr, .pname .flr {
transform: rotate(0deg);
- right: -6px;
+ /*right: -6px;*/
}
/* segment power wrapper */
@@ -1344,6 +1344,11 @@ TD .checkmark, TD .radiomark {
box-shadow: 0 0 10px 4px var(--c-1);
}
+.lstI .flr:hover {
+ background: var(--c-6);
+ border-radius: 100%;
+}
+
#pcont .selected:not([class*="expanded"]) {
bottom: 52px;
top: 42px;
diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h
index 71b00599c..1855a8b63 100644
--- a/wled00/fcn_declare.h
+++ b/wled00/fcn_declare.h
@@ -169,7 +169,6 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient = 0);
void setValuesFromSegment(uint8_t s);
void setValuesFromMainSeg();
void setValuesFromFirstSelectedSeg();
-void resetTimebase();
void toggleOnOff();
void applyBri();
void applyFinalBri();
@@ -324,6 +323,10 @@ class Usermod {
protected:
// Shim for oappend(), which used to exist in utils.cpp
template static inline void oappend(const T& t) { oappend_shim->print(t); };
+#ifdef ESP8266
+ // Handle print(PSTR()) without crashing by detecting PROGMEM strings
+ static void oappend(const char* c) { if ((intptr_t) c >= 0x40000000) oappend_shim->print(FPSTR(c)); else oappend_shim->print(c); };
+#endif
};
class UsermodManager {
diff --git a/wled00/json.cpp b/wled00/json.cpp
index 06eb3015e..288059653 100644
--- a/wled00/json.cpp
+++ b/wled00/json.cpp
@@ -346,7 +346,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
}
}
- int tr = -1;
+ long tr = -1;
if (!presetId || currentPlaylist < 0) { //do not apply transition time from preset if playlist active, as it would override playlist transition times
tr = root[F("transition")] | -1;
if (tr >= 0) {
@@ -363,7 +363,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
}
tr = root[F("tb")] | -1;
- if (tr >= 0) strip.timebase = ((uint32_t)tr) - millis();
+ if (tr >= 0) strip.timebase = (unsigned long)tr - millis();
JsonObject nl = root["nl"];
nightlightActive = getBoolVal(nl["on"], nightlightActive);
diff --git a/wled00/led.cpp b/wled00/led.cpp
index 9de0495b4..9b97091e6 100644
--- a/wled00/led.cpp
+++ b/wled00/led.cpp
@@ -47,17 +47,12 @@ void applyValuesToSelectedSegs()
}
-void resetTimebase()
-{
- strip.timebase = 0 - millis();
-}
-
-
void toggleOnOff()
{
if (bri == 0)
{
bri = briLast;
+ strip.restartRuntime();
} else
{
briLast = bri;
@@ -122,7 +117,7 @@ void stateUpdated(byte callMode) {
nightlightStartTime = millis();
}
if (briT == 0) {
- if (callMode != CALL_MODE_NOTIFICATION) resetTimebase(); //effect start from beginning
+ if (callMode != CALL_MODE_NOTIFICATION) strip.resetTimebase(); //effect start from beginning
}
if (bri > 0) briLast = bri;
diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp
index 793b5440c..0d4c2ad5c 100644
--- a/wled00/pin_manager.cpp
+++ b/wled00/pin_manager.cpp
@@ -201,7 +201,12 @@ bool PinManager::isPinOk(byte gpio, bool output)
if (gpio > 18 && gpio < 21) return false; // 19 + 20 = USB-JTAG. Not recommended for other uses.
#endif
if (gpio > 21 && gpio < 33) return false; // 22 to 32: not connected + SPI FLASH
- if (gpio > 32 && gpio < 38) return !psramFound(); // 33 to 37: not available if using _octal_ SPI Flash or _octal_ PSRAM
+ #if CONFIG_ESPTOOLPY_FLASHMODE_OPI // 33-37: never available if using _octal_ Flash (opi_opi)
+ if (gpio > 32 && gpio < 38) return false;
+ #endif
+ #if CONFIG_SPIRAM_MODE_OCT // 33-37: not available if using _octal_ PSRAM (qio_opi), but free to use on _quad_ PSRAM (qio_qspi)
+ if (gpio > 32 && gpio < 38) return !psramFound();
+ #endif
// 38 to 48 are for general use. Be careful about straping pins GPIO45 and GPIO46 - these may be pull-up or pulled-down on your board.
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
// strapping pins: 0, 45 & 46
diff --git a/wled00/presets.cpp b/wled00/presets.cpp
index 20edfd91e..04474113d 100644
--- a/wled00/presets.cpp
+++ b/wled00/presets.cpp
@@ -143,6 +143,7 @@ void applyPresetWithFallback(uint8_t index, uint8_t callMode, uint8_t effectID,
void handlePresets()
{
+ byte presetErrFlag = ERR_NONE;
if (presetToSave) {
strip.suspend();
doSaveState();
@@ -166,14 +167,16 @@ void handlePresets()
#ifdef ARDUINO_ARCH_ESP32
if (tmpPreset==255 && tmpRAMbuffer!=nullptr) {
deserializeJson(*pDoc,tmpRAMbuffer);
- errorFlag = ERR_NONE;
} else
#endif
{
- errorFlag = readObjectFromFileUsingId(getPresetsFileName(tmpPreset < 255), tmpPreset, pDoc) ? ERR_NONE : ERR_FS_PLOAD;
+ presetErrFlag = readObjectFromFileUsingId(getPresetsFileName(tmpPreset < 255), tmpPreset, pDoc) ? ERR_NONE : ERR_FS_PLOAD;
}
fdo = pDoc->as();
+ // only reset errorflag if previous error was preset-related
+ if ((errorFlag == ERR_NONE) || (errorFlag == ERR_FS_PLOAD)) errorFlag = presetErrFlag;
+
//HTTP API commands
const char* httpwin = fdo["win"];
if (httpwin) {
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);
diff --git a/wled00/src/dependencies/espalexa/Espalexa.h b/wled00/src/dependencies/espalexa/Espalexa.h
index 5c780e248..ae761e9fa 100644
--- a/wled00/src/dependencies/espalexa/Espalexa.h
+++ b/wled00/src/dependencies/espalexa/Espalexa.h
@@ -120,10 +120,8 @@ private:
void encodeLightId(uint8_t idx, char* out)
{
- uint8_t mac[6];
- WiFi.macAddress(mac);
-
- sprintf_P(out, PSTR("%02X:%02X:%02X:%02X:%02X:%02X:00:11-%02X"), mac[0],mac[1],mac[2],mac[3],mac[4],mac[5], idx);
+ String mymac = WiFi.macAddress();
+ sprintf_P(out, PSTR("%02X:%s:AB-%02X"), idx, mymac.c_str(), idx);
}
// construct 'globally unique' Json dict key fitting into signed int
diff --git a/wled00/wled.cpp b/wled00/wled.cpp
index 13d43218a..d6a39a399 100644
--- a/wled00/wled.cpp
+++ b/wled00/wled.cpp
@@ -380,6 +380,12 @@ void WLED::setup()
case FM_QOUT: DEBUG_PRINT(F("(QOUT)"));break;
case FM_DIO: DEBUG_PRINT(F("(DIO)")); break;
case FM_DOUT: DEBUG_PRINT(F("(DOUT)"));break;
+ #if defined(CONFIG_IDF_TARGET_ESP32S3) && CONFIG_ESPTOOLPY_FLASHMODE_OPI
+ case FM_FAST_READ: DEBUG_PRINT(F("(OPI)")); break;
+ #else
+ case FM_FAST_READ: DEBUG_PRINT(F("(fast_read)")); break;
+ #endif
+ case FM_SLOW_READ: DEBUG_PRINT(F("(slow_read)")); break;
default: break;
}
#endif
diff --git a/wled00/wled.h b/wled00/wled.h
index bc525cd6f..2b3a77d24 100644
--- a/wled00/wled.h
+++ b/wled00/wled.h
@@ -3,12 +3,12 @@
/*
Main sketch, global variable declarations
@title WLED project sketch
- @version 0.15.0-b6
+ @version 0.15.0-b7
@author Christian Schwinne
*/
// version code in format yymmddb (b = daily build)
-#define VERSION 2410140
+#define VERSION 2410270
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG
@@ -36,12 +36,13 @@
#undef WLED_ENABLE_ADALIGHT // disable has priority over enable
#endif
//#define WLED_ENABLE_DMX // uses 3.5kb
-//#define WLED_ENABLE_JSONLIVE // peek LED output via /json/live (WS binary peek is always enabled)
#ifndef WLED_DISABLE_LOXONE
#define WLED_ENABLE_LOXONE // uses 1.2kb
#endif
#ifndef WLED_DISABLE_WEBSOCKETS
#define WLED_ENABLE_WEBSOCKETS
+#else
+ #define WLED_ENABLE_JSONLIVE // peek LED output via /json/live (WS binary peek is always enabled)
#endif
//#define WLED_DISABLE_ESPNOW // Removes dependence on esp now
diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp
index 958b51330..e8cbb41ae 100644
--- a/wled00/wled_server.cpp
+++ b/wled00/wled_server.cpp
@@ -193,12 +193,12 @@ void createEditHandler(bool enable) {
editHandler = &server.addHandler(new SPIFFSEditor("","",WLED_FS));//http_username,http_password));
#endif
#else
- editHandler = &server.on(SET_F("/edit"), HTTP_GET, [](AsyncWebServerRequest *request){
+ editHandler = &server.on(F("/edit"), HTTP_GET, [](AsyncWebServerRequest *request){
serveMessage(request, 501, FPSTR(s_notimplemented), F("The FS editor is disabled in this build."), 254);
});
#endif
} else {
- editHandler = &server.on(SET_F("/edit"), HTTP_ANY, [](AsyncWebServerRequest *request){
+ editHandler = &server.on(F("/edit"), HTTP_ANY, [](AsyncWebServerRequest *request){
serveMessage(request, 401, FPSTR(s_accessdenied), FPSTR(s_unlock_cfg), 254);
});
}
@@ -427,11 +427,11 @@ void initServer()
#ifdef WLED_ENABLE_DMX
- server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){
+ server.on(F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, FPSTR(CONTENT_TYPE_HTML), PAGE_dmxmap , dmxProcessor);
});
#else
- server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){
+ server.on(F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){
serveMessage(request, 501, FPSTR(s_notimplemented), F("DMX support is not enabled in this build."), 254);
});
#endif
diff --git a/wled00/xml.cpp b/wled00/xml.cpp
index 1ac22c9ce..dc2673271 100644
--- a/wled00/xml.cpp
+++ b/wled00/xml.cpp
@@ -227,7 +227,7 @@ void getSettingsJS(byte subPage, Print& settingsScript)
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
- if (Network.isEthernet()) strcat_P(s ,SET_F(" (Ethernet)"));
+ if (Network.isEthernet()) strcat_P(s ,PSTR(" (Ethernet)"));
#endif
printSetClassElementHTML(settingsScript,PSTR("sip"),0,s);
} else
@@ -501,7 +501,7 @@ void getSettingsJS(byte subPage, Print& settingsScript)
#endif
printSetFormValue(settingsScript,PSTR("BD"),serialBaud);
#ifndef WLED_ENABLE_ADALIGHT
- settingsScript.print(F("toggle('Serial);"));
+ settingsScript.print(F("toggle('Serial');"));
#endif
}