diff --git a/platformio.ini b/platformio.ini
index 01ed902001..fe585449cf 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -198,6 +198,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
@@ -260,7 +261,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]
diff --git a/usermods/Animated_Staircase/Animated_Staircase.h b/usermods/Animated_Staircase/Animated_Staircase.h
index d1ec9bb7f6..54a9b3331e 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 8e360515a2..aca24d0a29 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 e91de850c2..b36c5f4d60 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 3d562b5857..df05f3e3dc 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 2236bfeaba..c24b4c6288 100644
--- a/usermods/Internal_Temperature_v2/usermod_internal_temperature.h
+++ b/usermods/Internal_Temperature_v2/usermod_internal_temperature.h
@@ -149,11 +149,11 @@ class InternalTemperatureUsermod : public Usermod
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 29070cf84e..0deda181c2 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 0dbada382f..65f4cae5d3 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 ad755eaeec..178bc05a0d 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 fde7afded0..ad449fc83a 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);"));
-
- 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)');"));
-
- 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,'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);"));
+
+ 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)');"));
+
+ 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 4668ca8814..aad269c675 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 916f7da988..b04b78fac7 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 33a6cf85e2..c4446c7a20 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 a1e45ba33b..61348ebb8e 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 c6e17221be..f10c78a251 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/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 dfab7e6ffb..684dd86e46 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 55715b7c76..383c1193eb 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 b66be290a5..7ecec08e59 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 8c88d00018..8656a704af 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/fcn_declare.h b/wled00/fcn_declare.h
index 71b00599cd..d44ed43a0d 100644
--- a/wled00/fcn_declare.h
+++ b/wled00/fcn_declare.h
@@ -324,6 +324,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/wled_server.cpp b/wled00/wled_server.cpp
index 958b513303..e8cbb41ae5 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 1ac22c9ce8..6d1ff2f863 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