diff --git a/tools/cdata.js b/tools/cdata.js index 12dda1cbe..d65573a8e 100644 --- a/tools/cdata.js +++ b/tools/cdata.js @@ -116,7 +116,8 @@ async function minify(str, type = "plain") { } else if (type == "css-minify") { return new CleanCSS({}).minify(str).styles; } else if (type == "js-minify") { - return await minifyHtml('', options).replace(/<[\/]*script>/g, ''); + let js = await minifyHtml('', options); + return js.replace(/<[\/]*script>/g, ''); } else if (type == "html-minify") { return await minifyHtml(str, options); } @@ -252,6 +253,12 @@ writeChunks( str .replace("%%", "%") }, + { + file: "common.js", + name: "JS_common", + method: "gzip", + filter: "js-minify", + }, { file: "settings.htm", name: "PAGE_settings", diff --git a/usermods/Animated_Staircase/Animated_Staircase.h b/usermods/Animated_Staircase/Animated_Staircase.h index 8953756d3..d1ec9bb7f 100644 --- a/usermods/Animated_Staircase/Animated_Staircase.h +++ b/usermods/Animated_Staircase/Animated_Staircase.h @@ -332,7 +332,7 @@ class Animated_Staircase : public Usermod { }; // NOTE: this *WILL* return TRUE if all the pins are set to -1. // this is *BY DESIGN*. - if (!pinManager.allocateMultiplePins(pins, 4, PinOwner::UM_AnimatedStaircase)) { + if (!PinManager::allocateMultiplePins(pins, 4, PinOwner::UM_AnimatedStaircase)) { topPIRorTriggerPin = -1; topEchoPin = -1; bottomPIRorTriggerPin = -1; @@ -513,10 +513,10 @@ class Animated_Staircase : public Usermod { (oldBottomAPin != bottomPIRorTriggerPin) || (oldBottomBPin != bottomEchoPin)) { changed = true; - pinManager.deallocatePin(oldTopAPin, PinOwner::UM_AnimatedStaircase); - pinManager.deallocatePin(oldTopBPin, PinOwner::UM_AnimatedStaircase); - pinManager.deallocatePin(oldBottomAPin, PinOwner::UM_AnimatedStaircase); - pinManager.deallocatePin(oldBottomBPin, PinOwner::UM_AnimatedStaircase); + PinManager::deallocatePin(oldTopAPin, PinOwner::UM_AnimatedStaircase); + PinManager::deallocatePin(oldTopBPin, PinOwner::UM_AnimatedStaircase); + PinManager::deallocatePin(oldBottomAPin, PinOwner::UM_AnimatedStaircase); + PinManager::deallocatePin(oldBottomBPin, PinOwner::UM_AnimatedStaircase); } if (changed) setup(); } diff --git a/usermods/Animated_Staircase/README.md b/usermods/Animated_Staircase/README.md index 320b744a5..2ad66b5ae 100644 --- a/usermods/Animated_Staircase/README.md +++ b/usermods/Animated_Staircase/README.md @@ -18,7 +18,7 @@ Before compiling, you have to make the following modifications: Edit `usermods_list.cpp`: 1. Open `wled00/usermods_list.cpp` 2. add `#include "../usermods/Animated_Staircase/Animated_Staircase.h"` to the top of the file -3. add `usermods.add(new Animated_Staircase());` to the end of the `void registerUsermods()` function. +3. add `UsermodManager::add(new Animated_Staircase());` to the end of the `void registerUsermods()` function. You can configure usermod using the Usermods settings page. Please enter GPIO pins for PIR or ultrasonic sensors (trigger and echo). diff --git a/usermods/Battery/usermod_v2_Battery.h b/usermods/Battery/usermod_v2_Battery.h index 136d3a71a..e91de850c 100644 --- a/usermods/Battery/usermod_v2_Battery.h +++ b/usermods/Battery/usermod_v2_Battery.h @@ -200,7 +200,7 @@ class UsermodBattery : public Usermod bool success = false; DEBUG_PRINTLN(F("Allocating battery pin...")); if (batteryPin >= 0 && digitalPinToAnalogChannel(batteryPin) >= 0) - if (pinManager.allocatePin(batteryPin, false, PinOwner::UM_Battery)) { + if (PinManager::allocatePin(batteryPin, false, PinOwner::UM_Battery)) { DEBUG_PRINTLN(F("Battery pin allocation succeeded.")); success = true; } @@ -561,7 +561,7 @@ class UsermodBattery : public Usermod if (newBatteryPin != batteryPin) { // deallocate pin - pinManager.deallocatePin(batteryPin, PinOwner::UM_Battery); + PinManager::deallocatePin(batteryPin, PinOwner::UM_Battery); batteryPin = newBatteryPin; // initialise setup(); diff --git a/usermods/EXAMPLE_v2/usermod_v2_example.h b/usermods/EXAMPLE_v2/usermod_v2_example.h index 32374fde2..3d562b585 100644 --- a/usermods/EXAMPLE_v2/usermod_v2_example.h +++ b/usermods/EXAMPLE_v2/usermod_v2_example.h @@ -71,7 +71,7 @@ class MyExampleUsermod : public Usermod { // #endif // in setup() // #ifdef USERMOD_EXAMPLE - // UM = (MyExampleUsermod*) usermods.lookup(USERMOD_ID_EXAMPLE); + // UM = (MyExampleUsermod*) UsermodManager::lookup(USERMOD_ID_EXAMPLE); // #endif // somewhere in loop() or other member method // #ifdef USERMOD_EXAMPLE diff --git a/usermods/Fix_unreachable_netservices_v2/readme.md b/usermods/Fix_unreachable_netservices_v2/readme.md index 006eaf9f9..07d64bc67 100644 --- a/usermods/Fix_unreachable_netservices_v2/readme.md +++ b/usermods/Fix_unreachable_netservices_v2/readme.md @@ -59,10 +59,10 @@ void registerUsermods() * || || || * \/ \/ \/ */ - //usermods.add(new MyExampleUsermod()); - //usermods.add(new UsermodTemperature()); - //usermods.add(new UsermodRenameMe()); - usermods.add(new FixUnreachableNetServices()); + //UsermodManager::add(new MyExampleUsermod()); + //UsermodManager::add(new UsermodTemperature()); + //UsermodManager::add(new UsermodRenameMe()); + UsermodManager::add(new FixUnreachableNetServices()); } ``` diff --git a/usermods/LDR_Dusk_Dawn_v2/usermod_LDR_Dusk_Dawn_v2.h b/usermods/LDR_Dusk_Dawn_v2/usermod_LDR_Dusk_Dawn_v2.h index 393fc2232..03f4c078a 100644 --- a/usermods/LDR_Dusk_Dawn_v2/usermod_LDR_Dusk_Dawn_v2.h +++ b/usermods/LDR_Dusk_Dawn_v2/usermod_LDR_Dusk_Dawn_v2.h @@ -30,7 +30,7 @@ class LDR_Dusk_Dawn_v2 : public Usermod { void setup() { // register ldrPin if ((ldrPin >= 0) && (digitalPinToAnalogChannel(ldrPin) >= 0)) { - if(!pinManager.allocatePin(ldrPin, false, PinOwner::UM_LDR_DUSK_DAWN)) ldrEnabled = false; // pin already in use -> disable usermod + if(!PinManager::allocatePin(ldrPin, false, PinOwner::UM_LDR_DUSK_DAWN)) ldrEnabled = false; // pin already in use -> disable usermod else pinMode(ldrPin, INPUT); // alloc success -> configure pin for input } else ldrEnabled = false; // invalid pin -> disable usermod initDone = true; @@ -110,7 +110,7 @@ class LDR_Dusk_Dawn_v2 : public Usermod { if (initDone && (ldrPin != oldLdrPin)) { // pin changed - un-register previous pin, register new pin - if (oldLdrPin >= 0) pinManager.deallocatePin(oldLdrPin, PinOwner::UM_LDR_DUSK_DAWN); + if (oldLdrPin >= 0) PinManager::deallocatePin(oldLdrPin, PinOwner::UM_LDR_DUSK_DAWN); setup(); // setup new pin } return configComplete; @@ -139,7 +139,7 @@ class LDR_Dusk_Dawn_v2 : public Usermod { //LDR_Off_Count.add(ldrOffCount); //bool pinValid = ((ldrPin >= 0) && (digitalPinToAnalogChannel(ldrPin) >= 0)); - //if (pinManager.getPinOwner(ldrPin) != PinOwner::UM_LDR_DUSK_DAWN) pinValid = false; + //if (PinManager::getPinOwner(ldrPin) != PinOwner::UM_LDR_DUSK_DAWN) pinValid = false; //JsonArray LDR_valid = user.createNestedArray(F("LDR pin")); //LDR_valid.add(ldrPin); //LDR_valid.add(pinValid ? F(" OK"): F(" invalid")); diff --git a/usermods/PIR_sensor_switch/readme.md b/usermods/PIR_sensor_switch/readme.md index 4dfdb07bd..fac5419f0 100644 --- a/usermods/PIR_sensor_switch/readme.md +++ b/usermods/PIR_sensor_switch/readme.md @@ -52,7 +52,7 @@ class MyUsermod : public Usermod { void togglePIRSensor() { #ifdef USERMOD_PIR_SENSOR_SWITCH - PIRsensorSwitch *PIRsensor = (PIRsensorSwitch::*) usermods.lookup(USERMOD_ID_PIRSWITCH); + PIRsensorSwitch *PIRsensor = (PIRsensorSwitch::*) UsermodManager::lookup(USERMOD_ID_PIRSWITCH); if (PIRsensor != nullptr) { PIRsensor->EnablePIRsensor(!PIRsensor->PIRsensorEnabled()); } diff --git a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h index 7a67dd749..29070cf84 100644 --- a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h +++ b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h @@ -375,7 +375,7 @@ void PIRsensorSwitch::setup() sensorPinState[i] = LOW; if (PIRsensorPin[i] < 0) continue; // pin retrieved from cfg.json (readFromConfig()) prior to running setup() - if (pinManager.allocatePin(PIRsensorPin[i], false, PinOwner::UM_PIR)) { + if (PinManager::allocatePin(PIRsensorPin[i], false, PinOwner::UM_PIR)) { // PIR Sensor mode INPUT_PULLDOWN #ifdef ESP8266 pinMode(PIRsensorPin[i], PIRsensorPin[i]==16 ? INPUT_PULLDOWN_16 : INPUT_PULLUP); // ESP8266 has INPUT_PULLDOWN on GPIO16 only @@ -564,7 +564,7 @@ bool PIRsensorSwitch::readFromConfig(JsonObject &root) DEBUG_PRINTLN(F(" config loaded.")); } else { for (int i = 0; i < PIR_SENSOR_MAX_SENSORS; i++) - if (oldPin[i] >= 0) pinManager.deallocatePin(oldPin[i], PinOwner::UM_PIR); + if (oldPin[i] >= 0) PinManager::deallocatePin(oldPin[i], PinOwner::UM_PIR); setup(); DEBUG_PRINTLN(F(" config (re)loaded.")); } diff --git a/usermods/PWM_fan/usermod_PWM_fan.h b/usermods/PWM_fan/usermod_PWM_fan.h index 1b78cfd4c..c3ef24fe4 100644 --- a/usermods/PWM_fan/usermod_PWM_fan.h +++ b/usermods/PWM_fan/usermod_PWM_fan.h @@ -75,7 +75,7 @@ class PWMFanUsermod : public Usermod { static const char _lock[]; void initTacho(void) { - if (tachoPin < 0 || !pinManager.allocatePin(tachoPin, false, PinOwner::UM_Unspecified)){ + if (tachoPin < 0 || !PinManager::allocatePin(tachoPin, false, PinOwner::UM_Unspecified)){ tachoPin = -1; return; } @@ -88,7 +88,7 @@ class PWMFanUsermod : public Usermod { void deinitTacho(void) { if (tachoPin < 0) return; detachInterrupt(digitalPinToInterrupt(tachoPin)); - pinManager.deallocatePin(tachoPin, PinOwner::UM_Unspecified); + PinManager::deallocatePin(tachoPin, PinOwner::UM_Unspecified); tachoPin = -1; } @@ -111,7 +111,7 @@ class PWMFanUsermod : public Usermod { // https://randomnerdtutorials.com/esp32-pwm-arduino-ide/ void initPWMfan(void) { - if (pwmPin < 0 || !pinManager.allocatePin(pwmPin, true, PinOwner::UM_Unspecified)) { + if (pwmPin < 0 || !PinManager::allocatePin(pwmPin, true, PinOwner::UM_Unspecified)) { enabled = false; pwmPin = -1; return; @@ -121,7 +121,7 @@ class PWMFanUsermod : public Usermod { analogWriteRange(255); analogWriteFreq(WLED_PWM_FREQ); #else - pwmChannel = pinManager.allocateLedc(1); + pwmChannel = PinManager::allocateLedc(1); if (pwmChannel == 255) { //no more free LEDC channels deinitPWMfan(); return; } @@ -136,9 +136,9 @@ class PWMFanUsermod : public Usermod { void deinitPWMfan(void) { if (pwmPin < 0) return; - pinManager.deallocatePin(pwmPin, PinOwner::UM_Unspecified); + PinManager::deallocatePin(pwmPin, PinOwner::UM_Unspecified); #ifdef ARDUINO_ARCH_ESP32 - pinManager.deallocateLedc(pwmChannel, 1); + PinManager::deallocateLedc(pwmChannel, 1); #endif pwmPin = -1; } @@ -191,9 +191,9 @@ class PWMFanUsermod : public Usermod { void setup() override { #ifdef USERMOD_DALLASTEMPERATURE // This Usermod requires Temperature usermod - tempUM = (UsermodTemperature*) usermods.lookup(USERMOD_ID_TEMPERATURE); + tempUM = (UsermodTemperature*) UsermodManager::lookup(USERMOD_ID_TEMPERATURE); #elif defined(USERMOD_SHT) - tempUM = (ShtUsermod*) usermods.lookup(USERMOD_ID_SHT); + tempUM = (ShtUsermod*) UsermodManager::lookup(USERMOD_ID_SHT); #endif initTacho(); initPWMfan(); diff --git a/usermods/SN_Photoresistor/usermods_list.cpp b/usermods/SN_Photoresistor/usermods_list.cpp index 649e19739..a2c6ca165 100644 --- a/usermods/SN_Photoresistor/usermods_list.cpp +++ b/usermods/SN_Photoresistor/usermods_list.cpp @@ -9,6 +9,6 @@ void registerUsermods() { #ifdef USERMOD_SN_PHOTORESISTOR - usermods.add(new Usermod_SN_Photoresistor()); + UsermodManager::add(new Usermod_SN_Photoresistor()); #endif } \ No newline at end of file diff --git a/usermods/ST7789_display/ST7789_display.h b/usermods/ST7789_display/ST7789_display.h index 59f6d9271..0dbada382 100644 --- a/usermods/ST7789_display/ST7789_display.h +++ b/usermods/ST7789_display/ST7789_display.h @@ -138,10 +138,10 @@ class St7789DisplayUsermod : public Usermod { void setup() override { PinManagerPinType spiPins[] = { { spi_mosi, true }, { spi_miso, false}, { spi_sclk, true } }; - if (!pinManager.allocateMultiplePins(spiPins, 3, PinOwner::HW_SPI)) { enabled = false; return; } + if (!PinManager::allocateMultiplePins(spiPins, 3, PinOwner::HW_SPI)) { enabled = false; return; } PinManagerPinType displayPins[] = { { TFT_CS, true}, { TFT_DC, true}, { TFT_RST, true }, { TFT_BL, true } }; - if (!pinManager.allocateMultiplePins(displayPins, sizeof(displayPins)/sizeof(PinManagerPinType), PinOwner::UM_FourLineDisplay)) { - pinManager.deallocateMultiplePins(spiPins, 3, PinOwner::HW_SPI); + if (!PinManager::allocateMultiplePins(displayPins, sizeof(displayPins)/sizeof(PinManagerPinType), PinOwner::UM_FourLineDisplay)) { + PinManager::deallocateMultiplePins(spiPins, 3, PinOwner::HW_SPI); enabled = false; return; } diff --git a/usermods/Temperature/usermod_temperature.h b/usermods/Temperature/usermod_temperature.h index 23c560650..ad755eaee 100644 --- a/usermods/Temperature/usermod_temperature.h +++ b/usermods/Temperature/usermod_temperature.h @@ -73,7 +73,7 @@ class UsermodTemperature : public Usermod { void publishHomeAssistantAutodiscovery(); #endif - static UsermodTemperature* _instance; // to overcome nonstatic getTemperatureC() method and avoid usermods.lookup(USERMOD_ID_TEMPERATURE); + static UsermodTemperature* _instance; // to overcome nonstatic getTemperatureC() method and avoid UsermodManager::lookup(USERMOD_ID_TEMPERATURE); public: @@ -223,14 +223,14 @@ void UsermodTemperature::setup() { // config says we are enabled DEBUG_PRINTLN(F("Allocating temperature pin...")); // pin retrieved from cfg.json (readFromConfig()) prior to running setup() - if (temperaturePin >= 0 && pinManager.allocatePin(temperaturePin, true, PinOwner::UM_Temperature)) { + if (temperaturePin >= 0 && PinManager::allocatePin(temperaturePin, true, PinOwner::UM_Temperature)) { oneWire = new OneWire(temperaturePin); if (oneWire->reset()) { while (!findSensor() && retries--) { delay(25); // try to find sensor } } - if (parasite && pinManager.allocatePin(parasitePin, true, PinOwner::UM_Temperature)) { + if (parasite && PinManager::allocatePin(parasitePin, true, PinOwner::UM_Temperature)) { pinMode(parasitePin, OUTPUT); digitalWrite(parasitePin, LOW); // deactivate power (close MOSFET) } else { @@ -423,9 +423,9 @@ bool UsermodTemperature::readFromConfig(JsonObject &root) { DEBUG_PRINTLN(F("Re-init temperature.")); // deallocate pin and release memory delete oneWire; - pinManager.deallocatePin(temperaturePin, PinOwner::UM_Temperature); + PinManager::deallocatePin(temperaturePin, PinOwner::UM_Temperature); temperaturePin = newTemperaturePin; - pinManager.deallocatePin(parasitePin, PinOwner::UM_Temperature); + PinManager::deallocatePin(parasitePin, PinOwner::UM_Temperature); // initialise setup(); } @@ -461,13 +461,13 @@ const char UsermodTemperature::_domoticzIDX[] PROGMEM = "domoticz-idx"; const char UsermodTemperature::_sensor[] PROGMEM = "sensor"; const char UsermodTemperature::_temperature[] PROGMEM = "temperature"; const char UsermodTemperature::_Temperature[] PROGMEM = "/temperature"; -const char UsermodTemperature::_data_fx[] PROGMEM = "Temperature@Min,Max;;!;01;pal=54"; +const char UsermodTemperature::_data_fx[] PROGMEM = "Temperature@Min,Max;;!;01;pal=54,sx=255,ix=0"; static uint16_t mode_temperature() { - float low = mapf((float)SEGMENT.speed, 0.f, 255.f, -150.f, 149.9f); // default: 0°C, range: -15°C to 15°C - float high = mapf((float)SEGMENT.intensity, 0.f, 255.f, 150.f, 450.f); // default: 30°C, range 15°C to 45°C - float temp = constrain(UsermodTemperature::getInstance()->getTemperatureC()*10.f, low, high); // get a little better resolution - unsigned i = map(temp, (unsigned)low, (unsigned)high, 0, 255); + float low = roundf(mapf((float)SEGMENT.speed, 0.f, 255.f, -150.f, 150.f)); // default: 15°C, range: -15°C to 15°C + float high = roundf(mapf((float)SEGMENT.intensity, 0.f, 255.f, 300.f, 600.f)); // default: 30°C, range 30°C to 60°C + float temp = constrain(UsermodTemperature::getInstance()->getTemperatureC()*10.f, low, high); // get a little better resolution (*10) + unsigned i = map(roundf(temp), (unsigned)low, (unsigned)high, 0, 248); SEGMENT.fill(SEGMENT.color_from_palette(i, false, false, 255)); return FRAMETIME; } diff --git a/usermods/audioreactive/audio_source.h b/usermods/audioreactive/audio_source.h index a7337eaf9..a14f8def0 100644 --- a/usermods/audioreactive/audio_source.h +++ b/usermods/audioreactive/audio_source.h @@ -194,8 +194,8 @@ class I2SSource : public AudioSource { virtual void initialize(int8_t i2swsPin = I2S_PIN_NO_CHANGE, int8_t i2ssdPin = I2S_PIN_NO_CHANGE, int8_t i2sckPin = I2S_PIN_NO_CHANGE, int8_t mclkPin = I2S_PIN_NO_CHANGE) { DEBUGSR_PRINTLN(F("I2SSource:: initialize().")); if (i2swsPin != I2S_PIN_NO_CHANGE && i2ssdPin != I2S_PIN_NO_CHANGE) { - if (!pinManager.allocatePin(i2swsPin, true, PinOwner::UM_Audioreactive) || - !pinManager.allocatePin(i2ssdPin, false, PinOwner::UM_Audioreactive)) { // #206 + if (!PinManager::allocatePin(i2swsPin, true, PinOwner::UM_Audioreactive) || + !PinManager::allocatePin(i2ssdPin, false, PinOwner::UM_Audioreactive)) { // #206 DEBUGSR_PRINTF("\nAR: Failed to allocate I2S pins: ws=%d, sd=%d\n", i2swsPin, i2ssdPin); return; } @@ -203,7 +203,7 @@ class I2SSource : public AudioSource { // i2ssckPin needs special treatment, since it might be unused on PDM mics if (i2sckPin != I2S_PIN_NO_CHANGE) { - if (!pinManager.allocatePin(i2sckPin, true, PinOwner::UM_Audioreactive)) { + if (!PinManager::allocatePin(i2sckPin, true, PinOwner::UM_Audioreactive)) { DEBUGSR_PRINTF("\nAR: Failed to allocate I2S pins: sck=%d\n", i2sckPin); return; } @@ -249,7 +249,7 @@ class I2SSource : public AudioSource { // Reserve the master clock pin if provided _mclkPin = mclkPin; if (mclkPin != I2S_PIN_NO_CHANGE) { - if(!pinManager.allocatePin(mclkPin, true, PinOwner::UM_Audioreactive)) { + if(!PinManager::allocatePin(mclkPin, true, PinOwner::UM_Audioreactive)) { DEBUGSR_PRINTF("\nAR: Failed to allocate I2S pin: MCLK=%d\n", mclkPin); return; } else @@ -307,11 +307,11 @@ class I2SSource : public AudioSource { DEBUGSR_PRINTF("Failed to uninstall i2s driver: %d\n", err); return; } - if (_pinConfig.ws_io_num != I2S_PIN_NO_CHANGE) pinManager.deallocatePin(_pinConfig.ws_io_num, PinOwner::UM_Audioreactive); - if (_pinConfig.data_in_num != I2S_PIN_NO_CHANGE) pinManager.deallocatePin(_pinConfig.data_in_num, PinOwner::UM_Audioreactive); - if (_pinConfig.bck_io_num != I2S_PIN_NO_CHANGE) pinManager.deallocatePin(_pinConfig.bck_io_num, PinOwner::UM_Audioreactive); + if (_pinConfig.ws_io_num != I2S_PIN_NO_CHANGE) PinManager::deallocatePin(_pinConfig.ws_io_num, PinOwner::UM_Audioreactive); + if (_pinConfig.data_in_num != I2S_PIN_NO_CHANGE) PinManager::deallocatePin(_pinConfig.data_in_num, PinOwner::UM_Audioreactive); + if (_pinConfig.bck_io_num != I2S_PIN_NO_CHANGE) PinManager::deallocatePin(_pinConfig.bck_io_num, PinOwner::UM_Audioreactive); // Release the master clock pin - if (_mclkPin != I2S_PIN_NO_CHANGE) pinManager.deallocatePin(_mclkPin, PinOwner::UM_Audioreactive); + if (_mclkPin != I2S_PIN_NO_CHANGE) PinManager::deallocatePin(_mclkPin, PinOwner::UM_Audioreactive); } virtual void getSamples(float *buffer, uint16_t num_samples) { @@ -589,7 +589,7 @@ class I2SAdcSource : public I2SSource { void initialize(int8_t audioPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) { DEBUGSR_PRINTLN(F("I2SAdcSource:: initialize().")); _myADCchannel = 0x0F; - if(!pinManager.allocatePin(audioPin, false, PinOwner::UM_Audioreactive)) { + if(!PinManager::allocatePin(audioPin, false, PinOwner::UM_Audioreactive)) { DEBUGSR_PRINTF("failed to allocate GPIO for audio analog input: %d\n", audioPin); return; } @@ -717,7 +717,7 @@ class I2SAdcSource : public I2SSource { } void deinitialize() { - pinManager.deallocatePin(_audioPin, PinOwner::UM_Audioreactive); + PinManager::deallocatePin(_audioPin, PinOwner::UM_Audioreactive); _initialized = false; _myADCchannel = 0x0F; diff --git a/usermods/mpu6050_imu/readme.md b/usermods/mpu6050_imu/readme.md index b804ba602..c324738d6 100644 --- a/usermods/mpu6050_imu/readme.md +++ b/usermods/mpu6050_imu/readme.md @@ -86,6 +86,6 @@ Example **usermods_list.cpp**: void registerUsermods() { - usermods.add(new MPU6050Driver()); + UsermodManager::add(new MPU6050Driver()); } ``` diff --git a/usermods/mpu6050_imu/usermod_gyro_surge.h b/usermods/mpu6050_imu/usermod_gyro_surge.h index c49d930ff..c19358de7 100644 --- a/usermods/mpu6050_imu/usermod_gyro_surge.h +++ b/usermods/mpu6050_imu/usermod_gyro_surge.h @@ -163,7 +163,7 @@ class GyroSurge : public Usermod { void loop() { // get IMU data um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_IMU)) { + if (!UsermodManager::getUMData(&um_data, USERMOD_ID_IMU)) { // Apply max strip.getSegment(0).fadeToBlackBy(max); return; diff --git a/usermods/mpu6050_imu/usermod_mpu6050_imu.h b/usermods/mpu6050_imu/usermod_mpu6050_imu.h index 436d03601..f04578fe3 100644 --- a/usermods/mpu6050_imu/usermod_mpu6050_imu.h +++ b/usermods/mpu6050_imu/usermod_mpu6050_imu.h @@ -164,7 +164,7 @@ class MPU6050Driver : public Usermod { if (i2c_scl<0 || i2c_sda<0) { DEBUG_PRINTLN(F("MPU6050: I2C is no good.")); return; } // Check the interrupt pin if (config.interruptPin >= 0) { - irqBound = pinManager.allocatePin(config.interruptPin, false, PinOwner::UM_IMU); + irqBound = PinManager::allocatePin(config.interruptPin, false, PinOwner::UM_IMU); if (!irqBound) { DEBUG_PRINTLN(F("MPU6050: IRQ pin already in use.")); return; } pinMode(config.interruptPin, INPUT); }; @@ -408,7 +408,7 @@ class MPU6050Driver : public Usermod { // Previously loaded and config changed if (irqBound && ((old_cfg.interruptPin != config.interruptPin) || !config.enabled)) { detachInterrupt(old_cfg.interruptPin); - pinManager.deallocatePin(old_cfg.interruptPin, PinOwner::UM_IMU); + PinManager::deallocatePin(old_cfg.interruptPin, PinOwner::UM_IMU); irqBound = false; } diff --git a/usermods/mqtt_switch_v2/README.md b/usermods/mqtt_switch_v2/README.md index 4cb7ef0e8..382f72d0e 100644 --- a/usermods/mqtt_switch_v2/README.md +++ b/usermods/mqtt_switch_v2/README.md @@ -19,7 +19,7 @@ Example `usermods_list.cpp`: void registerUsermods() { - usermods.add(new UsermodMqttSwitch()); + UsermodManager::add(new UsermodMqttSwitch()); } ``` diff --git a/usermods/multi_relay/readme.md b/usermods/multi_relay/readme.md index 24dd394b8..eaa069ae7 100644 --- a/usermods/multi_relay/readme.md +++ b/usermods/multi_relay/readme.md @@ -41,7 +41,7 @@ When a relay is switched, a message is published: ## Usermod installation -1. Register the usermod by adding `#include "../usermods/multi_relay/usermod_multi_relay.h"` at the top and `usermods.add(new MultiRelay());` at the bottom of `usermods_list.cpp`. +1. Register the usermod by adding `#include "../usermods/multi_relay/usermod_multi_relay.h"` at the top and `UsermodManager::add(new MultiRelay());` at the bottom of `usermods_list.cpp`. or 2. Use `#define USERMOD_MULTI_RELAY` in wled.h or `-D USERMOD_MULTI_RELAY` in your platformio.ini @@ -90,9 +90,9 @@ void registerUsermods() * || || || * \/ \/ \/ */ - //usermods.add(new MyExampleUsermod()); - //usermods.add(new UsermodTemperature()); - usermods.add(new MultiRelay()); + //UsermodManager::add(new MyExampleUsermod()); + //UsermodManager::add(new UsermodTemperature()); + UsermodManager::add(new MultiRelay()); } ``` diff --git a/usermods/multi_relay/usermod_multi_relay.h b/usermods/multi_relay/usermod_multi_relay.h index efb3c8ae1..33a6cf85e 100644 --- a/usermods/multi_relay/usermod_multi_relay.h +++ b/usermods/multi_relay/usermod_multi_relay.h @@ -516,7 +516,7 @@ void MultiRelay::setup() { if (!_relay[i].external) _relay[i].state = !offMode; state |= (uint8_t)(_relay[i].invert ? !_relay[i].state : _relay[i].state) << pin; } else if (_relay[i].pin<100 && _relay[i].pin>=0) { - if (pinManager.allocatePin(_relay[i].pin,true, PinOwner::UM_MultiRelay)) { + if (PinManager::allocatePin(_relay[i].pin,true, PinOwner::UM_MultiRelay)) { if (!_relay[i].external) _relay[i].state = !offMode; switchRelay(i, _relay[i].state); _relay[i].active = false; @@ -817,7 +817,7 @@ bool MultiRelay::readFromConfig(JsonObject &root) { // deallocate all pins 1st for (int i=0; i=0 && oldPin[i]<100) { - pinManager.deallocatePin(oldPin[i], PinOwner::UM_MultiRelay); + PinManager::deallocatePin(oldPin[i], PinOwner::UM_MultiRelay); } // allocate new pins setup(); diff --git a/usermods/pixels_dice_tray/pixels_dice_tray.h b/usermods/pixels_dice_tray/pixels_dice_tray.h index 238af314e..a1e45ba33 100644 --- a/usermods/pixels_dice_tray/pixels_dice_tray.h +++ b/usermods/pixels_dice_tray/pixels_dice_tray.h @@ -112,15 +112,15 @@ class PixelsDiceTrayUsermod : public Usermod { SetSPIPinsFromMacros(); PinManagerPinType spiPins[] = { {spi_mosi, true}, {spi_miso, false}, {spi_sclk, true}}; - if (!pinManager.allocateMultiplePins(spiPins, 3, PinOwner::HW_SPI)) { + if (!PinManager::allocateMultiplePins(spiPins, 3, PinOwner::HW_SPI)) { enabled = false; } else { PinManagerPinType displayPins[] = { {TFT_CS, true}, {TFT_DC, true}, {TFT_RST, true}, {TFT_BL, true}}; - if (!pinManager.allocateMultiplePins( + if (!PinManager::allocateMultiplePins( displayPins, sizeof(displayPins) / sizeof(PinManagerPinType), PinOwner::UM_FourLineDisplay)) { - pinManager.deallocateMultiplePins(spiPins, 3, PinOwner::HW_SPI); + PinManager::deallocateMultiplePins(spiPins, 3, PinOwner::HW_SPI); enabled = false; } } diff --git a/usermods/pwm_outputs/usermod_pwm_outputs.h b/usermods/pwm_outputs/usermod_pwm_outputs.h index 1880308c4..09232f043 100644 --- a/usermods/pwm_outputs/usermod_pwm_outputs.h +++ b/usermods/pwm_outputs/usermod_pwm_outputs.h @@ -29,13 +29,13 @@ class PwmOutput { return; DEBUG_PRINTF("pwm_output[%d]: setup to freq %d\n", pin_, freq_); - if (!pinManager.allocatePin(pin_, true, PinOwner::UM_PWM_OUTPUTS)) + if (!PinManager::allocatePin(pin_, true, PinOwner::UM_PWM_OUTPUTS)) return; - channel_ = pinManager.allocateLedc(1); + channel_ = PinManager::allocateLedc(1); if (channel_ == 255) { DEBUG_PRINTF("pwm_output[%d]: failed to quire ledc\n", pin_); - pinManager.deallocatePin(pin_, PinOwner::UM_PWM_OUTPUTS); + PinManager::deallocatePin(pin_, PinOwner::UM_PWM_OUTPUTS); return; } @@ -49,9 +49,9 @@ class PwmOutput { DEBUG_PRINTF("pwm_output[%d]: close\n", pin_); if (!enabled_) return; - pinManager.deallocatePin(pin_, PinOwner::UM_PWM_OUTPUTS); + PinManager::deallocatePin(pin_, PinOwner::UM_PWM_OUTPUTS); if (channel_ != 255) - pinManager.deallocateLedc(channel_, 1); + PinManager::deallocateLedc(channel_, 1); channel_ = 255; duty_ = 0.0f; enabled_ = false; diff --git a/usermods/quinled-an-penta/quinled-an-penta.h b/usermods/quinled-an-penta/quinled-an-penta.h index 10b784334..e44672039 100644 --- a/usermods/quinled-an-penta/quinled-an-penta.h +++ b/usermods/quinled-an-penta/quinled-an-penta.h @@ -129,7 +129,7 @@ class QuinLEDAnPentaUsermod : public Usermod void initOledDisplay() { PinManagerPinType pins[5] = { { oledSpiClk, true }, { oledSpiData, true }, { oledSpiCs, true }, { oledSpiDc, true }, { oledSpiRst, true } }; - if (!pinManager.allocateMultiplePins(pins, 5, PinOwner::UM_QuinLEDAnPenta)) { + if (!PinManager::allocateMultiplePins(pins, 5, PinOwner::UM_QuinLEDAnPenta)) { DEBUG_PRINTF("[%s] OLED pin allocation failed!\n", _name); oledEnabled = oledInitDone = false; return; @@ -164,11 +164,11 @@ class QuinLEDAnPentaUsermod : public Usermod oledDisplay->clear(); } - pinManager.deallocatePin(oledSpiClk, PinOwner::UM_QuinLEDAnPenta); - pinManager.deallocatePin(oledSpiData, PinOwner::UM_QuinLEDAnPenta); - pinManager.deallocatePin(oledSpiCs, PinOwner::UM_QuinLEDAnPenta); - pinManager.deallocatePin(oledSpiDc, PinOwner::UM_QuinLEDAnPenta); - pinManager.deallocatePin(oledSpiRst, PinOwner::UM_QuinLEDAnPenta); + PinManager::deallocatePin(oledSpiClk, PinOwner::UM_QuinLEDAnPenta); + PinManager::deallocatePin(oledSpiData, PinOwner::UM_QuinLEDAnPenta); + PinManager::deallocatePin(oledSpiCs, PinOwner::UM_QuinLEDAnPenta); + PinManager::deallocatePin(oledSpiDc, PinOwner::UM_QuinLEDAnPenta); + PinManager::deallocatePin(oledSpiRst, PinOwner::UM_QuinLEDAnPenta); delete oledDisplay; @@ -184,7 +184,7 @@ class QuinLEDAnPentaUsermod : public Usermod void initSht30TempHumiditySensor() { PinManagerPinType pins[2] = { { shtSda, true }, { shtScl, true } }; - if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::UM_QuinLEDAnPenta)) { + if (!PinManager::allocateMultiplePins(pins, 2, PinOwner::UM_QuinLEDAnPenta)) { DEBUG_PRINTF("[%s] SHT30 pin allocation failed!\n", _name); shtEnabled = shtInitDone = false; return; @@ -212,8 +212,8 @@ class QuinLEDAnPentaUsermod : public Usermod sht30TempHumidSensor->reset(); } - pinManager.deallocatePin(shtSda, PinOwner::UM_QuinLEDAnPenta); - pinManager.deallocatePin(shtScl, PinOwner::UM_QuinLEDAnPenta); + PinManager::deallocatePin(shtSda, PinOwner::UM_QuinLEDAnPenta); + PinManager::deallocatePin(shtScl, PinOwner::UM_QuinLEDAnPenta); delete sht30TempHumidSensor; diff --git a/usermods/rgb-rotary-encoder/rgb-rotary-encoder.h b/usermods/rgb-rotary-encoder/rgb-rotary-encoder.h index e57641bf9..00fc22725 100644 --- a/usermods/rgb-rotary-encoder/rgb-rotary-encoder.h +++ b/usermods/rgb-rotary-encoder/rgb-rotary-encoder.h @@ -40,7 +40,7 @@ class RgbRotaryEncoderUsermod : public Usermod void initRotaryEncoder() { PinManagerPinType pins[2] = { { eaIo, false }, { ebIo, false } }; - if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::UM_RGBRotaryEncoder)) { + if (!PinManager::allocateMultiplePins(pins, 2, PinOwner::UM_RGBRotaryEncoder)) { eaIo = -1; ebIo = -1; cleanup(); @@ -108,11 +108,11 @@ class RgbRotaryEncoderUsermod : public Usermod { // Only deallocate pins if we allocated them ;) if (eaIo != -1) { - pinManager.deallocatePin(eaIo, PinOwner::UM_RGBRotaryEncoder); + PinManager::deallocatePin(eaIo, PinOwner::UM_RGBRotaryEncoder); eaIo = -1; } if (ebIo != -1) { - pinManager.deallocatePin(ebIo, PinOwner::UM_RGBRotaryEncoder); + PinManager::deallocatePin(ebIo, PinOwner::UM_RGBRotaryEncoder); ebIo = -1; } @@ -303,8 +303,8 @@ class RgbRotaryEncoderUsermod : public Usermod } if (eaIo != oldEaIo || ebIo != oldEbIo || stepsPerClick != oldStepsPerClick || incrementPerClick != oldIncrementPerClick) { - pinManager.deallocatePin(oldEaIo, PinOwner::UM_RGBRotaryEncoder); - pinManager.deallocatePin(oldEbIo, PinOwner::UM_RGBRotaryEncoder); + PinManager::deallocatePin(oldEaIo, PinOwner::UM_RGBRotaryEncoder); + PinManager::deallocatePin(oldEbIo, PinOwner::UM_RGBRotaryEncoder); delete rotaryEncoder; initRotaryEncoder(); diff --git a/usermods/sd_card/usermod_sd_card.h b/usermods/sd_card/usermod_sd_card.h index 5dac79159..da1999d9b 100644 --- a/usermods/sd_card/usermod_sd_card.h +++ b/usermods/sd_card/usermod_sd_card.h @@ -45,7 +45,7 @@ class UsermodSdCard : public Usermod { { configPinPico, true } }; - if (!pinManager.allocateMultiplePins(pins, 4, PinOwner::UM_SdCard)) { + if (!PinManager::allocateMultiplePins(pins, 4, PinOwner::UM_SdCard)) { DEBUG_PRINTF("[%s] SD (SPI) pin allocation failed!\n", _name); sdInitDone = false; return; @@ -75,10 +75,10 @@ class UsermodSdCard : public Usermod { SD_ADAPTER.end(); DEBUG_PRINTF("[%s] deallocate pins!\n", _name); - pinManager.deallocatePin(configPinSourceSelect, PinOwner::UM_SdCard); - pinManager.deallocatePin(configPinSourceClock, PinOwner::UM_SdCard); - pinManager.deallocatePin(configPinPoci, PinOwner::UM_SdCard); - pinManager.deallocatePin(configPinPico, PinOwner::UM_SdCard); + PinManager::deallocatePin(configPinSourceSelect, PinOwner::UM_SdCard); + PinManager::deallocatePin(configPinSourceClock, PinOwner::UM_SdCard); + PinManager::deallocatePin(configPinPoci, PinOwner::UM_SdCard); + PinManager::deallocatePin(configPinPico, PinOwner::UM_SdCard); sdInitDone = false; } diff --git a/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h b/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h index 111df2967..1436f8fc4 100644 --- a/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h +++ b/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h @@ -385,7 +385,7 @@ public: _setAllFalse(); #ifdef USERMOD_SN_PHOTORESISTOR - ptr = (Usermod_SN_Photoresistor*) usermods.lookup(USERMOD_ID_SN_PHOTORESISTOR); + ptr = (Usermod_SN_Photoresistor*) UsermodManager::lookup(USERMOD_ID_SN_PHOTORESISTOR); #endif DEBUG_PRINTLN(F("Setup done")); } diff --git a/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h b/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h index 52ff3cc1d..a257413b4 100644 --- a/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h +++ b/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h @@ -103,7 +103,7 @@ class AutoSaveUsermod : public Usermod { #ifdef USERMOD_FOUR_LINE_DISPLAY // This Usermod has enhanced functionality if // FourLineDisplayUsermod is available. - display = (FourLineDisplayUsermod*) usermods.lookup(USERMOD_ID_FOUR_LINE_DISP); + display = (FourLineDisplayUsermod*) UsermodManager::lookup(USERMOD_ID_FOUR_LINE_DISP); #endif initDone = true; if (enabled && applyAutoSaveOnBoot) applyPreset(autoSavePreset); 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 008647fa7..dfab7e6ff 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 @@ -543,7 +543,7 @@ void FourLineDisplayUsermod::setup() { type = NONE; } else { PinManagerPinType cspins[3] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true } }; - if (!pinManager.allocateMultiplePins(cspins, 3, PinOwner::UM_FourLineDisplay)) { type = NONE; } + if (!PinManager::allocateMultiplePins(cspins, 3, PinOwner::UM_FourLineDisplay)) { type = NONE; } } } else { if (i2c_scl<0 || i2c_sda<0) { type=NONE; } @@ -569,7 +569,7 @@ void FourLineDisplayUsermod::setup() { if (nullptr == u8x8) { DEBUG_PRINTLN(F("Display init failed.")); if (isSPI) { - pinManager.deallocateMultiplePins((const uint8_t*)ioPin, 3, PinOwner::UM_FourLineDisplay); + PinManager::deallocateMultiplePins((const uint8_t*)ioPin, 3, PinOwner::UM_FourLineDisplay); } type = NONE; return; @@ -1307,7 +1307,7 @@ bool FourLineDisplayUsermod::readFromConfig(JsonObject& root) { bool isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64 || type == SSD1309_SPI64); bool newSPI = (newType == SSD1306_SPI || newType == SSD1306_SPI64 || newType == SSD1309_SPI64); if (isSPI) { - if (pinsChanged || !newSPI) pinManager.deallocateMultiplePins((const uint8_t*)oldPin, 3, PinOwner::UM_FourLineDisplay); + if (pinsChanged || !newSPI) PinManager::deallocateMultiplePins((const uint8_t*)oldPin, 3, PinOwner::UM_FourLineDisplay); if (!newSPI) { // was SPI but is no longer SPI if (i2c_scl<0 || i2c_sda<0) { newType=NONE; } @@ -1315,7 +1315,7 @@ bool FourLineDisplayUsermod::readFromConfig(JsonObject& root) { // still SPI but pins changed PinManagerPinType cspins[3] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true } }; if (ioPin[0]<0 || ioPin[1]<0 || ioPin[1]<0) { newType=NONE; } - else if (!pinManager.allocateMultiplePins(cspins, 3, PinOwner::UM_FourLineDisplay)) { newType=NONE; } + else if (!PinManager::allocateMultiplePins(cspins, 3, PinOwner::UM_FourLineDisplay)) { newType=NONE; } } } else if (newSPI) { // was I2C but is now SPI @@ -1324,7 +1324,7 @@ bool FourLineDisplayUsermod::readFromConfig(JsonObject& root) { } else { PinManagerPinType pins[3] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true } }; if (ioPin[0]<0 || ioPin[1]<0 || ioPin[1]<0) { newType=NONE; } - else if (!pinManager.allocateMultiplePins(pins, 3, PinOwner::UM_FourLineDisplay)) { newType=NONE; } + else if (!PinManager::allocateMultiplePins(pins, 3, PinOwner::UM_FourLineDisplay)) { newType=NONE; } } } else { // just I2C type changed 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 5756fbb69..55715b7c7 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 @@ -489,7 +489,7 @@ void RotaryEncoderUIUsermod::setup() enabled = false; return; } else { - if (pinIRQ >= 0 && pinManager.allocatePin(pinIRQ, false, PinOwner::UM_RotaryEncoderUI)) { + if (pinIRQ >= 0 && PinManager::allocatePin(pinIRQ, false, PinOwner::UM_RotaryEncoderUI)) { pinMode(pinIRQ, INPUT_PULLUP); attachInterrupt(pinIRQ, i2cReadingISR, FALLING); // RISING, FALLING, CHANGE, ONLOW, ONHIGH DEBUG_PRINTLN(F("Interrupt attached.")); @@ -502,7 +502,7 @@ void RotaryEncoderUIUsermod::setup() } } else { PinManagerPinType pins[3] = { { pinA, false }, { pinB, false }, { pinC, false } }; - if (pinA<0 || pinB<0 || !pinManager.allocateMultiplePins(pins, 3, PinOwner::UM_RotaryEncoderUI)) { + if (pinA<0 || pinB<0 || !PinManager::allocateMultiplePins(pins, 3, PinOwner::UM_RotaryEncoderUI)) { pinA = pinB = pinC = -1; enabled = false; return; @@ -525,7 +525,7 @@ void RotaryEncoderUIUsermod::setup() #ifdef USERMOD_FOUR_LINE_DISPLAY // This Usermod uses FourLineDisplayUsermod for the best experience. // But it's optional. But you want it. - display = (FourLineDisplayUsermod*) usermods.lookup(USERMOD_ID_FOUR_LINE_DISP); + display = (FourLineDisplayUsermod*) UsermodManager::lookup(USERMOD_ID_FOUR_LINE_DISP); if (display != nullptr) { display->setMarkLine(1, 0); } @@ -1138,14 +1138,14 @@ bool RotaryEncoderUIUsermod::readFromConfig(JsonObject &root) { if (oldPcf8574) { if (pinIRQ >= 0) { detachInterrupt(pinIRQ); - pinManager.deallocatePin(pinIRQ, PinOwner::UM_RotaryEncoderUI); + PinManager::deallocatePin(pinIRQ, PinOwner::UM_RotaryEncoderUI); DEBUG_PRINTLN(F("Deallocated old IRQ pin.")); } pinIRQ = newIRQpin<100 ? newIRQpin : -1; // ignore PCF8574 pins } else { - pinManager.deallocatePin(pinA, PinOwner::UM_RotaryEncoderUI); - pinManager.deallocatePin(pinB, PinOwner::UM_RotaryEncoderUI); - pinManager.deallocatePin(pinC, PinOwner::UM_RotaryEncoderUI); + PinManager::deallocatePin(pinA, PinOwner::UM_RotaryEncoderUI); + PinManager::deallocatePin(pinB, PinOwner::UM_RotaryEncoderUI); + PinManager::deallocatePin(pinC, PinOwner::UM_RotaryEncoderUI); DEBUG_PRINTLN(F("Deallocated old pins.")); } pinA = newDTpin; diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 0084b09e0..ad843f0f9 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -75,7 +75,7 @@ int8_t tristate_square8(uint8_t x, uint8_t pulsewidth, uint8_t attdec) { static um_data_t* getAudioData() { um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { + if (!UsermodManager::getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { // add support for no audio um_data = simulateSound(SEGMENT.soundSim); } @@ -6298,7 +6298,7 @@ static const char _data_FX_MODE_2DPLASMAROTOZOOM[] PROGMEM = "Rotozoomer@!,Scale uint8_t *fftResult = nullptr; float *fftBin = nullptr; um_data_t *um_data; - if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { + if (UsermodManager::getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { volumeSmth = *(float*) um_data->u_data[0]; volumeRaw = *(float*) um_data->u_data[1]; fftResult = (uint8_t*) um_data->u_data[2]; @@ -6911,7 +6911,7 @@ uint16_t mode_pixels(void) { // Pixels. By Andrew Tuline. uint8_t *myVals = reinterpret_cast(SEGENV.data); // Used to store a pile of samples because WLED frame rate and WLED sample rate are not synchronized. Frame rate is too low. um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { + if (!UsermodManager::getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { um_data = simulateSound(SEGMENT.soundSim); } float volumeSmth = *(float*) um_data->u_data[0]; @@ -7494,7 +7494,7 @@ uint16_t mode_2DAkemi(void) { const float normalFactor = 0.4f; um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { + if (!UsermodManager::getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { um_data = simulateSound(SEGMENT.soundSim); } uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 25b61095d..9a0c80700 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -187,11 +187,7 @@ void IRAM_ATTR_YN Segment::deallocateData() { if ((Segment::getUsedSegmentData() > 0) && (_dataLen > 0)) { // check that we don't have a dangling / inconsistent data pointer free(data); } else { - DEBUG_PRINT(F("---- Released data ")); - DEBUG_PRINTF_P(PSTR("(%p): "), this); - DEBUG_PRINT(F("inconsistent UsedSegmentData ")); - DEBUG_PRINTF_P(PSTR("(%d/%d)"), _dataLen, Segment::getUsedSegmentData()); - DEBUG_PRINTLN(F(", cowardly refusing to free nothing.")); + DEBUG_PRINTF_P(PSTR("---- Released data (%p): inconsistent UsedSegmentData (%d/%d), cowardly refusing to free nothing.\n"), this, _dataLen, Segment::getUsedSegmentData()); } data = nullptr; Segment::addUsedSegmentData(_dataLen <= Segment::getUsedSegmentData() ? -_dataLen : -Segment::getUsedSegmentData()); @@ -1136,7 +1132,6 @@ void Segment::refreshLightCapabilities() { if (bus->getStart() >= segStopIdx) continue; if (bus->getStart() + bus->getLength() <= segStartIdx) continue; - //uint8_t type = bus->getType(); if (bus->hasRGB() || (strip.cctFromRgb && bus->hasCCT())) capabilities |= SEG_CAPABILITY_RGB; if (!strip.cctFromRgb && bus->hasCCT()) capabilities |= SEG_CAPABILITY_CCT; if (strip.correctWB && (bus->hasRGB() || bus->hasCCT())) capabilities |= SEG_CAPABILITY_CCT; //white balance correction (CCT slider) @@ -1353,7 +1348,7 @@ void WS2812FX::finalizeInit() { // When booting without config (1st boot) we need to make sure GPIOs defined for LED output don't clash with hardware // i.e. DEBUG (GPIO1), DMX (2), SPI RAM/FLASH (16&17 on ESP32-WROVER/PICO), read/only pins, etc. // Pin should not be already allocated, read/only or defined for current bus - while (pinManager.isPinAllocated(defPin[j]) || !pinManager.isPinOk(defPin[j],true)) { + while (PinManager::isPinAllocated(defPin[j]) || !PinManager::isPinOk(defPin[j],true)) { if (validPin) { DEBUG_PRINTLN(F("Some of the provided pins cannot be used to configure this LED output.")); defPin[j] = 1; // start with GPIO1 and work upwards @@ -1364,16 +1359,30 @@ void WS2812FX::finalizeInit() { DEBUG_PRINTLN(F("No available pins left! Can't configure output.")); return; } - // is the newly assigned pin already defined? try next in line until there are no clashes + // is the newly assigned pin already defined or used previously? + // try next in line until there are no clashes or we run out of pins bool clash; do { clash = false; - for (const auto &pin : defDataPins) { - if (pin == defPin[j]) { - defPin[j]++; - if (defPin[j] < WLED_NUM_PINS) clash = true; + // check for conflicts on current bus + for (const auto &pin : defPin) { + if (&pin != &defPin[j] && pin == defPin[j]) { + clash = true; + break; } } + // We already have a clash on current bus, no point checking next buses + if (!clash) { + // check for conflicts in defined pins + for (const auto &pin : defDataPins) { + if (pin == defPin[j]) { + clash = true; + break; + } + } + } + if (clash) defPin[j]++; + if (defPin[j] >= WLED_NUM_PINS) break; } while (clash); } } @@ -1722,7 +1731,7 @@ uint16_t WS2812FX::getLengthPhysical() const { unsigned len = 0; for (size_t b = 0; b < BusManager::getNumBusses(); b++) { Bus *bus = BusManager::getBus(b); - if (bus->getType() >= TYPE_NET_DDP_RGB) continue; //exclude non-physical network busses + if (bus->isVirtual()) continue; //exclude non-physical network busses len += bus->getLength(); } return len; diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index b20095d4c..5b948b9c4 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -130,11 +130,11 @@ BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com) , _colorOrderMap(com) { if (!isDigital(bc.type) || !bc.count) return; - if (!pinManager.allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return; + if (!PinManager::allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return; _frequencykHz = 0U; _pins[0] = bc.pins[0]; if (is2Pin(bc.type)) { - if (!pinManager.allocatePin(bc.pins[1], true, PinOwner::BusDigital)) { + if (!PinManager::allocatePin(bc.pins[1], true, PinOwner::BusDigital)) { cleanup(); return; } @@ -422,8 +422,8 @@ void BusDigital::cleanup() { _valid = false; _busPtr = nullptr; if (_data != nullptr) freeData(); - pinManager.deallocatePin(_pins[1], PinOwner::BusDigital); - pinManager.deallocatePin(_pins[0], PinOwner::BusDigital); + PinManager::deallocatePin(_pins[1], PinOwner::BusDigital); + PinManager::deallocatePin(_pins[0], PinOwner::BusDigital); } @@ -464,16 +464,16 @@ BusPwm::BusPwm(BusConfig &bc) managed_pin_type pins[numPins]; for (unsigned i = 0; i < numPins; i++) pins[i] = {(int8_t)bc.pins[i], true}; - if (!pinManager.allocateMultiplePins(pins, numPins, PinOwner::BusPwm)) return; + if (!PinManager::allocateMultiplePins(pins, numPins, PinOwner::BusPwm)) return; #ifdef ESP8266 analogWriteRange((1<<_depth)-1); analogWriteFreq(_frequency); #else // for 2 pin PWM CCT strip pinManager will make sure both LEDC channels are in the same speed group and sharing the same timer - _ledcStart = pinManager.allocateLedc(numPins); + _ledcStart = PinManager::allocateLedc(numPins); if (_ledcStart == 255) { //no more free LEDC channels - pinManager.deallocateMultiplePins(pins, numPins, PinOwner::BusPwm); + PinManager::deallocateMultiplePins(pins, numPins, PinOwner::BusPwm); return; } // if _needsRefresh is true (UI hack) we are using dithering (credit @dedehai & @zalatnaicsongor) @@ -640,8 +640,8 @@ std::vector BusPwm::getLEDTypes() { void BusPwm::deallocatePins() { unsigned numPins = getPins(); for (unsigned i = 0; i < numPins; i++) { - pinManager.deallocatePin(_pins[i], PinOwner::BusPwm); - if (!pinManager.isPinOk(_pins[i])) continue; + PinManager::deallocatePin(_pins[i], PinOwner::BusPwm); + if (!PinManager::isPinOk(_pins[i])) continue; #ifdef ESP8266 digitalWrite(_pins[i], LOW); //turn off PWM interrupt #else @@ -649,7 +649,7 @@ void BusPwm::deallocatePins() { #endif } #ifdef ARDUINO_ARCH_ESP32 - pinManager.deallocateLedc(_ledcStart, numPins); + PinManager::deallocateLedc(_ledcStart, numPins); #endif } @@ -661,7 +661,7 @@ BusOnOff::BusOnOff(BusConfig &bc) if (!Bus::isOnOff(bc.type)) return; uint8_t currentPin = bc.pins[0]; - if (!pinManager.allocatePin(currentPin, true, PinOwner::BusOnOff)) { + if (!PinManager::allocatePin(currentPin, true, PinOwner::BusOnOff)) { return; } _pin = currentPin; //store only after allocatePin() succeeds @@ -830,7 +830,7 @@ static String LEDTypesToJson(const std::vector& types) { String json; for (const auto &type : types) { // capabilities follows similar pattern as JSON API - int capabilities = Bus::hasRGB(type.id) | Bus::hasWhite(type.id)<<1 | Bus::hasCCT(type.id)<<2 | Bus::is16bit(type.id)<<4; + int capabilities = Bus::hasRGB(type.id) | Bus::hasWhite(type.id)<<1 | Bus::hasCCT(type.id)<<2 | Bus::is16bit(type.id)<<4 | Bus::mustRefresh(type.id)<<5; char str[256]; sprintf_P(str, PSTR("{i:%d,c:%d,t:\"%s\",n:\"%s\"},"), type.id, capabilities, type.type, type.name); json += str; @@ -904,7 +904,7 @@ void BusManager::esp32RMTInvertIdle() { void BusManager::on() { #ifdef ESP8266 //Fix for turning off onboard LED breaking bus - if (pinManager.getPinOwner(LED_BUILTIN) == PinOwner::BusDigital) { + if (PinManager::getPinOwner(LED_BUILTIN) == PinOwner::BusDigital) { for (unsigned i = 0; i < numBusses; i++) { uint8_t pins[2] = {255,255}; if (busses[i]->isDigital() && busses[i]->getPins(pins)) { @@ -926,7 +926,7 @@ void BusManager::off() { #ifdef ESP8266 // turn off built-in LED if strip is turned off // this will break digital bus so will need to be re-initialised on On - if (pinManager.getPinOwner(LED_BUILTIN) == PinOwner::BusDigital) { + if (PinManager::getPinOwner(LED_BUILTIN) == PinOwner::BusDigital) { for (unsigned i = 0; i < numBusses; i++) if (busses[i]->isOffRefreshRequired()) return; pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 24f10f0a7..e96b9de71 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -104,6 +104,7 @@ class Bus { inline bool isPWM() const { return isPWM(_type); } inline bool isVirtual() const { return isVirtual(_type); } inline bool is16bit() const { return is16bit(_type); } + inline bool mustRefresh() const { return mustRefresh(_type); } inline void setReversed(bool reversed) { _reversed = reversed; } inline void setStart(uint16_t start) { _start = start; } inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; } @@ -142,6 +143,7 @@ class Bus { static constexpr bool isPWM(uint8_t type) { return (type >= TYPE_ANALOG_MIN && type <= TYPE_ANALOG_MAX); } static constexpr bool isVirtual(uint8_t type) { return (type >= TYPE_VIRTUAL_MIN && type <= TYPE_VIRTUAL_MAX); } static constexpr bool is16bit(uint8_t type) { return type == TYPE_UCS8903 || type == TYPE_UCS8904 || type == TYPE_SM16825; } + static constexpr bool mustRefresh(uint8_t type) { return type == TYPE_TM1814; } static constexpr int numPWMPins(uint8_t type) { return (type - 40); } static inline int16_t getCCT() { return _cct; } @@ -280,7 +282,7 @@ class BusOnOff : public Bus { uint32_t getPixelColor(uint16_t pix) const override; uint8_t getPins(uint8_t* pinArray) const override; void show() override; - void cleanup() { pinManager.deallocatePin(_pin, PinOwner::BusOnOff); } + void cleanup() { PinManager::deallocatePin(_pin, PinOwner::BusOnOff); } static std::vector getLEDTypes(); diff --git a/wled00/button.cpp b/wled00/button.cpp index b5a4e9436..f02ed3d6d 100644 --- a/wled00/button.cpp +++ b/wled00/button.cpp @@ -267,7 +267,7 @@ void handleButton() if (btnPin[b]<0 || buttonType[b] == BTN_TYPE_NONE) continue; #endif - if (usermods.handleButton(b)) continue; // did usermod handle buttons + if (UsermodManager::handleButton(b)) continue; // did usermod handle buttons if (buttonType[b] == BTN_TYPE_ANALOG || buttonType[b] == BTN_TYPE_ANALOG_INVERTED) { // button is not a button but a potentiometer if (now - lastAnalogRead > ANALOG_BTN_READ_CYCLE) { diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index be63d2aa6..233386ce9 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -261,12 +261,12 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { JsonArray hw_btn_ins = btn_obj["ins"]; if (!hw_btn_ins.isNull()) { // deallocate existing button pins - for (unsigned b = 0; b < WLED_MAX_BUTTONS; b++) pinManager.deallocatePin(btnPin[b], PinOwner::Button); // does nothing if trying to deallocate a pin with PinOwner != Button + for (unsigned b = 0; b < WLED_MAX_BUTTONS; b++) PinManager::deallocatePin(btnPin[b], PinOwner::Button); // does nothing if trying to deallocate a pin with PinOwner != Button unsigned s = 0; for (JsonObject btn : hw_btn_ins) { CJSON(buttonType[s], btn["type"]); int8_t pin = btn["pin"][0] | -1; - if (pin > -1 && pinManager.allocatePin(pin, false, PinOwner::Button)) { + if (pin > -1 && PinManager::allocatePin(pin, false, PinOwner::Button)) { btnPin[s] = pin; #ifdef ARDUINO_ARCH_ESP32 // ESP32 only: check that analog button pin is a valid ADC gpio @@ -275,7 +275,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { // not an ADC analog pin DEBUG_PRINTF_P(PSTR("PIN ALLOC error: GPIO%d for analog button #%d is not an analog pin!\n"), btnPin[s], s); btnPin[s] = -1; - pinManager.deallocatePin(pin,PinOwner::Button); + PinManager::deallocatePin(pin,PinOwner::Button); } else { analogReadResolution(12); // see #4040 } @@ -286,7 +286,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { // not a touch pin DEBUG_PRINTF_P(PSTR("PIN ALLOC error: GPIO%d for touch button #%d is not a touch pin!\n"), btnPin[s], s); btnPin[s] = -1; - pinManager.deallocatePin(pin,PinOwner::Button); + PinManager::deallocatePin(pin,PinOwner::Button); } //if touch pin, enable the touch interrupt on ESP32 S2 & S3 #ifdef SOC_TOUCH_VERSION_2 // ESP32 S2 and S3 have a function to check touch state but need to attach an interrupt to do so @@ -331,7 +331,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { if (fromFS) { // relies upon only being called once with fromFS == true, which is currently true. for (size_t s = 0; s < WLED_MAX_BUTTONS; s++) { - if (buttonType[s] == BTN_TYPE_NONE || btnPin[s] < 0 || !pinManager.allocatePin(btnPin[s], false, PinOwner::Button)) { + if (buttonType[s] == BTN_TYPE_NONE || btnPin[s] < 0 || !PinManager::allocatePin(btnPin[s], false, PinOwner::Button)) { btnPin[s] = -1; buttonType[s] = BTN_TYPE_NONE; } @@ -358,8 +358,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { #ifndef WLED_DISABLE_INFRARED int hw_ir_pin = hw["ir"]["pin"] | -2; // 4 if (hw_ir_pin > -2) { - pinManager.deallocatePin(irPin, PinOwner::IR); - if (pinManager.allocatePin(hw_ir_pin, false, PinOwner::IR)) { + PinManager::deallocatePin(irPin, PinOwner::IR); + if (PinManager::allocatePin(hw_ir_pin, false, PinOwner::IR)) { irPin = hw_ir_pin; } else { irPin = -1; @@ -374,8 +374,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { rlyOpenDrain = relay[F("odrain")] | rlyOpenDrain; int hw_relay_pin = relay["pin"] | -2; if (hw_relay_pin > -2) { - pinManager.deallocatePin(rlyPin, PinOwner::Relay); - if (pinManager.allocatePin(hw_relay_pin,true, PinOwner::Relay)) { + PinManager::deallocatePin(rlyPin, PinOwner::Relay); + if (PinManager::allocatePin(hw_relay_pin,true, PinOwner::Relay)) { rlyPin = hw_relay_pin; pinMode(rlyPin, rlyOpenDrain ? OUTPUT_OPEN_DRAIN : OUTPUT); } else { @@ -394,7 +394,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(i2c_sda, hw_if_i2c[0]); CJSON(i2c_scl, hw_if_i2c[1]); PinManagerPinType i2c[2] = { { i2c_sda, true }, { i2c_scl, true } }; - if (i2c_scl >= 0 && i2c_sda >= 0 && pinManager.allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) { + if (i2c_scl >= 0 && i2c_sda >= 0 && PinManager::allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) { #ifdef ESP32 if (!Wire.setPins(i2c_sda, i2c_scl)) { i2c_scl = i2c_sda = -1; } // this will fail if Wire is initialised (Wire.begin() called prior) else Wire.begin(); @@ -410,7 +410,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(spi_sclk, hw_if_spi[1]); CJSON(spi_miso, hw_if_spi[2]); PinManagerPinType spi[3] = { { spi_mosi, true }, { spi_miso, true }, { spi_sclk, true } }; - if (spi_mosi >= 0 && spi_sclk >= 0 && pinManager.allocateMultiplePins(spi, 3, PinOwner::HW_SPI)) { + if (spi_mosi >= 0 && spi_sclk >= 0 && PinManager::allocateMultiplePins(spi, 3, PinOwner::HW_SPI)) { #ifdef ESP32 SPI.begin(spi_sclk, spi_miso, spi_mosi); // SPI global uses VSPI on ESP32 and FSPI on C3, S3 #else @@ -479,6 +479,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(receiveNotificationBrightness, if_sync_recv["bri"]); CJSON(receiveNotificationColor, if_sync_recv["col"]); CJSON(receiveNotificationEffects, if_sync_recv["fx"]); + CJSON(receiveNotificationPalette, if_sync_recv["pal"]); CJSON(receiveGroups, if_sync_recv["grp"]); CJSON(receiveSegmentOptions, if_sync_recv["seg"]); CJSON(receiveSegmentBounds, if_sync_recv["sb"]); @@ -660,7 +661,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { DEBUG_PRINTLN(F("Starting usermod config.")); JsonObject usermods_settings = doc["um"]; if (!usermods_settings.isNull()) { - needsSave = !usermods.readFromConfig(usermods_settings); + needsSave = !UsermodManager::readFromConfig(usermods_settings); } if (fromFS) return needsSave; @@ -696,7 +697,7 @@ void deserializeConfigFromFS() { // save default values to /cfg.json // call readFromConfig() with an empty object so that usermods can initialize to defaults prior to saving JsonObject empty = JsonObject(); - usermods.readFromConfig(empty); + UsermodManager::readFromConfig(empty); serializeConfig(); // init Ethernet (in case default type is set at compile time) #ifdef WLED_USE_ETHERNET @@ -963,6 +964,7 @@ void serializeConfig() { if_sync_recv["bri"] = receiveNotificationBrightness; if_sync_recv["col"] = receiveNotificationColor; if_sync_recv["fx"] = receiveNotificationEffects; + if_sync_recv["pal"] = receiveNotificationPalette; if_sync_recv["grp"] = receiveGroups; if_sync_recv["seg"] = receiveSegmentOptions; if_sync_recv["sb"] = receiveSegmentBounds; @@ -1113,7 +1115,7 @@ void serializeConfig() { #endif JsonObject usermods_settings = root.createNestedObject("um"); - usermods.addToConfig(usermods_settings); + UsermodManager::addToConfig(usermods_settings); File f = WLED_FS.open(FPSTR(s_cfg_json), "w"); if (f) serializeJson(root, f); diff --git a/wled00/data/common.js b/wled00/data/common.js new file mode 100644 index 000000000..9378ef07a --- /dev/null +++ b/wled00/data/common.js @@ -0,0 +1,118 @@ +var d=document; +var loc = false, locip, locproto = "http:"; + +function H(pg="") { window.open("https://kno.wled.ge/"+pg); } +function GH() { window.open("https://github.com/Aircoookie/WLED"); } +function gId(c) { return d.getElementById(c); } // getElementById +function cE(e) { return d.createElement(e); } // createElement +function gEBCN(c) { return d.getElementsByClassName(c); } // getElementsByClassName +function gN(s) { return d.getElementsByName(s)[0]; } // getElementsByName +function isE(o) { return Object.keys(o).length === 0; } // isEmpty +function isO(i) { return (i && typeof i === 'object' && !Array.isArray(i)); } // isObject +function isN(n) { return !isNaN(parseFloat(n)) && isFinite(n); } // isNumber +// https://stackoverflow.com/questions/3885817/how-do-i-check-that-a-number-is-float-or-integer +function isF(n) { return n === +n && n !== (n|0); } // isFloat +function isI(n) { return n === +n && n === (n|0); } // isInteger +function toggle(el) { gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide"); } +function tooltip(cont=null) { + d.querySelectorAll((cont?cont+" ":"")+"[title]").forEach((element)=>{ + element.addEventListener("mouseover", ()=>{ + // save title + element.setAttribute("data-title", element.getAttribute("title")); + const tooltip = d.createElement("span"); + tooltip.className = "tooltip"; + tooltip.textContent = element.getAttribute("title"); + + // prevent default title popup + element.removeAttribute("title"); + + let { top, left, width } = element.getBoundingClientRect(); + + d.body.appendChild(tooltip); + + const { offsetHeight, offsetWidth } = tooltip; + + const offset = element.classList.contains("sliderwrap") ? 4 : 10; + top -= offsetHeight + offset; + left += (width - offsetWidth) / 2; + + tooltip.style.top = top + "px"; + tooltip.style.left = left + "px"; + tooltip.classList.add("visible"); + }); + + element.addEventListener("mouseout", ()=>{ + d.querySelectorAll('.tooltip').forEach((tooltip)=>{ + tooltip.classList.remove("visible"); + d.body.removeChild(tooltip); + }); + // restore title + element.setAttribute("title", element.getAttribute("data-title")); + }); + }); +}; +// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript +function loadJS(FILE_URL, async = true, preGetV = undefined, postGetV = undefined) { + let scE = d.createElement("script"); + scE.setAttribute("src", FILE_URL); + scE.setAttribute("type", "text/javascript"); + scE.setAttribute("async", async); + d.body.appendChild(scE); + // success event + scE.addEventListener("load", () => { + //console.log("File loaded"); + if (preGetV) preGetV(); + GetV(); + if (postGetV) postGetV(); + }); + // error event + scE.addEventListener("error", (ev) => { + console.log("Error on loading file", ev); + alert("Loading of configuration script failed.\nIncomplete page data!"); + }); +} +function getLoc() { + let l = window.location; + if (l.protocol == "file:") { + loc = true; + locip = localStorage.getItem('locIp'); + if (!locip) { + locip = prompt("File Mode. Please enter WLED IP!"); + localStorage.setItem('locIp', locip); + } + } else { + // detect reverse proxy + let path = l.pathname; + let paths = path.slice(1,path.endsWith('/')?-1:undefined).split("/"); + if (paths.length > 1) paths.pop(); // remove subpage (or "settings") + if (paths.length > 0 && paths[paths.length-1]=="settings") paths.pop(); // remove "settings" + if (paths.length > 1) { + locproto = l.protocol; + loc = true; + locip = l.hostname + (l.port ? ":" + l.port : "") + "/" + paths.join('/'); + } + } +} +function getURL(path) { return (loc ? locproto + "//" + locip : "") + path; } +function B() { window.open(getURL("/settings"),"_self"); } +var timeout; +function showToast(text, error = false) { + var x = gId("toast"); + if (!x) return; + x.innerHTML = text; + x.className = error ? "error":"show"; + clearTimeout(timeout); + x.style.animation = 'none'; + timeout = setTimeout(function(){ x.className = x.className.replace("show", ""); }, 2900); +} +function uploadFile(fileObj, name) { + var req = new XMLHttpRequest(); + req.addEventListener('load', function(){showToast(this.responseText,this.status >= 400)}); + req.addEventListener('error', function(e){showToast(e.stack,true);}); + req.open("POST", "/upload"); + var formData = new FormData(); + formData.append("data", fileObj.files[0], name); + req.send(formData); + fileObj.value = ''; + return false; +} diff --git a/wled00/data/cpal/cpal.htm b/wled00/data/cpal/cpal.htm index a4b913592..b58c0987a 100644 --- a/wled00/data/cpal/cpal.htm +++ b/wled00/data/cpal/cpal.htm @@ -608,8 +608,8 @@ } function generatePaletteDivs() { - const palettesDiv = d.getElementById("palettes"); - const staticPalettesDiv = d.getElementById("staticPalettes"); + const palettesDiv = gId("palettes"); + const staticPalettesDiv = gId("staticPalettes"); const paletteDivs = Array.from(palettesDiv.children).filter((child) => { return child.id.match(/^palette\d$/); // match only elements with id starting with "palette" followed by a single digit }); @@ -620,25 +620,25 @@ for (let i = 0; i < paletteArray.length; i++) { const palette = paletteArray[i]; - const paletteDiv = d.createElement("div"); + const paletteDiv = cE("div"); paletteDiv.id = `palette${i}`; paletteDiv.classList.add("palette"); const thisKey = Object.keys(palette)[0]; paletteDiv.dataset.colarray = JSON.stringify(palette[thisKey]); - const gradientDiv = d.createElement("div"); + const gradientDiv = cE("div"); gradientDiv.id = `paletteGradient${i}` - const buttonsDiv = d.createElement("div"); + const buttonsDiv = cE("div"); buttonsDiv.id = `buttonsDiv${i}`; buttonsDiv.classList.add("buttonsDiv") - const sendSpan = d.createElement("span"); + const sendSpan = cE("span"); sendSpan.id = `sendSpan${i}`; sendSpan.onclick = function() {initiateUpload(i)}; sendSpan.setAttribute('title', `Send current editor to slot ${i}`); // perhaps Save instead of Send? sendSpan.innerHTML = svgSave; sendSpan.classList.add("sendSpan") - const editSpan = d.createElement("span"); + const editSpan = cE("span"); editSpan.id = `editSpan${i}`; editSpan.onclick = function() {loadForEdit(i)}; editSpan.setAttribute('title', `Copy slot ${i} palette to editor`); diff --git a/wled00/data/index.js b/wled00/data/index.js index 96b87c494..c266640d9 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -3207,7 +3207,7 @@ function simplifyUI() { createDropdown("palw", "Change palette"); createDropdown("fx", "Change effect", [gId("fxFind"), gId("fxlist")]); - // Hide pallete label + // Hide palette label gId("pall").style.display = "none"; gId("Colors").insertBefore(document.createElement("br"), gId("pall")); // Hide effect label diff --git a/wled00/data/pxmagic/pxmagic.htm b/wled00/data/pxmagic/pxmagic.htm index d59f924cf..8ec11f454 100644 --- a/wled00/data/pxmagic/pxmagic.htm +++ b/wled00/data/pxmagic/pxmagic.htm @@ -882,10 +882,8 @@ hostnameLabel(); })(); - function gId(id) { - return d.getElementById(id); - } - + function gId(e) {return d.getElementById(e);} + function cE(e) {return d.createElement(e);} function hostnameLabel() { const link = gId("wledEdit"); link.href = WLED_URL + "/edit"; @@ -1675,7 +1673,7 @@ } function createCanvas(width, height) { - const canvas = d.createElement("canvas"); + const canvas = cE("canvas"); canvas.width = width; canvas.height = height; @@ -1719,7 +1717,7 @@ const blob = new Blob([text], { type: mimeType }); const url = URL.createObjectURL(blob); - const anchorElement = d.createElement("a"); + const anchorElement = cE("a"); anchorElement.href = url; anchorElement.download = `${filename}.${fileExtension}`; @@ -1790,7 +1788,7 @@ hideElement = "preview" ) { const hide = gId(hideElement); - const toast = d.createElement("div"); + const toast = cE("div"); const wait = 100; toast.style.animation = "fadeIn"; @@ -1799,14 +1797,14 @@ toast.classList.add("toast", type); - const body = d.createElement("span"); + const body = cE("span"); body.classList.add("toast-body"); body.textContent = message; toast.appendChild(body); - const progress = d.createElement("div"); + const progress = cE("div"); progress.classList.add("toast-progress"); progress.style.animation = "progress"; @@ -1831,7 +1829,7 @@ function carousel(id, images, delay = 3000) { let index = 0; - const carousel = d.createElement("div"); + const carousel = cE("div"); carousel.classList.add("carousel"); images.forEach((canvas, i) => { @@ -1959,7 +1957,7 @@ let errorElement = parent.querySelector(".error-message"); if (!errorElement) { - errorElement = d.createElement("div"); + errorElement = cE("div"); errorElement.classList.add("error-message"); parent.appendChild(errorElement); } diff --git a/wled00/data/settings.htm b/wled00/data/settings.htm index 52b64006b..82c778214 100644 --- a/wled00/data/settings.htm +++ b/wled00/data/settings.htm @@ -4,53 +4,12 @@ WLED Settings +
-
+

Imma firin ma lazer (if it has DMX support)

diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 438b5b83d..8cc66e2bb 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -4,20 +4,12 @@ LED Settings +
-
+

LED & Hardware setup

@@ -861,7 +801,7 @@ Swap:  ✕
Apply IR change to main segment only:
- + IR info

Relay GPIO:  ✕
diff --git a/wled00/data/settings_sec.htm b/wled00/data/settings_sec.htm index ff8231ccb..ce9bd8aa3 100644 --- a/wled00/data/settings_sec.htm +++ b/wled00/data/settings_sec.htm @@ -4,55 +4,9 @@ Misc Settings +
-
+


diff --git a/wled00/data/settings_um.htm b/wled00/data/settings_um.htm index e2fbd5eb7..c2f0ffbf2 100644 --- a/wled00/data/settings_um.htm +++ b/wled00/data/settings_um.htm @@ -4,75 +4,55 @@ Usermod Settings +
-
+

WiFi setup

diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 0172377e2..a8aef13cf 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -317,34 +317,34 @@ class Usermod { class UsermodManager { private: - Usermod* ums[WLED_MAX_USERMODS]; - byte numMods = 0; + static Usermod* ums[WLED_MAX_USERMODS]; + static byte numMods; public: - void loop(); - void handleOverlayDraw(); - bool handleButton(uint8_t b); - bool getUMData(um_data_t **um_data, uint8_t mod_id = USERMOD_ID_RESERVED); // USERMOD_ID_RESERVED will poll all usermods - void setup(); - void connected(); - void appendConfigData(); - void addToJsonState(JsonObject& obj); - void addToJsonInfo(JsonObject& obj); - void readFromJsonState(JsonObject& obj); - void addToConfig(JsonObject& obj); - bool readFromConfig(JsonObject& obj); + static void loop(); + static void handleOverlayDraw(); + static bool handleButton(uint8_t b); + static bool getUMData(um_data_t **um_data, uint8_t mod_id = USERMOD_ID_RESERVED); // USERMOD_ID_RESERVED will poll all usermods + static void setup(); + static void connected(); + static void appendConfigData(); + static void addToJsonState(JsonObject& obj); + static void addToJsonInfo(JsonObject& obj); + static void readFromJsonState(JsonObject& obj); + static void addToConfig(JsonObject& obj); + static bool readFromConfig(JsonObject& obj); #ifndef WLED_DISABLE_MQTT - void onMqttConnect(bool sessionPresent); - bool onMqttMessage(char* topic, char* payload); + static void onMqttConnect(bool sessionPresent); + static bool onMqttMessage(char* topic, char* payload); #endif #ifndef WLED_DISABLE_ESPNOW - bool onEspNowMessage(uint8_t* sender, uint8_t* payload, uint8_t len); + static bool onEspNowMessage(uint8_t* sender, uint8_t* payload, uint8_t len); #endif - void onUpdateBegin(bool); - void onStateChange(uint8_t); - bool add(Usermod* um); - Usermod* lookup(uint16_t mod_id); - byte getModCount() {return numMods;}; + static void onUpdateBegin(bool); + static void onStateChange(uint8_t); + static bool add(Usermod* um); + static Usermod* lookup(uint16_t mod_id); + static inline byte getModCount() {return numMods;}; }; //usermods_list.cpp diff --git a/wled00/ir.cpp b/wled00/ir.cpp index 9e1974366..e4541cd90 100644 --- a/wled00/ir.cpp +++ b/wled00/ir.cpp @@ -714,9 +714,8 @@ void handleIR() if (strip.isUpdating() && timeDiff < 240) return; // be nice, but not too nice irCheckedTime = currentTime; if (irrecv->decode(&results)) { - if (results.value != 0) { // only print results if anything is received ( != 0 ) - if (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut) // Serial TX pin (GPIO 1 on ESP32 and ESP8266) - Serial.printf_P(PSTR("IR recv: 0x%lX\n"), (unsigned long)results.value); + if (results.value != 0 && serialCanTX) { // only print results if anything is received ( != 0 ) + Serial.printf_P(PSTR("IR recv: 0x%lX\n"), (unsigned long)results.value); } decodeIR(results.value); irrecv->resume(); diff --git a/wled00/json.cpp b/wled00/json.cpp index 6175a8dda..ed229e75a 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -441,7 +441,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId) } strip.resume(); - usermods.readFromJsonState(root); + UsermodManager::readFromJsonState(root); loadLedmap = root[F("ledmap")] | loadLedmap; @@ -600,7 +600,7 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme root[F("pl")] = currentPlaylist; root[F("ledmap")] = currentLedmap; - usermods.addToJsonState(root); + UsermodManager::addToJsonState(root); JsonObject nl = root.createNestedObject("nl"); nl["on"] = nightlightActive; @@ -792,7 +792,7 @@ void serializeInfo(JsonObject root) getTimeString(time); root[F("time")] = time; - usermods.addToJsonInfo(root); + UsermodManager::addToJsonInfo(root); uint16_t os = 0; #ifdef WLED_DEBUG diff --git a/wled00/led.cpp b/wled00/led.cpp index f96f73e82..ada0e57bb 100644 --- a/wled00/led.cpp +++ b/wled00/led.cpp @@ -126,7 +126,7 @@ void stateUpdated(byte callMode) { if (bri == nightlightTargetBri && callMode != CALL_MODE_NO_NOTIFY && nightlightMode != NL_MODE_SUN) nightlightActive = false; // notify usermods of state change - usermods.onStateChange(callMode); + UsermodManager::onStateChange(callMode); if (strip.getTransition() == 0) { jsonTransitionOnce = false; diff --git a/wled00/mqtt.cpp b/wled00/mqtt.cpp index 833e6eb7d..6c523c3eb 100644 --- a/wled00/mqtt.cpp +++ b/wled00/mqtt.cpp @@ -45,7 +45,7 @@ static void onMqttConnect(bool sessionPresent) mqtt->subscribe(subuf, 0); } - usermods.onMqttConnect(sessionPresent); + UsermodManager::onMqttConnect(sessionPresent); DEBUG_PRINTLN(F("MQTT ready")); publishMqtt(); @@ -89,7 +89,7 @@ static void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProp topic += topicPrefixLen; } else { // Non-Wled Topic used here. Probably a usermod subscribed to this topic. - usermods.onMqttMessage(topic, payloadStr); + UsermodManager::onMqttMessage(topic, payloadStr); delete[] payloadStr; payloadStr = nullptr; return; @@ -115,7 +115,7 @@ static void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProp } } else if (strlen(topic) != 0) { // non standard topic, check with usermods - usermods.onMqttMessage(topic, payloadStr); + UsermodManager::onMqttMessage(topic, payloadStr); } else { // topmost topic (just wled/MAC) parseMQTTBriPayload(payloadStr); diff --git a/wled00/overlay.cpp b/wled00/overlay.cpp index 239cff528..fcd0a40c2 100644 --- a/wled00/overlay.cpp +++ b/wled00/overlay.cpp @@ -88,7 +88,7 @@ void _overlayAnalogCountdown() } void handleOverlayDraw() { - usermods.handleOverlayDraw(); + UsermodManager::handleOverlayDraw(); if (analogClockSolidBlack) { const Segment* segments = strip.getSegments(); for (unsigned i = 0; i < strip.getSegmentsNum(); i++) { diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index 47cba2ec6..793b5440c 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -1,34 +1,28 @@ #include "pin_manager.h" #include "wled.h" -#ifdef WLED_DEBUG -static void DebugPrintOwnerTag(PinOwner tag) -{ - uint32_t q = static_cast(tag); - if (q) { - DEBUG_PRINTF_P(PSTR("0x%02x (%d)"), q, q); - } else { - DEBUG_PRINT(F("(no owner)")); - } -} +#ifdef ARDUINO_ARCH_ESP32 + #ifdef bitRead + // Arduino variants assume 32 bit values + #undef bitRead + #undef bitSet + #undef bitClear + #define bitRead(var,bit) (((unsigned long long)(var)>>(bit))&0x1ULL) + #define bitSet(var,bit) ((var)|=(1ULL<<(bit))) + #define bitClear(var,bit) ((var)&=(~(1ULL<<(bit)))) + #endif #endif + /// Actual allocation/deallocation routines -bool PinManagerClass::deallocatePin(byte gpio, PinOwner tag) +bool PinManager::deallocatePin(byte gpio, PinOwner tag) { if (gpio == 0xFF) return true; // explicitly allow clients to free -1 as a no-op if (!isPinOk(gpio, false)) return false; // but return false for any other invalid pin // if a non-zero ownerTag, only allow de-allocation if the owner's tag is provided if ((ownerTag[gpio] != PinOwner::None) && (ownerTag[gpio] != tag)) { - #ifdef WLED_DEBUG - DEBUG_PRINT(F("PIN DEALLOC: IO ")); - DEBUG_PRINT(gpio); - DEBUG_PRINT(F(" allocated by ")); - DebugPrintOwnerTag(ownerTag[gpio]); - DEBUG_PRINT(F(", but attempted de-allocation by ")); - DebugPrintOwnerTag(tag); - #endif + DEBUG_PRINTF_P(PSTR("PIN DEALLOC: FAIL GPIO %d allocated by 0x%02X, but attempted de-allocation by 0x%02X.\n"), gpio, static_cast(ownerTag[gpio]), static_cast(tag)); return false; } @@ -38,7 +32,7 @@ bool PinManagerClass::deallocatePin(byte gpio, PinOwner tag) } // support function for deallocating multiple pins -bool PinManagerClass::deallocateMultiplePins(const uint8_t *pinArray, byte arrayElementCount, PinOwner tag) +bool PinManager::deallocateMultiplePins(const uint8_t *pinArray, byte arrayElementCount, PinOwner tag) { bool shouldFail = false; DEBUG_PRINTLN(F("MULTIPIN DEALLOC")); @@ -54,14 +48,7 @@ bool PinManagerClass::deallocateMultiplePins(const uint8_t *pinArray, byte array // if the current pin is allocated by selected owner it is possible to release it continue; } - #ifdef WLED_DEBUG - DEBUG_PRINT(F("PIN DEALLOC: IO ")); - DEBUG_PRINT(gpio); - DEBUG_PRINT(F(" allocated by ")); - DebugPrintOwnerTag(ownerTag[gpio]); - DEBUG_PRINT(F(", but attempted de-allocation by ")); - DebugPrintOwnerTag(tag); - #endif + DEBUG_PRINTF_P(PSTR("PIN DEALLOC: FAIL GPIO %d allocated by 0x%02X, but attempted de-allocation by 0x%02X.\n"), gpio, static_cast(ownerTag[gpio]), static_cast(tag)); shouldFail = true; } if (shouldFail) { @@ -85,14 +72,14 @@ bool PinManagerClass::deallocateMultiplePins(const uint8_t *pinArray, byte array return true; } -bool PinManagerClass::deallocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag) +bool PinManager::deallocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag) { uint8_t pins[arrayElementCount]; for (int i=0; i(ownerTag[gpio])); shouldFail = true; } } @@ -146,64 +122,45 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by bitWrite(pinAlloc, gpio, true); ownerTag[gpio] = tag; - #ifdef WLED_DEBUG - DEBUG_PRINT(F("PIN ALLOC: Pin ")); - DEBUG_PRINT(gpio); - DEBUG_PRINT(F(" allocated by ")); - DebugPrintOwnerTag(tag); - DEBUG_PRINTLN(F("")); - #endif + DEBUG_PRINTF_P(PSTR("PIN ALLOC: Pin %d allocated by 0x%02X.\n"), gpio, static_cast(tag)); } + DEBUG_PRINTF_P(PSTR("PIN ALLOC: 0x%014llX.\n"), (unsigned long long)pinAlloc); return true; } -bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag) +bool PinManager::allocatePin(byte gpio, bool output, PinOwner tag) { // HW I2C & SPI pins have to be allocated using allocateMultiplePins variant since there is always SCL/SDA pair if (!isPinOk(gpio, output) || (gpio >= WLED_NUM_PINS) || tag==PinOwner::HW_I2C || tag==PinOwner::HW_SPI) { #ifdef WLED_DEBUG if (gpio < 255) { // 255 (-1) is the "not defined GPIO" if (!isPinOk(gpio, output)) { - DEBUG_PRINT(F("PIN ALLOC: FAIL for owner ")); - DebugPrintOwnerTag(tag); - DEBUG_PRINT(F(": GPIO ")); DEBUG_PRINT(gpio); + DEBUG_PRINTF_P(PSTR("PIN ALLOC: FAIL for owner 0x%02X: GPIO %d "), static_cast(tag), gpio); if (output) DEBUG_PRINTLN(F(" cannot be used for i/o on this MCU.")); else DEBUG_PRINTLN(F(" cannot be used as input on this MCU.")); } else { - DEBUG_PRINT(F("PIN ALLOC: FAIL: GPIO ")); DEBUG_PRINT(gpio); - DEBUG_PRINTLN(F(" - HW I2C & SPI pins have to be allocated using allocateMultiplePins()")); + DEBUG_PRINTF_P(PSTR("PIN ALLOC: FAIL GPIO %d - HW I2C & SPI pins have to be allocated using allocateMultiplePins.\n"), gpio); } } #endif return false; } if (isPinAllocated(gpio)) { - #ifdef WLED_DEBUG - DEBUG_PRINT(F("PIN ALLOC: Pin ")); - DEBUG_PRINT(gpio); - DEBUG_PRINT(F(" already allocated by ")); - DebugPrintOwnerTag(ownerTag[gpio]); - DEBUG_PRINTLN(F("")); - #endif + DEBUG_PRINTF_P(PSTR("PIN ALLOC: FAIL Pin %d already allocated by 0x%02X.\n"), gpio, static_cast(ownerTag[gpio])); return false; } bitWrite(pinAlloc, gpio, true); ownerTag[gpio] = tag; - #ifdef WLED_DEBUG - DEBUG_PRINT(F("PIN ALLOC: Pin ")); - DEBUG_PRINT(gpio); - DEBUG_PRINT(F(" successfully allocated by ")); - DebugPrintOwnerTag(tag); - DEBUG_PRINTLN(F("")); - #endif + DEBUG_PRINTF_P(PSTR("PIN ALLOC: Pin %d successfully allocated by 0x%02X.\n"), gpio, static_cast(ownerTag[gpio])); + DEBUG_PRINTF_P(PSTR("PIN ALLOC: 0x%014llX.\n"), (unsigned long long)pinAlloc); return true; } // if tag is set to PinOwner::None, checks for ANY owner of the pin. // if tag is set to any other value, checks if that tag is the current owner of the pin. -bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag) const +bool PinManager::isPinAllocated(byte gpio, PinOwner tag) { if (!isPinOk(gpio, false)) return true; if ((tag != PinOwner::None) && (ownerTag[gpio] != tag)) return false; @@ -227,7 +184,7 @@ bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag) const */ // Check if supplied GPIO is ok to use -bool PinManagerClass::isPinOk(byte gpio, bool output) const +bool PinManager::isPinOk(byte gpio, bool output) { if (gpio >= WLED_NUM_PINS) return false; // catch error case, to avoid array out-of-bounds access #ifdef ARDUINO_ARCH_ESP32 @@ -267,7 +224,7 @@ bool PinManagerClass::isPinOk(byte gpio, bool output) const return false; } -bool PinManagerClass::isReadOnlyPin(byte gpio) +bool PinManager::isReadOnlyPin(byte gpio) { #ifdef ARDUINO_ARCH_ESP32 if (gpio < WLED_NUM_PINS) return (digitalPinIsValid(gpio) && !digitalPinCanOutput(gpio)); @@ -275,14 +232,14 @@ bool PinManagerClass::isReadOnlyPin(byte gpio) return false; } -PinOwner PinManagerClass::getPinOwner(byte gpio) const +PinOwner PinManager::getPinOwner(byte gpio) { if (!isPinOk(gpio, false)) return PinOwner::None; return ownerTag[gpio]; } #ifdef ARDUINO_ARCH_ESP32 -byte PinManagerClass::allocateLedc(byte channels) +byte PinManager::allocateLedc(byte channels) { if (channels > WLED_MAX_ANALOG_CHANNELS || channels == 0) return 255; unsigned ca = 0; @@ -309,7 +266,7 @@ byte PinManagerClass::allocateLedc(byte channels) return 255; //not enough consecutive free LEDC channels } -void PinManagerClass::deallocateLedc(byte pos, byte channels) +void PinManager::deallocateLedc(byte pos, byte channels) { for (unsigned j = pos; j < pos + channels && j < WLED_MAX_ANALOG_CHANNELS; j++) { bitWrite(ledcAlloc, j, false); @@ -317,4 +274,12 @@ void PinManagerClass::deallocateLedc(byte pos, byte channels) } #endif -PinManagerClass pinManager = PinManagerClass(); +#ifdef ESP8266 +uint32_t PinManager::pinAlloc = 0UL; +#else +uint64_t PinManager::pinAlloc = 0ULL; +uint16_t PinManager::ledcAlloc = 0; +#endif +uint8_t PinManager::i2cAllocCount = 0; +uint8_t PinManager::spiAllocCount = 0; +PinOwner PinManager::ownerTag[WLED_NUM_PINS] = { PinOwner::None }; diff --git a/wled00/pin_manager.h b/wled00/pin_manager.h index a8ddf5f75..73a4a3656 100644 --- a/wled00/pin_manager.h +++ b/wled00/pin_manager.h @@ -70,57 +70,54 @@ enum struct PinOwner : uint8_t { }; static_assert(0u == static_cast(PinOwner::None), "PinOwner::None must be zero, so default array initialization works as expected"); -class PinManagerClass { +class PinManager { private: - struct { #ifdef ESP8266 - #define WLED_NUM_PINS (GPIO_PIN_COUNT+1) // somehow they forgot GPIO 16 (0-16==17) - uint32_t pinAlloc : 24; // 24bit, 1 bit per pin, we use first 17bits + #define WLED_NUM_PINS (GPIO_PIN_COUNT+1) // somehow they forgot GPIO 16 (0-16==17) + static uint32_t pinAlloc; // 1 bit per pin, we use first 17bits #else - #define WLED_NUM_PINS (GPIO_PIN_COUNT) - uint64_t pinAlloc : 56; // 56 bits, 1 bit per pin, we use 50 bits on ESP32-S3 - uint16_t ledcAlloc : 16; // up to 16 LEDC channels (WLED_MAX_ANALOG_CHANNELS) + #define WLED_NUM_PINS (GPIO_PIN_COUNT) + static uint64_t pinAlloc; // 1 bit per pin, we use 50 bits on ESP32-S3 + static uint16_t ledcAlloc; // up to 16 LEDC channels (WLED_MAX_ANALOG_CHANNELS) #endif - uint8_t i2cAllocCount : 4; // allow multiple allocation of I2C bus pins but keep track of allocations - uint8_t spiAllocCount : 4; // allow multiple allocation of SPI bus pins but keep track of allocations - } __attribute__ ((packed)); - PinOwner ownerTag[WLED_NUM_PINS] = { PinOwner::None }; + static uint8_t i2cAllocCount; // allow multiple allocation of I2C bus pins but keep track of allocations + static uint8_t spiAllocCount; // allow multiple allocation of SPI bus pins but keep track of allocations + static PinOwner ownerTag[WLED_NUM_PINS]; public: - PinManagerClass() : pinAlloc(0), i2cAllocCount(0), spiAllocCount(0) {} - // De-allocates a single pin - bool deallocatePin(byte gpio, PinOwner tag); - // De-allocates multiple pins but only if all can be deallocated (PinOwner has to be specified) - bool deallocateMultiplePins(const uint8_t *pinArray, byte arrayElementCount, PinOwner tag); - bool deallocateMultiplePins(const managed_pin_type *pinArray, byte arrayElementCount, PinOwner tag); - // Allocates a single pin, with an owner tag. - // De-allocation requires the same owner tag (or override) - bool allocatePin(byte gpio, bool output, PinOwner tag); - // Allocates all the pins, or allocates none of the pins, with owner tag. - // Provided to simplify error condition handling in clients - // using more than one pin, such as I2C, SPI, rotary encoders, - // ethernet, etc.. - bool allocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag ); + // De-allocates a single pin + static bool deallocatePin(byte gpio, PinOwner tag); + // De-allocates multiple pins but only if all can be deallocated (PinOwner has to be specified) + static bool deallocateMultiplePins(const uint8_t *pinArray, byte arrayElementCount, PinOwner tag); + static bool deallocateMultiplePins(const managed_pin_type *pinArray, byte arrayElementCount, PinOwner tag); + // Allocates a single pin, with an owner tag. + // De-allocation requires the same owner tag (or override) + static bool allocatePin(byte gpio, bool output, PinOwner tag); + // Allocates all the pins, or allocates none of the pins, with owner tag. + // Provided to simplify error condition handling in clients + // using more than one pin, such as I2C, SPI, rotary encoders, + // ethernet, etc.. + static bool allocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag ); - [[deprecated("Replaced by three-parameter allocatePin(gpio, output, ownerTag), for improved debugging")]] - inline bool allocatePin(byte gpio, bool output = true) { return allocatePin(gpio, output, PinOwner::None); } - [[deprecated("Replaced by two-parameter deallocatePin(gpio, ownerTag), for improved debugging")]] - inline void deallocatePin(byte gpio) { deallocatePin(gpio, PinOwner::None); } + [[deprecated("Replaced by three-parameter allocatePin(gpio, output, ownerTag), for improved debugging")]] + static inline bool allocatePin(byte gpio, bool output = true) { return allocatePin(gpio, output, PinOwner::None); } + [[deprecated("Replaced by two-parameter deallocatePin(gpio, ownerTag), for improved debugging")]] + static inline void deallocatePin(byte gpio) { deallocatePin(gpio, PinOwner::None); } - // will return true for reserved pins - bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None) const; - // will return false for reserved pins - bool isPinOk(byte gpio, bool output = true) const; - - static bool isReadOnlyPin(byte gpio); + // will return true for reserved pins + static bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None); + // will return false for reserved pins + static bool isPinOk(byte gpio, bool output = true); + + static bool isReadOnlyPin(byte gpio); - PinOwner getPinOwner(byte gpio) const; + static PinOwner getPinOwner(byte gpio); - #ifdef ARDUINO_ARCH_ESP32 - byte allocateLedc(byte channels); - void deallocateLedc(byte pos, byte channels); - #endif + #ifdef ARDUINO_ARCH_ESP32 + static byte allocateLedc(byte channels); + static void deallocateLedc(byte pos, byte channels); + #endif }; -extern PinManagerClass pinManager; +//extern PinManager pinManager; #endif diff --git a/wled00/set.cpp b/wled00/set.cpp index 624e26472..519f8c000 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -104,18 +104,18 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) { int t = 0; - if (rlyPin>=0 && pinManager.isPinAllocated(rlyPin, PinOwner::Relay)) { - pinManager.deallocatePin(rlyPin, PinOwner::Relay); + if (rlyPin>=0 && PinManager::isPinAllocated(rlyPin, PinOwner::Relay)) { + PinManager::deallocatePin(rlyPin, PinOwner::Relay); } #ifndef WLED_DISABLE_INFRARED - if (irPin>=0 && pinManager.isPinAllocated(irPin, PinOwner::IR)) { + if (irPin>=0 && PinManager::isPinAllocated(irPin, PinOwner::IR)) { deInitIR(); - pinManager.deallocatePin(irPin, PinOwner::IR); + PinManager::deallocatePin(irPin, PinOwner::IR); } #endif for (unsigned s=0; s=0 && pinManager.isPinAllocated(btnPin[s], PinOwner::Button)) { - pinManager.deallocatePin(btnPin[s], PinOwner::Button); + if (btnPin[s]>=0 && PinManager::isPinAllocated(btnPin[s], PinOwner::Button)) { + PinManager::deallocatePin(btnPin[s], PinOwner::Button); #ifdef SOC_TOUCH_VERSION_2 // ESP32 S2 and S3 have a function to check touch state, detach interrupt if (digitalPinToTouchChannel(btnPin[s]) >= 0) // if touch capable pin touchDetachInterrupt(btnPin[s]); // if not assigned previously, this will do nothing @@ -233,7 +233,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) // update other pins #ifndef WLED_DISABLE_INFRARED int hw_ir_pin = request->arg(F("IR")).toInt(); - if (pinManager.allocatePin(hw_ir_pin,false, PinOwner::IR)) { + if (PinManager::allocatePin(hw_ir_pin,false, PinOwner::IR)) { irPin = hw_ir_pin; } else { irPin = -1; @@ -244,7 +244,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) irApplyToAllSelected = !request->hasArg(F("MSO")); int hw_rly_pin = request->arg(F("RL")).toInt(); - if (pinManager.allocatePin(hw_rly_pin,true, PinOwner::Relay)) { + if (PinManager::allocatePin(hw_rly_pin,true, PinOwner::Relay)) { rlyPin = hw_rly_pin; } else { rlyPin = -1; @@ -259,7 +259,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) char bt[4] = "BT"; bt[2] = offset+i; bt[3] = 0; // button pin (use A,B,C,... if WLED_MAX_BUTTONS>10) char be[4] = "BE"; be[2] = offset+i; be[3] = 0; // button type (use A,B,C,... if WLED_MAX_BUTTONS>10) int hw_btn_pin = request->arg(bt).toInt(); - if (hw_btn_pin >= 0 && pinManager.allocatePin(hw_btn_pin,false,PinOwner::Button)) { + if (hw_btn_pin >= 0 && PinManager::allocatePin(hw_btn_pin,false,PinOwner::Button)) { btnPin[i] = hw_btn_pin; buttonType[i] = request->arg(be).toInt(); #ifdef ARDUINO_ARCH_ESP32 @@ -270,7 +270,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) // not an ADC analog pin DEBUG_PRINTF_P(PSTR("PIN ALLOC error: GPIO%d for analog button #%d is not an analog pin!\n"), btnPin[i], i); btnPin[i] = -1; - pinManager.deallocatePin(hw_btn_pin,PinOwner::Button); + PinManager::deallocatePin(hw_btn_pin,PinOwner::Button); } else { analogReadResolution(12); // see #4040 } @@ -282,7 +282,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) // not a touch pin DEBUG_PRINTF_P(PSTR("PIN ALLOC error: GPIO%d for touch button #%d is not an touch pin!\n"), btnPin[i], i); btnPin[i] = -1; - pinManager.deallocatePin(hw_btn_pin,PinOwner::Button); + PinManager::deallocatePin(hw_btn_pin,PinOwner::Button); } #ifdef SOC_TOUCH_VERSION_2 // ESP32 S2 and S3 have a fucntion to check touch state but need to attach an interrupt to do so else @@ -376,6 +376,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) receiveNotificationBrightness = request->hasArg(F("RB")); receiveNotificationColor = request->hasArg(F("RC")); receiveNotificationEffects = request->hasArg(F("RX")); + receiveNotificationPalette = request->hasArg(F("RP")); receiveSegmentOptions = request->hasArg(F("SO")); receiveSegmentBounds = request->hasArg(F("SG")); sendNotifications = request->hasArg(F("SS")); @@ -627,10 +628,10 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) if (i2c_sda != hw_sda_pin || i2c_scl != hw_scl_pin) { // only if pins changed uint8_t old_i2c[2] = { static_cast(i2c_scl), static_cast(i2c_sda) }; - pinManager.deallocateMultiplePins(old_i2c, 2, PinOwner::HW_I2C); // just in case deallocation of old pins + PinManager::deallocateMultiplePins(old_i2c, 2, PinOwner::HW_I2C); // just in case deallocation of old pins PinManagerPinType i2c[2] = { { hw_sda_pin, true }, { hw_scl_pin, true } }; - if (hw_sda_pin >= 0 && hw_scl_pin >= 0 && pinManager.allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) { + if (hw_sda_pin >= 0 && hw_scl_pin >= 0 && PinManager::allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) { i2c_sda = hw_sda_pin; i2c_scl = hw_scl_pin; // no bus re-initialisation as usermods do not get any notification @@ -654,9 +655,9 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) if (spi_mosi != hw_mosi_pin || spi_miso != hw_miso_pin || spi_sclk != hw_sclk_pin) { // only if pins changed uint8_t old_spi[3] = { static_cast(spi_mosi), static_cast(spi_miso), static_cast(spi_sclk) }; - pinManager.deallocateMultiplePins(old_spi, 3, PinOwner::HW_SPI); // just in case deallocation of old pins + PinManager::deallocateMultiplePins(old_spi, 3, PinOwner::HW_SPI); // just in case deallocation of old pins PinManagerPinType spi[3] = { { hw_mosi_pin, true }, { hw_miso_pin, true }, { hw_sclk_pin, true } }; - if (hw_mosi_pin >= 0 && hw_sclk_pin >= 0 && pinManager.allocateMultiplePins(spi, 3, PinOwner::HW_SPI)) { + if (hw_mosi_pin >= 0 && hw_sclk_pin >= 0 && PinManager::allocateMultiplePins(spi, 3, PinOwner::HW_SPI)) { spi_mosi = hw_mosi_pin; spi_miso = hw_miso_pin; spi_sclk = hw_sclk_pin; @@ -746,8 +747,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) DEBUG_PRINTF_P(PSTR(" = %s\n"), value.c_str()); } } - usermods.readFromConfig(um); // force change of usermod parameters - DEBUG_PRINTLN(F("Done re-init usermods.")); + UsermodManager::readFromConfig(um); // force change of usermod parameters + DEBUG_PRINTLN(F("Done re-init UsermodManager::")); releaseJSONBufferLock(); } diff --git a/wled00/udp.cpp b/wled00/udp.cpp index 246668ebb..e16d5b606 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -221,7 +221,7 @@ void parseNotifyPacket(uint8_t *udpIn) { if (!(receiveGroups & 0x01)) return; } else if (!(receiveGroups & udpIn[36])) return; - bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects); + bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects || receiveNotificationPalette); // set transition time before making any segment changes if (version > 3) { @@ -309,6 +309,9 @@ void parseNotifyPacket(uint8_t *udpIn) { selseg.setMode(udpIn[11+ofs]); selseg.speed = udpIn[12+ofs]; selseg.intensity = udpIn[13+ofs]; + } + if (receiveNotificationPalette || !someSel) { + DEBUG_PRINTF_P(PSTR("Apply palette: %u\n"), id); selseg.palette = udpIn[14+ofs]; } if (receiveNotificationColor || !someSel) { @@ -350,14 +353,16 @@ void parseNotifyPacket(uint8_t *udpIn) { } // simple effect sync, applies to all selected segments - if (applyEffects && (version < 11 || !receiveSegmentOptions)) { + if ((applyEffects || receiveNotificationPalette) && (version < 11 || !receiveSegmentOptions)) { for (size_t i = 0; i < strip.getSegmentsNum(); i++) { Segment& seg = strip.getSegment(i); if (!seg.isActive() || !seg.isSelected()) continue; - seg.setMode(udpIn[8]); - seg.speed = udpIn[9]; - if (version > 2) seg.intensity = udpIn[16]; - if (version > 4) seg.setPalette(udpIn[19]); + if (applyEffects) { + seg.setMode(udpIn[8]); + seg.speed = udpIn[9]; + if (version > 2) seg.intensity = udpIn[16]; + } + if (version > 4 && receiveNotificationPalette) seg.setPalette(udpIn[19]); } stateChanged = true; } @@ -969,7 +974,7 @@ void espNowReceiveCB(uint8_t* address, uint8_t* data, uint8_t len, signed int rs #ifndef WLED_DISABLE_ESPNOW // usermods hook can override processing - if (usermods.onEspNowMessage(address, data, len)) return; + if (UsermodManager::onEspNowMessage(address, data, len)) return; #endif // handle WiZ Mote data diff --git a/wled00/um_manager.cpp b/wled00/um_manager.cpp index 2db29c3cd..d4ed8135f 100644 --- a/wled00/um_manager.cpp +++ b/wled00/um_manager.cpp @@ -68,3 +68,6 @@ bool UsermodManager::add(Usermod* um) ums[numMods++] = um; return true; } + +Usermod* UsermodManager::ums[WLED_MAX_USERMODS] = {nullptr}; +byte UsermodManager::numMods = 0; diff --git a/wled00/usermods_list.cpp b/wled00/usermods_list.cpp index 25d9ee9ab..36bd122a5 100644 --- a/wled00/usermods_list.cpp +++ b/wled00/usermods_list.cpp @@ -249,225 +249,225 @@ void registerUsermods() * || || || * \/ \/ \/ */ - //usermods.add(new MyExampleUsermod()); + //UsermodManager::add(new MyExampleUsermod()); #ifdef USERMOD_BATTERY - usermods.add(new UsermodBattery()); + UsermodManager::add(new UsermodBattery()); #endif #ifdef USERMOD_DALLASTEMPERATURE - usermods.add(new UsermodTemperature()); + UsermodManager::add(new UsermodTemperature()); #endif #ifdef USERMOD_SN_PHOTORESISTOR - usermods.add(new Usermod_SN_Photoresistor()); + UsermodManager::add(new Usermod_SN_Photoresistor()); #endif #ifdef USERMOD_PWM_FAN - usermods.add(new PWMFanUsermod()); + UsermodManager::add(new PWMFanUsermod()); #endif #ifdef USERMOD_BUZZER - usermods.add(new BuzzerUsermod()); + UsermodManager::add(new BuzzerUsermod()); #endif #ifdef USERMOD_BH1750 - usermods.add(new Usermod_BH1750()); + UsermodManager::add(new Usermod_BH1750()); #endif #ifdef USERMOD_BME280 - usermods.add(new UsermodBME280()); + UsermodManager::add(new UsermodBME280()); #endif #ifdef USERMOD_BME68X - usermods.add(new UsermodBME68X()); + UsermodManager::add(new UsermodBME68X()); #endif #ifdef USERMOD_SENSORSTOMQTT - usermods.add(new UserMod_SensorsToMQTT()); + UsermodManager::add(new UserMod_SensorsToMQTT()); #endif #ifdef USERMOD_PIRSWITCH - usermods.add(new PIRsensorSwitch()); + UsermodManager::add(new PIRsensorSwitch()); #endif #ifdef USERMOD_FOUR_LINE_DISPLAY - usermods.add(new FourLineDisplayUsermod()); + UsermodManager::add(new FourLineDisplayUsermod()); #endif #ifdef USERMOD_ROTARY_ENCODER_UI - usermods.add(new RotaryEncoderUIUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY + UsermodManager::add(new RotaryEncoderUIUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY #endif #ifdef USERMOD_AUTO_SAVE - usermods.add(new AutoSaveUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY + UsermodManager::add(new AutoSaveUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY #endif #ifdef USERMOD_DHT - usermods.add(new UsermodDHT()); + UsermodManager::add(new UsermodDHT()); #endif #ifdef USERMOD_VL53L0X_GESTURES - usermods.add(new UsermodVL53L0XGestures()); + UsermodManager::add(new UsermodVL53L0XGestures()); #endif #ifdef USERMOD_ANIMATED_STAIRCASE - usermods.add(new Animated_Staircase()); + UsermodManager::add(new Animated_Staircase()); #endif #ifdef USERMOD_MULTI_RELAY - usermods.add(new MultiRelay()); + UsermodManager::add(new MultiRelay()); #endif #ifdef USERMOD_RTC - usermods.add(new RTCUsermod()); + UsermodManager::add(new RTCUsermod()); #endif #ifdef USERMOD_ELEKSTUBE_IPS - usermods.add(new ElekstubeIPSUsermod()); + UsermodManager::add(new ElekstubeIPSUsermod()); #endif #ifdef USERMOD_ROTARY_ENCODER_BRIGHTNESS_COLOR - usermods.add(new RotaryEncoderBrightnessColor()); + UsermodManager::add(new RotaryEncoderBrightnessColor()); #endif #ifdef RGB_ROTARY_ENCODER - usermods.add(new RgbRotaryEncoderUsermod()); + UsermodManager::add(new RgbRotaryEncoderUsermod()); #endif #ifdef USERMOD_ST7789_DISPLAY - usermods.add(new St7789DisplayUsermod()); + UsermodManager::add(new St7789DisplayUsermod()); #endif #ifdef USERMOD_PIXELS_DICE_TRAY - usermods.add(new PixelsDiceTrayUsermod()); + UsermodManager::add(new PixelsDiceTrayUsermod()); #endif #ifdef USERMOD_SEVEN_SEGMENT - usermods.add(new SevenSegmentDisplay()); + UsermodManager::add(new SevenSegmentDisplay()); #endif #ifdef USERMOD_SSDR - usermods.add(new UsermodSSDR()); + UsermodManager::add(new UsermodSSDR()); #endif #ifdef USERMOD_CRONIXIE - usermods.add(new UsermodCronixie()); + UsermodManager::add(new UsermodCronixie()); #endif #ifdef QUINLED_AN_PENTA - usermods.add(new QuinLEDAnPentaUsermod()); + UsermodManager::add(new QuinLEDAnPentaUsermod()); #endif #ifdef USERMOD_WIZLIGHTS - usermods.add(new WizLightsUsermod()); + UsermodManager::add(new WizLightsUsermod()); #endif #ifdef USERMOD_WIREGUARD - usermods.add(new WireguardUsermod()); + UsermodManager::add(new WireguardUsermod()); #endif #ifdef USERMOD_WORDCLOCK - usermods.add(new WordClockUsermod()); + UsermodManager::add(new WordClockUsermod()); #endif #ifdef USERMOD_MY9291 - usermods.add(new MY9291Usermod()); + UsermodManager::add(new MY9291Usermod()); #endif #ifdef USERMOD_SI7021_MQTT_HA - usermods.add(new Si7021_MQTT_HA()); + UsermodManager::add(new Si7021_MQTT_HA()); #endif #ifdef USERMOD_SMARTNEST - usermods.add(new Smartnest()); + UsermodManager::add(new Smartnest()); #endif #ifdef USERMOD_AUDIOREACTIVE - usermods.add(new AudioReactive()); + UsermodManager::add(new AudioReactive()); #endif #ifdef USERMOD_ANALOG_CLOCK - usermods.add(new AnalogClockUsermod()); + UsermodManager::add(new AnalogClockUsermod()); #endif #ifdef USERMOD_PING_PONG_CLOCK - usermods.add(new PingPongClockUsermod()); + UsermodManager::add(new PingPongClockUsermod()); #endif #ifdef USERMOD_ADS1115 - usermods.add(new ADS1115Usermod()); + UsermodManager::add(new ADS1115Usermod()); #endif #ifdef USERMOD_KLIPPER_PERCENTAGE - usermods.add(new klipper_percentage()); + UsermodManager::add(new klipper_percentage()); #endif #ifdef USERMOD_BOBLIGHT - usermods.add(new BobLightUsermod()); + UsermodManager::add(new BobLightUsermod()); #endif #ifdef SD_ADAPTER - usermods.add(new UsermodSdCard()); + UsermodManager::add(new UsermodSdCard()); #endif #ifdef USERMOD_PWM_OUTPUTS - usermods.add(new PwmOutputsUsermod()); + UsermodManager::add(new PwmOutputsUsermod()); #endif #ifdef USERMOD_SHT - usermods.add(new ShtUsermod()); + UsermodManager::add(new ShtUsermod()); #endif #ifdef USERMOD_ANIMARTRIX - usermods.add(new AnimartrixUsermod("Animartrix", false)); + UsermodManager::add(new AnimartrixUsermod("Animartrix", false)); #endif #ifdef USERMOD_INTERNAL_TEMPERATURE - usermods.add(new InternalTemperatureUsermod()); + UsermodManager::add(new InternalTemperatureUsermod()); #endif #ifdef USERMOD_HTTP_PULL_LIGHT_CONTROL - usermods.add(new HttpPullLightControl()); + UsermodManager::add(new HttpPullLightControl()); #endif #ifdef USERMOD_MPU6050_IMU - static MPU6050Driver mpu6050; usermods.add(&mpu6050); + static MPU6050Driver mpu6050; UsermodManager::add(&mpu6050); #endif #ifdef USERMOD_GYRO_SURGE - static GyroSurge gyro_surge; usermods.add(&gyro_surge); + static GyroSurge gyro_surge; UsermodManager::add(&gyro_surge); #endif #ifdef USERMOD_LDR_DUSK_DAWN - usermods.add(new LDR_Dusk_Dawn_v2()); + UsermodManager::add(new LDR_Dusk_Dawn_v2()); #endif #ifdef USERMOD_STAIRCASE_WIPE - usermods.add(new StairwayWipeUsermod()); + UsermodManager::add(new StairwayWipeUsermod()); #endif #ifdef USERMOD_MAX17048 - usermods.add(new Usermod_MAX17048()); + UsermodManager::add(new Usermod_MAX17048()); #endif #ifdef USERMOD_TETRISAI - usermods.add(new TetrisAIUsermod()); + UsermodManager::add(new TetrisAIUsermod()); #endif #ifdef USERMOD_AHT10 - usermods.add(new UsermodAHT10()); + UsermodManager::add(new UsermodAHT10()); #endif #ifdef USERMOD_INA226 - usermods.add(new UsermodINA226()); + UsermodManager::add(new UsermodINA226()); #endif #ifdef USERMOD_LD2410 - usermods.add(new LD2410Usermod()); + UsermodManager::add(new LD2410Usermod()); #endif #ifdef USERMOD_POV_DISPLAY - usermods.add(new PovDisplayUsermod()); + UsermodManager::add(new PovDisplayUsermod()); #endif } diff --git a/wled00/wled.cpp b/wled00/wled.cpp index f2b0fa223..eabdbd08d 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -54,23 +54,25 @@ void WLED::loop() #endif handleTime(); -#ifndef WLED_DISABLE_INFRARED + #ifndef WLED_DISABLE_INFRARED handleIR(); // 2nd call to function needed for ESP32 to return valid results -- should be good for ESP8266, too -#endif + #endif handleConnection(); + #ifdef WLED_ENABLE_ADALIGHT handleSerial(); + #endif handleImprovWifiScan(); handleNotifications(); handleTransitions(); -#ifdef WLED_ENABLE_DMX + #ifdef WLED_ENABLE_DMX handleDMX(); -#endif + #endif #ifdef WLED_DEBUG unsigned long usermodMillis = millis(); #endif userLoop(); - usermods.loop(); + UsermodManager::loop(); #ifdef WLED_DEBUG usermodMillis = millis() - usermodMillis; avgUsermodMillis += usermodMillis; @@ -408,10 +410,10 @@ void WLED::setup() #endif #if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST) - pinManager.allocatePin(hardwareTX, true, PinOwner::DebugOut); // TX (GPIO1 on ESP32) reserved for debug output + PinManager::allocatePin(hardwareTX, true, PinOwner::DebugOut); // TX (GPIO1 on ESP32) reserved for debug output #endif #ifdef WLED_ENABLE_DMX //reserve GPIO2 as hardcoded DMX pin - pinManager.allocatePin(2, true, PinOwner::DMX); + PinManager::allocatePin(2, true, PinOwner::DMX); #endif DEBUG_PRINTLN(F("Registering usermods ...")); @@ -450,7 +452,7 @@ void WLED::setup() DEBUG_PRINTF_P(PSTR("heap %u\n"), ESP.getFreeHeap()); #if defined(STATUSLED) && STATUSLED>=0 - if (!pinManager.isPinAllocated(STATUSLED)) { + if (!PinManager::isPinAllocated(STATUSLED)) { // NOTE: Special case: The status LED should *NOT* be allocated. // See comments in handleStatusLed(). pinMode(STATUSLED, OUTPUT); @@ -463,7 +465,7 @@ void WLED::setup() DEBUG_PRINTLN(F("Usermods setup")); userSetup(); - usermods.setup(); + UsermodManager::setup(); DEBUG_PRINTF_P(PSTR("heap %u\n"), ESP.getFreeHeap()); if (strcmp(multiWiFi[0].clientSSID, DEFAULT_CLIENT_SSID) == 0) @@ -476,10 +478,14 @@ void WLED::setup() WiFi.mode(WIFI_STA); // enable scanning findWiFi(true); // start scanning for available WiFi-s + // all GPIOs are allocated at this point + serialCanRX = !PinManager::isPinAllocated(hardwareRX); // Serial RX pin (GPIO 3 on ESP32 and ESP8266) + serialCanTX = !PinManager::isPinAllocated(hardwareTX) || PinManager::getPinOwner(hardwareTX) == PinOwner::DebugOut; // Serial TX pin (GPIO 1 on ESP32 and ESP8266) + #ifdef WLED_ENABLE_ADALIGHT //Serial RX (Adalight, Improv, Serial JSON) only possible if GPIO3 unused //Serial TX (Debug, Improv, Serial JSON) only possible if GPIO1 unused - if (!pinManager.isPinAllocated(hardwareRX) && !pinManager.isPinAllocated(hardwareTX)) { + if (serialCanRX && serialCanTX) { Serial.println(F("Ada")); } #endif @@ -491,10 +497,6 @@ void WLED::setup() if (mqttClientID[0] == 0) sprintf_P(mqttClientID, PSTR("WLED-%*s"), 6, escapedMac.c_str() + 6); #endif -#ifdef WLED_ENABLE_ADALIGHT - if (Serial.available() > 0 && Serial.peek() == 'I') handleImprovPacket(); -#endif - #ifndef WLED_DISABLE_OTA if (aOtaEnabled) { ArduinoOTA.onStart([]() { @@ -521,7 +523,7 @@ void WLED::setup() #endif #ifdef WLED_ENABLE_ADALIGHT - if (Serial.available() > 0 && Serial.peek() == 'I') handleImprovPacket(); + if (serialCanRX && Serial.available() > 0 && Serial.peek() == 'I') handleImprovPacket(); #endif // HTTP server page init @@ -683,7 +685,7 @@ bool WLED::initEthernet() return false; } - if (!pinManager.allocateMultiplePins(pinsToAllocate, 10, PinOwner::Ethernet)) { + if (!PinManager::allocateMultiplePins(pinsToAllocate, 10, PinOwner::Ethernet)) { DEBUG_PRINTLN(F("initE: Failed to allocate ethernet pins")); return false; } @@ -717,7 +719,7 @@ bool WLED::initEthernet() DEBUG_PRINTLN(F("initC: ETH.begin() failed")); // de-allocate the allocated pins for (managed_pin_type mpt : pinsToAllocate) { - pinManager.deallocatePin(mpt.pin, PinOwner::Ethernet); + PinManager::deallocatePin(mpt.pin, PinOwner::Ethernet); } return false; } @@ -1008,7 +1010,7 @@ void WLED::handleConnection() } initInterfaces(); userConnected(); - usermods.connected(); + UsermodManager::connected(); lastMqttReconnectAttempt = 0; // force immediate update // shut down AP @@ -1031,7 +1033,7 @@ void WLED::handleStatusLED() uint32_t c = 0; #if STATUSLED>=0 - if (pinManager.isPinAllocated(STATUSLED)) { + if (PinManager::isPinAllocated(STATUSLED)) { return; //lower priority if something else uses the same pin } #endif diff --git a/wled00/wled.h b/wled00/wled.h index 187571a7d..b33f5b9a2 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2409140 +#define VERSION 2409170 //uncomment this if you have a "my_config.h" file you'd like to use //#define WLED_USE_MY_CONFIG @@ -510,6 +510,8 @@ WLED_GLOBAL bool hueApplyColor _INIT(true); #endif WLED_GLOBAL uint16_t serialBaud _INIT(1152); // serial baud rate, multiply by 100 +WLED_GLOBAL bool serialCanRX _INIT(false); +WLED_GLOBAL bool serialCanTX _INIT(false); #ifndef WLED_DISABLE_ESPNOW WLED_GLOBAL bool enableESPNow _INIT(false); // global on/off for ESP-NOW @@ -638,17 +640,19 @@ typedef class Receive { bool SegmentOptions : 1; bool SegmentBounds : 1; bool Direct : 1; - uint8_t reserved : 2; + bool Palette : 1; + uint8_t reserved : 1; }; }; Receive(int i) { Options = i; } - Receive(bool b, bool c, bool e, bool sO, bool sB) { - Brightness = b; - Color = c; - Effects = e; - SegmentOptions = sO; - SegmentBounds = sB; - }; + Receive(bool b, bool c, bool e, bool sO, bool sB, bool p) + : Brightness(b) + , Color(c) + , Effects(e) + , SegmentOptions(sO) + , SegmentBounds(sB) + , Palette(p) + {}; } __attribute__ ((aligned(1), packed)) receive_notification_t; typedef class Send { public: @@ -670,11 +674,12 @@ typedef class Send { Hue = h; } } __attribute__ ((aligned(1), packed)) send_notification_t; -WLED_GLOBAL receive_notification_t receiveN _INIT(0b00100111); +WLED_GLOBAL receive_notification_t receiveN _INIT(0b01100111); WLED_GLOBAL send_notification_t notifyG _INIT(0b00001111); #define receiveNotificationBrightness receiveN.Brightness #define receiveNotificationColor receiveN.Color #define receiveNotificationEffects receiveN.Effects +#define receiveNotificationPalette receiveN.Palette #define receiveSegmentOptions receiveN.SegmentOptions #define receiveSegmentBounds receiveN.SegmentBounds #define receiveDirect receiveN.Direct @@ -686,6 +691,7 @@ WLED_GLOBAL send_notification_t notifyG _INIT(0b00001111); WLED_GLOBAL bool receiveNotificationBrightness _INIT(true); // apply brightness from incoming notifications WLED_GLOBAL bool receiveNotificationColor _INIT(true); // apply color WLED_GLOBAL bool receiveNotificationEffects _INIT(true); // apply effects setup +WLED_GLOBAL bool receiveNotificationPalette _INIT(true); // apply palette WLED_GLOBAL bool receiveSegmentOptions _INIT(false); // apply segment options WLED_GLOBAL bool receiveSegmentBounds _INIT(false); // apply segment bounds (start, stop, offset) WLED_GLOBAL bool receiveDirect _INIT(true); // receive UDP/Hyperion realtime diff --git a/wled00/wled_serial.cpp b/wled00/wled_serial.cpp index 3ca7c7f2f..ad9bb1413 100644 --- a/wled00/wled_serial.cpp +++ b/wled00/wled_serial.cpp @@ -28,7 +28,7 @@ void updateBaudRate(uint32_t rate){ if (rate100 == currentBaud || rate100 < 96) return; currentBaud = rate100; - if (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut){ + if (serialCanTX){ Serial.print(F("Baud is now ")); Serial.println(rate); } @@ -38,7 +38,7 @@ void updateBaudRate(uint32_t rate){ // RGB LED data return as JSON array. Slow, but easy to use on the other end. void sendJSON(){ - if (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut) { + if (serialCanTX) { unsigned used = strip.getLengthTotal(); Serial.write('['); for (unsigned i=0; ias()); - //only send response if TX pin is unused for other purposes - if (verboseResponse && (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut)) { - pDoc->clear(); - JsonObject state = pDoc->createNestedObject("state"); - serializeState(state); - JsonObject info = pDoc->createNestedObject("info"); - serializeInfo(info); + if (!error) { + verboseResponse = deserializeState(pDoc->as()); + //only send response if TX pin is unused for other purposes + if (verboseResponse && serialCanTX) { + pDoc->clear(); + JsonObject state = pDoc->createNestedObject("state"); + serializeState(state); + JsonObject info = pDoc->createNestedObject("info"); + serializeInfo(info); - serializeJson(*pDoc, Serial); - Serial.println(); + serializeJson(*pDoc, Serial); + Serial.println(); + } } releaseJSONBufferLock(); } @@ -199,11 +186,10 @@ void handleSerial() // All other received bytes will disable Continuous Serial Streaming if (continuousSendLED && next != 'O'){ continuousSendLED = false; - } + } Serial.read(); //discard the byte } - #endif // If Continuous Serial Streaming is enabled, send new LED data as bytes if (continuousSendLED && (lastUpdate != strip.getLastShow())){ diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index 291f6f5fc..7d6fecd8b 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -18,6 +18,7 @@ static const char s_unlock_ota [] PROGMEM = "Please unlock OTA in security setti static const char s_unlock_cfg [] PROGMEM = "Please unlock settings using PIN code!"; static const char s_notimplemented[] PROGMEM = "Not implemented"; static const char s_accessdenied[] PROGMEM = "Access Denied"; +static const char _common_js[] PROGMEM = "/common.js"; //Is this an IP? static bool isIp(String str) { @@ -237,6 +238,10 @@ void initServer() handleStaticContent(request, "", 200, FPSTR(CONTENT_TYPE_HTML), PAGE_liveview, PAGE_liveview_length); }); + server.on(_common_js, HTTP_GET, [](AsyncWebServerRequest *request) { + handleStaticContent(request, FPSTR(_common_js), 200, FPSTR(CONTENT_TYPE_JAVASCRIPT), JS_common, JS_common_length); + }); + //settings page server.on(F("/settings"), HTTP_GET, [](AsyncWebServerRequest *request){ serveSettings(request); @@ -391,7 +396,7 @@ void initServer() #if WLED_WATCHDOG_TIMEOUT > 0 WLED::instance().disableWatchdog(); #endif - usermods.onUpdateBegin(true); // notify usermods that update is about to begin (some may require task de-init) + UsermodManager::onUpdateBegin(true); // notify usermods that update is about to begin (some may require task de-init) lastEditTime = millis(); // make sure PIN does not lock during update strip.suspend(); #ifdef ESP8266 @@ -407,7 +412,7 @@ void initServer() } else { DEBUG_PRINTLN(F("Update Failed")); strip.resume(); - usermods.onUpdateBegin(false); // notify usermods that update has failed (some may require task init) + UsermodManager::onUpdateBegin(false); // notify usermods that update has failed (some may require task init) #if WLED_WATCHDOG_TIMEOUT > 0 WLED::instance().enableWatchdog(); #endif @@ -511,6 +516,10 @@ void serveJsonError(AsyncWebServerRequest* request, uint16_t code, uint16_t erro void serveSettingsJS(AsyncWebServerRequest* request) { + if (request->url().indexOf(FPSTR(_common_js)) > 0) { + handleStaticContent(request, FPSTR(_common_js), 200, FPSTR(CONTENT_TYPE_JAVASCRIPT), JS_common, JS_common_length); + return; + } char buf[SETTINGS_STACK_BUF_SIZE+37]; buf[0] = 0; byte subPage = request->arg(F("p")).toInt(); diff --git a/wled00/xml.cpp b/wled00/xml.cpp index 5b84ef99f..4106c4089 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -135,7 +135,7 @@ void appendGPIOinfo() { if (requestJSONBufferLock(6)) { // if we can't allocate JSON buffer ignore usermod pins JsonObject mods = pDoc->createNestedObject(F("um")); - usermods.addToConfig(mods); + UsermodManager::addToConfig(mods); if (!mods.isNull()) fillUMPins(mods); releaseJSONBufferLock(); } @@ -144,7 +144,7 @@ void appendGPIOinfo() { // add reserved (unusable) pins oappend(SET_F("d.rsvd=[")); for (unsigned i = 0; i < WLED_NUM_PINS; i++) { - if (!pinManager.isPinOk(i, false)) { // include readonly pins + if (!PinManager::isPinOk(i, false)) { // include readonly pins oappendi(i); oappend(","); } } @@ -181,7 +181,7 @@ void appendGPIOinfo() { oappend(SET_F("d.ro_gpio=[")); bool firstPin = true; for (unsigned i = 0; i < WLED_NUM_PINS; i++) { - if (pinManager.isReadOnlyPin(i)) { + if (PinManager::isReadOnlyPin(i)) { // No comma before the first pin if (!firstPin) oappend(SET_F(",")); oappendi(i); @@ -370,7 +370,7 @@ void getSettingsJS(byte subPage, char* dest) int nPins = bus->getPins(pins); for (int i = 0; i < nPins; i++) { lp[1] = offset+i; - if (pinManager.isPinOk(pins[i]) || bus->isVirtual()) sappend('v',lp,pins[i]); + if (PinManager::isPinOk(pins[i]) || bus->isVirtual()) sappend('v',lp,pins[i]); } sappend('v',lc,bus->getLength()); sappend('v',lt,bus->getType()); @@ -481,6 +481,7 @@ void getSettingsJS(byte subPage, char* dest) sappend('c',SET_F("RB"),receiveNotificationBrightness); sappend('c',SET_F("RC"),receiveNotificationColor); sappend('c',SET_F("RX"),receiveNotificationEffects); + sappend('c',SET_F("RP"),receiveNotificationPalette); sappend('c',SET_F("SO"),receiveSegmentOptions); sappend('c',SET_F("SG"),receiveSegmentBounds); sappend('c',SET_F("SS"),sendNotifications); @@ -567,6 +568,9 @@ void getSettingsJS(byte subPage, char* dest) oappend(SET_F("toggle('Hue');")); // hide Hue Sync settings #endif sappend('v',SET_F("BD"),serialBaud); + #ifndef WLED_ENABLE_ADALIGHT + oappend(SET_F("toggle('Serial);")); + #endif } if (subPage == SUBPAGE_TIME) @@ -687,7 +691,7 @@ void getSettingsJS(byte subPage, char* dest) { appendGPIOinfo(); oappend(SET_F("numM=")); - oappendi(usermods.getModCount()); + oappendi(UsermodManager::getModCount()); oappend(";"); sappend('v',SET_F("SDA"),i2c_sda); sappend('v',SET_F("SCL"),i2c_scl); @@ -699,7 +703,7 @@ void getSettingsJS(byte subPage, char* dest) oappend(SET_F("addInfo('MOSI','")); oappendi(HW_PIN_DATASPI); oappend(SET_F("');")); oappend(SET_F("addInfo('MISO','")); oappendi(HW_PIN_MISOSPI); oappend(SET_F("');")); oappend(SET_F("addInfo('SCLK','")); oappendi(HW_PIN_CLOCKSPI); oappend(SET_F("');")); - usermods.appendConfigData(); + UsermodManager::appendConfigData(); } if (subPage == SUBPAGE_UPDATE) // update