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