Merge branch '0_15' into feature/add-APA106-led

This commit is contained in:
Blaz Kristan 2024-01-31 17:21:55 +01:00
commit 5f1cadfea4
28 changed files with 504 additions and 355 deletions

View File

@ -1,7 +1,27 @@
## WLED changelog
#### Build 2309120 till build 2201060
#### Build 2309120 till build 2401270
- WLED version 0.15.0-a0
- BREAKING: Effect: updated Palette effect to support 2D (#3683 by @TripleWhy)
- "SuperSync" from WLED MM (by @MoonModules)
- Effect: DNA Spiral Effect Speed Fix (#3723 by @Derek4aty1)
- Fix for #3693
- Orange flash fix (#3196) for transitions
- Add own background image upload (#3596 by @WoodyLetsCode)
- WLED time overrides (`WLED_NTP_ENABLED`, `WLED_TIMEZONE`, `WLED_UTC_OFFSET`, `WLED_LAT` and `WLED_LON`)
- Better sorting and naming of static palettes (by @WoodyLetsCode)
- ANIMartRIX usermod and effects (#3673 by @netmindz)
- Use canvas instead of CSS gradient for liveview (#3621 by @zanhecht)
- Fix for #3672
- ColoOrderMap W channel swap (color order overrides now have W swap)
- En-/disable LED maps when receiving realtime data (#3554 by @ezcGman)
- Added PWM frequency selection to UI (Settings)
- Automatically build UI before compiling (#3598, #3666 by @WoodyLetsCode)
- Internal: Added *suspend* API to `strip` (`WS2812FX class`)
- Possible fix for #3589 & partial fix for #3605
- MPU6050 upgrade (#3654 by @willmmiles)
- UI internals (#3656 by @WoodyLetsCode)
- ColorPicker fix (#3658 by @WoodyLetsCode)
- Global JSON buffer guarding (#3648 by @willmmiles, resolves #3641, #3312, #3367, #3637, #3646, #3447)
- Effect: Fireworks 1D (fix for matrix trailing strip)
- BREAKING: Reduced number of segments (12) on ESP8266 due to less available RAM

View File

@ -87,7 +87,7 @@ class MyExampleUsermod : public Usermod {
* readFromConfig() is called prior to setup()
* You can use it to initialize variables, sensors or similar.
*/
void setup() {
void setup() override {
// do your set-up here
//Serial.println("Hello from my usermod!");
initDone = true;
@ -98,7 +98,7 @@ class MyExampleUsermod : public Usermod {
* connected() is called every time the WiFi is (re)connected
* Use it to initialize network interfaces
*/
void connected() {
void connected() override {
//Serial.println("Connected to WiFi!");
}
@ -113,7 +113,7 @@ class MyExampleUsermod : public Usermod {
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
* Instead, use a timer check as shown here.
*/
void loop() {
void loop() override {
// if usermod is disabled or called during strip updating just exit
// NOTE: on very long strips strip.isUpdating() may always return true so update accordingly
if (!enabled || strip.isUpdating()) return;
@ -131,7 +131,7 @@ class MyExampleUsermod : public Usermod {
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
* Below it is shown how this could be used for e.g. a light sensor
*/
void addToJsonInfo(JsonObject& root)
void addToJsonInfo(JsonObject& root) override
{
// if "u" object does not exist yet wee need to create it
JsonObject user = root["u"];
@ -156,7 +156,7 @@ class MyExampleUsermod : public Usermod {
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
void addToJsonState(JsonObject& root)
void addToJsonState(JsonObject& root) override
{
if (!initDone || !enabled) return; // prevent crash on boot applyPreset()
@ -171,7 +171,7 @@ class MyExampleUsermod : public Usermod {
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
void readFromJsonState(JsonObject& root)
void readFromJsonState(JsonObject& root) override
{
if (!initDone) return; // prevent crash on boot applyPreset()
@ -220,7 +220,7 @@ class MyExampleUsermod : public Usermod {
*
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/
void addToConfig(JsonObject& root)
void addToConfig(JsonObject& root) override
{
JsonObject top = root.createNestedObject(FPSTR(_name));
top[FPSTR(_enabled)] = enabled;
@ -253,7 +253,7 @@ class MyExampleUsermod : public Usermod {
*
* This function is guaranteed to be called on boot, but could also be called every time settings are updated
*/
bool readFromConfig(JsonObject& root)
bool readFromConfig(JsonObject& root) override
{
// default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor
// setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed)
@ -285,7 +285,7 @@ class MyExampleUsermod : public Usermod {
* it may add additional metadata for certain entry fields (adding drop down is possible)
* be careful not to add too much as oappend() buffer is limited to 3k
*/
void appendConfigData()
void appendConfigData() override
{
oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":great")); oappend(SET_F("',1,'<i>(this is a great config value)</i>');"));
oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":testString")); oappend(SET_F("',1,'enter any string you want');"));
@ -300,7 +300,7 @@ class MyExampleUsermod : public Usermod {
* Use this to blank out some LEDs or set them to a different color regardless of the set effect mode.
* Commonly used for custom clocks (Cronixie, 7 segment)
*/
void handleOverlayDraw()
void handleOverlayDraw() override
{
//strip.setPixelColor(0, RGBW32(0,0,0,0)) // set the first pixel to black
}
@ -311,7 +311,7 @@ class MyExampleUsermod : public Usermod {
* will prevent button working in a default way.
* Replicating button.cpp
*/
bool handleButton(uint8_t b) {
bool handleButton(uint8_t b) override {
yield();
// ignore certain button types as they may have other consequences
if (!enabled
@ -334,7 +334,7 @@ class MyExampleUsermod : public Usermod {
* handling of MQTT message
* topic only contains stripped topic (part after /wled/MAC)
*/
bool onMqttMessage(char* topic, char* payload) {
bool onMqttMessage(char* topic, char* payload) override {
// check if we received a command
//if (strlen(topic) == 8 && strncmp_P(topic, PSTR("/command"), 8) == 0) {
// String action = payload;
@ -355,7 +355,7 @@ class MyExampleUsermod : public Usermod {
/**
* onMqttConnect() is called when MQTT connection is established
*/
void onMqttConnect(bool sessionPresent) {
void onMqttConnect(bool sessionPresent) override {
// do any MQTT related initialisation here
//publishMqtt("I am alive!");
}
@ -366,7 +366,7 @@ class MyExampleUsermod : public Usermod {
* onStateChanged() is used to detect WLED state change
* @mode parameter is CALL_MODE_... parameter used for notifications
*/
void onStateChange(uint8_t mode) {
void onStateChange(uint8_t mode) override {
// do something if WLED state changed (color, brightness, effect, preset, etc)
}
@ -375,7 +375,7 @@ class MyExampleUsermod : public Usermod {
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
uint16_t getId()
uint16_t getId() override
{
return USERMOD_ID_EXAMPLE;
}

View File

@ -117,7 +117,7 @@ public:
* setup() is called once at boot. WiFi is not yet connected at this point.
* You can use it to initialize variables, sensors or similar.
*/
void setup();
void setup() override;
/**
* connected() is called every time the WiFi is (re)connected
@ -128,24 +128,24 @@ public:
/**
* onMqttConnect() is called when MQTT connection is established
*/
void onMqttConnect(bool sessionPresent);
void onMqttConnect(bool sessionPresent) override;
/**
* loop() is called continuously. Here you can check for events, read sensors, etc.
*/
void loop();
void loop() override;
/**
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
*
* Add PIR sensor state and switch off timer duration to jsoninfo
*/
void addToJsonInfo(JsonObject &root);
void addToJsonInfo(JsonObject &root) override;
/**
* onStateChanged() is used to detect WLED state change
*/
void onStateChange(uint8_t mode);
void onStateChange(uint8_t mode) override;
/**
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
@ -157,17 +157,17 @@ public:
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
void readFromJsonState(JsonObject &root);
void readFromJsonState(JsonObject &root) override;
/**
* provide the changeable values
*/
void addToConfig(JsonObject &root);
void addToConfig(JsonObject &root) override;
/**
* provide UI information and allow extending UI options
*/
void appendConfigData();
void appendConfigData() override;
/**
* restore the changeable values
@ -175,13 +175,13 @@ public:
*
* The function should return true if configuration was successfully loaded or false if there was no configuration.
*/
bool readFromConfig(JsonObject &root);
bool readFromConfig(JsonObject &root) override;
/**
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
uint16_t getId() { return USERMOD_ID_PIRSWITCH; }
uint16_t getId() override { return USERMOD_ID_PIRSWITCH; }
};
// strings to reduce flash memory usage (used more than twice)

View File

@ -188,7 +188,7 @@ class PWMFanUsermod : public Usermod {
// gets called once at boot. Do all initialization that doesn't depend on
// network here
void setup() {
void setup() override {
#ifdef USERMOD_DALLASTEMPERATURE
// This Usermod requires Temperature usermod
tempUM = (UsermodTemperature*) usermods.lookup(USERMOD_ID_TEMPERATURE);
@ -203,12 +203,12 @@ class PWMFanUsermod : public Usermod {
// gets called every time WiFi is (re-)connected. Initialize own network
// interfaces here
void connected() {}
void connected() override {}
/*
* Da loop.
*/
void loop() {
void loop() override {
if (!enabled || strip.isUpdating()) return;
unsigned long now = millis();
@ -223,7 +223,7 @@ class PWMFanUsermod : public Usermod {
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
* Below it is shown how this could be used for e.g. a light sensor
*/
void addToJsonInfo(JsonObject& root) {
void addToJsonInfo(JsonObject& root) override {
JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u");
@ -272,7 +272,7 @@ class PWMFanUsermod : public Usermod {
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
void readFromJsonState(JsonObject& root) {
void readFromJsonState(JsonObject& root) override {
if (!initDone) return; // prevent crash on boot applyPreset()
JsonObject usermod = root[FPSTR(_name)];
if (!usermod.isNull()) {
@ -305,7 +305,7 @@ class PWMFanUsermod : public Usermod {
*
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/
void addToConfig(JsonObject& root) {
void addToConfig(JsonObject& root) override {
JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
top[FPSTR(_enabled)] = enabled;
top[FPSTR(_pwmPin)] = pwmPin;
@ -328,7 +328,7 @@ class PWMFanUsermod : public Usermod {
*
* The function should return true if configuration was successfully loaded or false if there was no configuration.
*/
bool readFromConfig(JsonObject& root) {
bool readFromConfig(JsonObject& root) override {
int8_t newTachoPin = tachoPin;
int8_t newPwmPin = pwmPin;
@ -380,7 +380,7 @@ class PWMFanUsermod : public Usermod {
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
uint16_t getId() {
uint16_t getId() override {
return USERMOD_ID_PWM_FAN;
}
};

View File

@ -132,7 +132,7 @@ class St7789DisplayUsermod : public Usermod {
* setup() is called once at boot. WiFi is not yet connected at this point.
* You can use it to initialize variables, sensors or similar.
*/
void setup()
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; }
@ -162,7 +162,7 @@ class St7789DisplayUsermod : public Usermod {
* connected() is called every time the WiFi is (re)connected
* Use it to initialize network interfaces
*/
void connected() {
void connected() override {
//Serial.println("Connected to WiFi!");
}
@ -176,7 +176,7 @@ class St7789DisplayUsermod : public Usermod {
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
* Instead, use a timer check as shown here.
*/
void loop() {
void loop() override {
char buff[LINE_BUFFER_SIZE];
// Check if we time interval for redrawing passes.
@ -316,7 +316,7 @@ class St7789DisplayUsermod : public Usermod {
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
* Below it is shown how this could be used for e.g. a light sensor
*/
void addToJsonInfo(JsonObject& root)
void addToJsonInfo(JsonObject& root) override
{
JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u");
@ -330,7 +330,7 @@ class St7789DisplayUsermod : public Usermod {
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
void addToJsonState(JsonObject& root)
void addToJsonState(JsonObject& root) override
{
//root["user0"] = userVar0;
}
@ -340,7 +340,7 @@ class St7789DisplayUsermod : public Usermod {
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
void readFromJsonState(JsonObject& root)
void readFromJsonState(JsonObject& root) override
{
//userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
@ -361,7 +361,7 @@ class St7789DisplayUsermod : public Usermod {
*
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/
void addToConfig(JsonObject& root)
void addToConfig(JsonObject& root) override
{
JsonObject top = root.createNestedObject("ST7789");
JsonArray pins = top.createNestedArray("pin");
@ -373,7 +373,7 @@ class St7789DisplayUsermod : public Usermod {
}
void appendConfigData() {
void appendConfigData() override {
oappend(SET_F("addInfo('ST7789:pin[]',0,'','SPI CS');"));
oappend(SET_F("addInfo('ST7789:pin[]',1,'','SPI DC');"));
oappend(SET_F("addInfo('ST7789:pin[]',2,'','SPI RST');"));
@ -388,7 +388,7 @@ class St7789DisplayUsermod : public Usermod {
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
*/
bool readFromConfig(JsonObject& root)
bool readFromConfig(JsonObject& root) override
{
//JsonObject top = root["top"];
//userVar0 = top["great"] | 42; //The value right of the pipe "|" is the default value in case your setting was not present in cfg.json (e.g. first boot)
@ -400,7 +400,7 @@ class St7789DisplayUsermod : public Usermod {
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
uint16_t getId()
uint16_t getId() override
{
return USERMOD_ID_ST7789_DISPLAY;
}

View File

@ -76,26 +76,26 @@ class UsermodTemperature : public Usermod {
inline float getTemperatureF() { return temperature * 1.8f + 32.0f; }
float getTemperature();
const char *getTemperatureUnit();
uint16_t getId() { return USERMOD_ID_TEMPERATURE; }
uint16_t getId() override { return USERMOD_ID_TEMPERATURE; }
void setup();
void loop();
//void connected();
void setup() override;
void loop() override;
//void connected() override;
#ifndef WLED_DISABLE_MQTT
void onMqttConnect(bool sessionPresent);
void onMqttConnect(bool sessionPresent) override;
#endif
//void onUpdateBegin(bool init);
//void onUpdateBegin(bool init) override;
//bool handleButton(uint8_t b);
//void handleOverlayDraw();
//bool handleButton(uint8_t b) override;
//void handleOverlayDraw() override;
void addToJsonInfo(JsonObject& root);
//void addToJsonState(JsonObject &root);
//void readFromJsonState(JsonObject &root);
void addToConfig(JsonObject &root);
bool readFromConfig(JsonObject &root);
void addToJsonInfo(JsonObject& root) override;
//void addToJsonState(JsonObject &root) override;
//void readFromJsonState(JsonObject &root) override;
void addToConfig(JsonObject &root) override;
bool readFromConfig(JsonObject &root) override;
void appendConfigData();
void appendConfigData() override;
};
//Dallas sensor quick (& dirty) reading. Credit to - Author: Peter Scargill, August 17th, 2013

View File

@ -1094,7 +1094,7 @@ class AudioReactive : public Usermod {
* You can use it to initialize variables, sensors or similar.
* It is called *AFTER* readFromConfig()
*/
void setup()
void setup() override
{
disableSoundProcessing = true; // just to be sure
if (!initDone) {
@ -1217,7 +1217,7 @@ class AudioReactive : public Usermod {
* connected() is called every time the WiFi is (re)connected
* Use it to initialize network interfaces
*/
void connected()
void connected() override
{
if (udpSyncConnected) { // clean-up: if open, close old UDP sync connection
udpSyncConnected = false;
@ -1244,7 +1244,7 @@ class AudioReactive : public Usermod {
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
* Instead, use a timer check as shown here.
*/
void loop()
void loop() override
{
static unsigned long lastUMRun = millis();
@ -1375,7 +1375,7 @@ class AudioReactive : public Usermod {
}
bool getUMData(um_data_t **data)
bool getUMData(um_data_t **data) override
{
if (!data || !enabled) return false; // no pointer provided by caller or not enabled -> exit
*data = um_data;
@ -1383,7 +1383,7 @@ class AudioReactive : public Usermod {
}
void onUpdateBegin(bool init)
void onUpdateBegin(bool init) override
{
#ifdef WLED_DEBUG
fftTime = sampleTime = 0;
@ -1438,7 +1438,7 @@ class AudioReactive : public Usermod {
* handleButton() can be used to override default button behaviour. Returning true
* will prevent button working in a default way.
*/
bool handleButton(uint8_t b) {
bool handleButton(uint8_t b) override {
yield();
// crude way of determining if audio input is analog
// better would be for AudioSource to implement getType()
@ -1461,7 +1461,7 @@ class AudioReactive : public Usermod {
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
* Below it is shown how this could be used for e.g. a light sensor
*/
void addToJsonInfo(JsonObject& root)
void addToJsonInfo(JsonObject& root) override
{
char myStringBuffer[16]; // buffer for snprintf()
JsonObject user = root["u"];
@ -1600,7 +1600,7 @@ class AudioReactive : public Usermod {
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
void addToJsonState(JsonObject& root)
void addToJsonState(JsonObject& root) override
{
if (!initDone) return; // prevent crash on boot applyPreset()
JsonObject usermod = root[FPSTR(_name)];
@ -1615,7 +1615,7 @@ class AudioReactive : public Usermod {
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
void readFromJsonState(JsonObject& root)
void readFromJsonState(JsonObject& root) override
{
if (!initDone) return; // prevent crash on boot applyPreset()
bool prevEnabled = enabled;
@ -1640,7 +1640,7 @@ class AudioReactive : public Usermod {
}
}
void onStateChange(uint8_t callMode) {
void onStateChange(uint8_t callMode) override {
if (initDone && enabled && addPalettes && palettes==0 && strip.customPalettes.size()<10) {
// if palettes were removed during JSON call re-add them
createAudioPalettes();
@ -1682,7 +1682,7 @@ class AudioReactive : public Usermod {
*
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/
void addToConfig(JsonObject& root)
void addToConfig(JsonObject& root) override
{
JsonObject top = root.createNestedObject(FPSTR(_name));
top[FPSTR(_enabled)] = enabled;
@ -1735,7 +1735,7 @@ class AudioReactive : public Usermod {
*
* This function is guaranteed to be called on boot, but could also be called every time settings are updated
*/
bool readFromConfig(JsonObject& root)
bool readFromConfig(JsonObject& root) override
{
JsonObject top = root[FPSTR(_name)];
bool configComplete = !top.isNull();
@ -1786,7 +1786,7 @@ class AudioReactive : public Usermod {
}
void appendConfigData()
void appendConfigData() override
{
oappend(SET_F("dd=addDropdown('AudioReactive','digitalmic:type');"));
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
@ -1841,7 +1841,7 @@ class AudioReactive : public Usermod {
* Use this to blank out some LEDs or set them to a different color regardless of the set effect mode.
* Commonly used for custom clocks (Cronixie, 7 segment)
*/
//void handleOverlayDraw()
//void handleOverlayDraw() override
//{
//strip.setPixelColor(0, RGBW32(0,0,0,0)) // set the first pixel to black
//}
@ -1851,7 +1851,7 @@ class AudioReactive : public Usermod {
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
uint16_t getId()
uint16_t getId() override
{
return USERMOD_ID_AUDIOREACTIVE;
}

View File

@ -187,7 +187,7 @@ class BobLightUsermod : public Usermod {
public:
void setup() {
void setup() override {
uint16_t totalLights = bottom + left + top + right;
if ( totalLights > strip.getLengthTotal() ) {
DEBUG_PRINTLN(F("BobLight: Too many lights."));
@ -202,14 +202,14 @@ class BobLightUsermod : public Usermod {
initDone = true;
}
void connected() {
void connected() override {
// we can only start server when WiFi is connected
if (!bob) bob = new WiFiServer(bobPort, 1);
bob->begin();
bob->setNoDelay(true);
}
void loop() {
void loop() override {
if (!enabled || strip.isUpdating()) return;
if (millis() - lastTime > 10) {
lastTime = millis();
@ -225,7 +225,7 @@ class BobLightUsermod : public Usermod {
* topic only contains stripped topic (part after /wled/MAC)
* topic should look like: /swipe with amessage of [up|down]
*/
bool onMqttMessage(char* topic, char* payload) {
bool onMqttMessage(char* topic, char* payload) override {
//if (strlen(topic) == 6 && strncmp_P(topic, PSTR("/subtopic"), 6) == 0) {
// String action = payload;
// if (action == "on") {
@ -242,7 +242,7 @@ class BobLightUsermod : public Usermod {
/**
* subscribe to MQTT topic for controlling usermod
*/
void onMqttConnect(bool sessionPresent) {
void onMqttConnect(bool sessionPresent) override {
//char subuf[64];
//if (mqttDeviceTopic[0] != 0) {
// strcpy(subuf, mqttDeviceTopic);
@ -252,7 +252,7 @@ class BobLightUsermod : public Usermod {
}
#endif
void addToJsonInfo(JsonObject& root)
void addToJsonInfo(JsonObject& root) override
{
JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u");
@ -273,7 +273,7 @@ class BobLightUsermod : public Usermod {
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
void addToJsonState(JsonObject& root)
void addToJsonState(JsonObject& root) override
{
}
@ -281,7 +281,7 @@ class BobLightUsermod : public Usermod {
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
void readFromJsonState(JsonObject& root) {
void readFromJsonState(JsonObject& root) override {
if (!initDone) return; // prevent crash on boot applyPreset()
bool en = enabled;
JsonObject um = root[FPSTR(_name)];
@ -304,7 +304,7 @@ class BobLightUsermod : public Usermod {
}
}
void appendConfigData() {
void appendConfigData() override {
//oappend(SET_F("dd=addDropdown('usermod','selectfield');"));
//oappend(SET_F("addOption(dd,'1st value',0);"));
//oappend(SET_F("addOption(dd,'2nd value',1);"));
@ -315,7 +315,7 @@ class BobLightUsermod : public Usermod {
oappend(SET_F("addInfo('BobLight:pct',1,'Depth of scan [%]');")); // 0 is field type, 1 is actual field
}
void addToConfig(JsonObject& root) {
void addToConfig(JsonObject& root) override {
JsonObject umData = root.createNestedObject(FPSTR(_name));
umData[FPSTR(_enabled)] = enabled;
umData[F("port")] = bobPort;
@ -326,7 +326,7 @@ class BobLightUsermod : public Usermod {
umData[F("pct")] = pct;
}
bool readFromConfig(JsonObject& root) {
bool readFromConfig(JsonObject& root) override {
JsonObject umData = root[FPSTR(_name)];
bool configComplete = !umData.isNull();
@ -355,11 +355,11 @@ class BobLightUsermod : public Usermod {
* Use this to blank out some LEDs or set them to a different color regardless of the set effect mode.
* Commonly used for custom clocks (Cronixie, 7 segment)
*/
void handleOverlayDraw() {
void handleOverlayDraw() override {
//strip.setPixelColor(0, RGBW32(0,0,0,0)) // set the first pixel to black
}
uint16_t getId() { return USERMOD_ID_BOBLIGHT; }
uint16_t getId() override { return USERMOD_ID_BOBLIGHT; }
};
@ -445,7 +445,7 @@ void BobLightUsermod::pollBob() {
//strip.setPixelColor(light_id, RGBW32(red, green, blue, 0));
setRealtimePixel(light_id, red, green, blue, 0);
} // currently no support for interpolation or speed, we just ignore this
} else if (input.startsWith(F("sync"))) {
} else if (input.startsWith("sync")) {
BobSync();
} else {
// Client sent gibberish

View File

@ -143,7 +143,7 @@ class MultiRelay : public Usermod {
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
inline uint16_t getId() { return USERMOD_ID_MULTI_RELAY; }
inline uint16_t getId() override { return USERMOD_ID_MULTI_RELAY; }
/**
* switch relay on/off
@ -161,22 +161,22 @@ class MultiRelay : public Usermod {
* setup() is called once at boot. WiFi is not yet connected at this point.
* You can use it to initialize variables, sensors or similar.
*/
void setup();
void setup() override;
/**
* connected() is called every time the WiFi is (re)connected
* Use it to initialize network interfaces
*/
inline void connected() { InitHtmlAPIHandle(); }
inline void connected() override { InitHtmlAPIHandle(); }
/**
* loop() is called continuously. Here you can check for events, read sensors, etc.
*/
void loop();
void loop() override;
#ifndef WLED_DISABLE_MQTT
bool onMqttMessage(char* topic, char* payload);
void onMqttConnect(bool sessionPresent);
bool onMqttMessage(char* topic, char* payload) override;
void onMqttConnect(bool sessionPresent) override;
#endif
/**
@ -184,31 +184,31 @@ class MultiRelay : public Usermod {
* will prevent button working in a default way.
* Replicating button.cpp
*/
bool handleButton(uint8_t b);
bool handleButton(uint8_t b) override;
/**
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
*/
void addToJsonInfo(JsonObject &root);
void addToJsonInfo(JsonObject &root) override;
/**
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
void addToJsonState(JsonObject &root);
void addToJsonState(JsonObject &root) override;
/**
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
void readFromJsonState(JsonObject &root);
void readFromJsonState(JsonObject &root) override;
/**
* provide the changeable values
*/
void addToConfig(JsonObject &root);
void addToConfig(JsonObject &root) override;
void appendConfigData();
void appendConfigData() override;
/**
* restore the changeable values
@ -216,7 +216,7 @@ class MultiRelay : public Usermod {
*
* The function should return true if configuration was successfully loaded or false if there was no configuration.
*/
bool readFromConfig(JsonObject &root);
bool readFromConfig(JsonObject &root) override;
};

View File

@ -211,16 +211,16 @@ class FourLineDisplayUsermod : public Usermod {
// gets called once at boot. Do all initialization that doesn't depend on
// network here
void setup();
void setup() override;
// gets called every time WiFi is (re-)connected. Initialize own network
// interfaces here
void connected();
void connected() override;
/**
* Da loop.
*/
void loop();
void loop() override;
//function to update lastredraw
inline void updateRedrawTime() { lastRedraw = millis(); }
@ -287,28 +287,28 @@ class FourLineDisplayUsermod : public Usermod {
*/
bool handleButton(uint8_t b);
void onUpdateBegin(bool init);
void onUpdateBegin(bool init) override;
/*
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
* Below it is shown how this could be used for e.g. a light sensor
*/
//void addToJsonInfo(JsonObject& root);
//void addToJsonInfo(JsonObject& root) override;
/*
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
//void addToJsonState(JsonObject& root);
//void addToJsonState(JsonObject& root) override;
/*
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
//void readFromJsonState(JsonObject& root);
//void readFromJsonState(JsonObject& root) override;
void appendConfigData();
void appendConfigData() override;
/*
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
@ -324,7 +324,7 @@ class FourLineDisplayUsermod : public Usermod {
*
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/
void addToConfig(JsonObject& root);
void addToConfig(JsonObject& root) override;
/*
* readFromConfig() can be used to read back the custom settings you added with addToConfig().
@ -334,13 +334,13 @@ class FourLineDisplayUsermod : public Usermod {
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
*/
bool readFromConfig(JsonObject& root);
bool readFromConfig(JsonObject& root) override;
/*
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
uint16_t getId() {
uint16_t getId() override {
return USERMOD_ID_FOUR_LINE_DISP;
}
};

View File

@ -285,7 +285,7 @@ class RotaryEncoderUIUsermod : public Usermod {
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
uint16_t getId() { return USERMOD_ID_ROTARY_ENC_UI; }
uint16_t getId() override { return USERMOD_ID_ROTARY_ENC_UI; }
/**
* Enable/Disable the usermod
*/
@ -300,7 +300,7 @@ class RotaryEncoderUIUsermod : public Usermod {
* setup() is called once at boot. WiFi is not yet connected at this point.
* You can use it to initialize variables, sensors or similar.
*/
void setup();
void setup() override;
/**
* connected() is called every time the WiFi is (re)connected
@ -311,11 +311,11 @@ class RotaryEncoderUIUsermod : public Usermod {
/**
* loop() is called continuously. Here you can check for events, read sensors, etc.
*/
void loop();
void loop() override;
#ifndef WLED_DISABLE_MQTT
//bool onMqttMessage(char* topic, char* payload);
//void onMqttConnect(bool sessionPresent);
//bool onMqttMessage(char* topic, char* payload) override;
//void onMqttConnect(bool sessionPresent) override;
#endif
/**
@ -323,31 +323,31 @@ class RotaryEncoderUIUsermod : public Usermod {
* will prevent button working in a default way.
* Replicating button.cpp
*/
//bool handleButton(uint8_t b);
//bool handleButton(uint8_t b) override;
/**
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
*/
//void addToJsonInfo(JsonObject &root);
//void addToJsonInfo(JsonObject &root) override;
/**
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
//void addToJsonState(JsonObject &root);
//void addToJsonState(JsonObject &root) override;
/**
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
//void readFromJsonState(JsonObject &root);
//void readFromJsonState(JsonObject &root) override;
/**
* provide the changeable values
*/
void addToConfig(JsonObject &root);
void addToConfig(JsonObject &root) override;
void appendConfigData();
void appendConfigData() override;
/**
* restore the changeable values
@ -355,7 +355,7 @@ class RotaryEncoderUIUsermod : public Usermod {
*
* The function should return true if configuration was successfully loaded or false if there was no configuration.
*/
bool readFromConfig(JsonObject &root);
bool readFromConfig(JsonObject &root) override;
// custom methods
void displayNetworkInfo();

View File

@ -67,8 +67,8 @@ class WireguardUsermod : public Usermod {
JsonObject top = root.createNestedObject(F("WireGuard"));
top[F("host")] = endpoint_address;
top[F("port")] = endpoint_port;
top[F("ip")] = local_ip.toString();
top[F("psk")] = preshared_key;
top["ip"] = local_ip.toString();
top["psk"] = preshared_key;
top[F("pem")] = private_key;
top[F("pub")] = public_key;
top[F("tz")] = posix_tz;
@ -77,11 +77,11 @@ class WireguardUsermod : public Usermod {
bool readFromConfig(JsonObject& root) {
JsonObject top = root[F("WireGuard")];
if (top["host"].isNull() || top["port"].isNull() || top["ip"].isNull() || top["pem"].isNull() || top["pub"].isNull() || top["tz"].isNull()) {
if (top[F("host")].isNull() || top[F("port")].isNull() || top["ip"].isNull() || top[F("pem")].isNull() || top[F("pub")].isNull() || top[F("tz")].isNull()) {
is_enabled = false;
return false;
} else {
const char* host = top["host"];
const char* host = top[F("host")];
strncpy(endpoint_address, host, 100);
const char* ip_s = top["ip"];
@ -89,16 +89,16 @@ class WireguardUsermod : public Usermod {
sscanf(ip_s, "%u.%u.%u.%u", &ip[0], &ip[1], &ip[2], &ip[3]);
local_ip = IPAddress(ip[0], ip[1], ip[2], ip[3]);
const char* pem = top["pem"];
const char* pem = top[F("pem")];
strncpy(private_key, pem, 45);
const char* pub = top["pub"];
const char* pub = top[F("pub")];
strncpy(public_key, pub, 45);
const char* tz = top["tz"];
const char* tz = top[F("tz")];
strncpy(posix_tz, tz, 150);
endpoint_port = top["port"];
endpoint_port = top[F("port")];
if (!top["psk"].isNull()) {
const char* psk = top["psk"];

View File

@ -325,8 +325,8 @@ public:
void addToConfig(JsonObject& root)
{
JsonObject modName = root.createNestedObject("id");
modName["mdns"] = "wled-word-clock";
modName["name"] = "WLED WORD CLOCK";
modName[F("mdns")] = "wled-word-clock";
modName[F("name")] = "WLED WORD CLOCK";
}
uint16_t getId()

View File

@ -1848,10 +1848,10 @@ uint16_t mode_lightning(void) {
}
SEGENV.aux1--;
SEGENV.step = millis();
SEGENV.step = strip.now;
//return random8(4, 10); // each flash only lasts one frame/every 24ms... originally 4-10 milliseconds
} else {
if (millis() - SEGENV.step > SEGENV.aux0) {
if (strip.now - SEGENV.step > SEGENV.aux0) {
SEGENV.aux1--;
if (SEGENV.aux1 < 2) SEGENV.aux1 = 0;
@ -1859,7 +1859,7 @@ uint16_t mode_lightning(void) {
if (SEGENV.aux1 == 2) {
SEGENV.aux0 = (random8(255 - SEGMENT.speed) * 100); // delay between strikes
}
SEGENV.step = millis();
SEGENV.step = strip.now;
}
}
return FRAMETIME;
@ -1929,22 +1929,102 @@ static const char _data_FX_MODE_JUGGLE[] PROGMEM = "Juggle@!,Trail;;!;;sx=64,ix=
uint16_t mode_palette() {
uint16_t counter = 0;
if (SEGMENT.speed != 0)
{
counter = (strip.now * ((SEGMENT.speed >> 3) +1)) & 0xFFFF;
counter = counter >> 8;
}
// Set up some compile time constants so that we can handle integer and float based modes using the same code base.
#ifdef ESP8266
using mathType = int32_t;
using wideMathType = int64_t;
using angleType = uint16_t;
constexpr mathType sInt16Scale = 0x7FFF;
constexpr mathType maxAngle = 0x8000;
constexpr mathType staticRotationScale = 256;
constexpr mathType animatedRotationScale = 1;
constexpr int16_t (*sinFunction)(uint16_t) = &sin16;
constexpr int16_t (*cosFunction)(uint16_t) = &cos16;
#else
using mathType = float;
using wideMathType = float;
using angleType = float;
constexpr mathType sInt16Scale = 1.0f;
constexpr mathType maxAngle = M_PI / 256.0;
constexpr mathType staticRotationScale = 1.0f;
constexpr mathType animatedRotationScale = M_TWOPI / double(0xFFFF);
constexpr float (*sinFunction)(float) = &sin_t;
constexpr float (*cosFunction)(float) = &cos_t;
#endif
const bool isMatrix = strip.isMatrix;
const int cols = SEGMENT.virtualWidth();
const int rows = isMatrix ? SEGMENT.virtualHeight() : strip.getActiveSegmentsNum();
for (int i = 0; i < SEGLEN; i++)
{
uint8_t colorIndex = (i * 255 / SEGLEN) - counter;
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(colorIndex, false, PALETTE_MOVING_WRAP, 255));
}
const int inputShift = SEGMENT.speed;
const int inputSize = SEGMENT.intensity;
const int inputRotation = SEGMENT.custom1;
const bool inputAnimateShift = SEGMENT.check1;
const bool inputAnimateRotation = SEGMENT.check2;
const bool inputAssumeSquare = SEGMENT.check3;
const angleType theta = (!inputAnimateRotation) ? (inputRotation * maxAngle / staticRotationScale) : (((strip.now * ((inputRotation >> 4) +1)) & 0xFFFF) * animatedRotationScale);
const mathType sinTheta = sinFunction(theta);
const mathType cosTheta = cosFunction(theta);
const mathType maxX = std::max(1, cols-1);
const mathType maxY = std::max(1, rows-1);
// Set up some parameters according to inputAssumeSquare, so that we can handle anamorphic mode using the same code base.
const mathType maxXIn = inputAssumeSquare ? maxX : mathType(1);
const mathType maxYIn = inputAssumeSquare ? maxY : mathType(1);
const mathType maxXOut = !inputAssumeSquare ? maxX : mathType(1);
const mathType maxYOut = !inputAssumeSquare ? maxY : mathType(1);
const mathType centerX = sInt16Scale * maxXOut / mathType(2);
const mathType centerY = sInt16Scale * maxYOut / mathType(2);
// The basic idea for this effect is to rotate a rectangle that is filled with the palette along one axis, then map our
// display to it, to find what color a pixel should have.
// However, we want a) no areas of solid color (in front of or behind the palette), and b) we want to make use of the full palette.
// So the rectangle needs to have exactly the right size. That size depends on the rotation.
// This scale computation here only considers one dimension. You can think of it like the rectangle is always scaled so that
// the left and right most points always match the left and right side of the display.
const mathType scale = std::abs(sinTheta) + (std::abs(cosTheta) * maxYOut / maxXOut);
// 2D simulation:
// If we are dealing with a 1D setup, we assume that each segment represents one line on a 2-dimensional display.
// The function is called once per segments, so we need to handle one line at a time.
const int yFrom = isMatrix ? 0 : strip.getCurrSegmentId();
const int yTo = isMatrix ? maxY : yFrom;
for (int y = yFrom; y <= yTo; ++y) {
// translate, scale, rotate
const mathType ytCosTheta = mathType((wideMathType(cosTheta) * wideMathType(y * sInt16Scale - centerY * maxYIn))/wideMathType(maxYIn * scale));
for (int x = 0; x < cols; ++x) {
// translate, scale, rotate
const mathType xtSinTheta = mathType((wideMathType(sinTheta) * wideMathType(x * sInt16Scale - centerX * maxXIn))/wideMathType(maxXIn * scale));
// Map the pixel coordinate to an imaginary-rectangle-coordinate.
// The y coordinate doesn't actually matter, as our imaginary rectangle is filled with the palette from left to right,
// so all points at a given x-coordinate have the same color.
const mathType sourceX = xtSinTheta + ytCosTheta + centerX;
// The computation was scaled just right so that the result should always be in range [0, maxXOut], but enforce this anyway
// to account for imprecision. Then scale it so that the range is [0, 255], which we can use with the palette.
int colorIndex = (std::min(std::max(sourceX, mathType(0)), maxXOut * sInt16Scale) * 255) / (sInt16Scale * maxXOut);
// inputSize determines by how much we want to scale the palette:
// values < 128 display a fraction of a palette,
// values > 128 display multiple palettes.
if (inputSize <= 128) {
colorIndex = (colorIndex * inputSize) / 128;
} else {
// Linear function that maps colorIndex 128=>1, 256=>9.
// With this function every full palette repetition is exactly 16 configuration steps wide.
// That allows displaying exactly 2 repetitions for example.
colorIndex = ((inputSize - 112) * colorIndex) / 16;
}
// Finally, shift the palette a bit.
const int paletteOffset = (!inputAnimateShift) ? (inputShift-128) : (((strip.now * ((inputShift >> 3) +1)) & 0xFFFF) >> 8);
colorIndex += paletteOffset;
const uint32_t color = SEGMENT.color_wheel((uint8_t)colorIndex);
if (isMatrix) {
SEGMENT.setPixelColorXY(x, y, color);
} else {
SEGMENT.setPixelColor(x, color);
}
}
}
return FRAMETIME;
}
static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Cycle speed;;!;;c3=0,o2=0";
static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Shift,Size,Rotation,,,Animate Shift,Animate Rotation,Anamorphic;;!;12;c1=128,c2=128,c3=128,o1=1,o2=1,o3=0";
// WLED limitation: Analog Clock overlay will NOT work when Fire2012 is active
@ -2899,7 +2979,7 @@ uint16_t mode_bouncing_balls(void) {
uint16_t numBalls = (SEGMENT.intensity * (maxNumBalls - 1)) / 255 + 1; // minimum 1 ball
const float gravity = -9.81f; // standard value of gravity
const bool hasCol2 = SEGCOLOR(2);
const unsigned long time = millis();
const unsigned long time = strip.now;
if (SEGENV.call == 0) {
for (size_t i = 0; i < maxNumBalls; i++) balls[i].lastBounceTime = time;
@ -3336,7 +3416,7 @@ uint16_t mode_starburst(void) {
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
uint32_t it = millis();
uint32_t it = strip.now;
star* stars = reinterpret_cast<star*>(SEGENV.data);
@ -3692,7 +3772,7 @@ uint16_t mode_tetrix(void) {
// initialize dropping on first call or segment full
if (SEGENV.call == 0) {
drop->stack = 0; // reset brick stack size
drop->step = millis() + 2000; // start by fading out strip
drop->step = strip.now + 2000; // start by fading out strip
if (SEGMENT.check1) drop->col = 0;// use only one color from palette
}
@ -3726,13 +3806,13 @@ uint16_t mode_tetrix(void) {
} else { // we hit bottom
drop->step = 0; // proceed with next brick, go back to init
drop->stack += drop->brick; // increase the stack size
if (drop->stack >= SEGLEN) drop->step = millis() + 2000; // fade out stack
if (drop->stack >= SEGLEN) drop->step = strip.now + 2000; // fade out stack
}
}
if (drop->step > 2) { // fade strip
drop->brick = 0; // reset brick size (no more growing)
if (drop->step > millis()) {
if (drop->step > strip.now) {
// allow fading of virtual strip
for (int i = 0; i < SEGLEN; i++) SEGMENT.blendPixelColor(indexToVStrip(i, stripNr), SEGCOLOR(1), 25); // 10% blend
} else {
@ -3991,7 +4071,7 @@ uint16_t mode_sunrise() {
//speed 60 - 120 : sunset time in minutes - 60;
//speed above: "breathing" rise and set
if (SEGENV.call == 0 || SEGMENT.speed != SEGENV.aux0) {
SEGENV.step = millis(); //save starting time, millis() because now can change from sync
SEGENV.step = millis(); //save starting time, millis() because strip.now can change from sync
SEGENV.aux0 = SEGMENT.speed;
}
@ -4104,9 +4184,9 @@ uint16_t mode_noisepal(void) { // Slow noise
CRGBPalette16* palettes = reinterpret_cast<CRGBPalette16*>(SEGENV.data);
uint16_t changePaletteMs = 4000 + SEGMENT.speed *10; //between 4 - 6.5sec
if (millis() - SEGENV.step > changePaletteMs)
if (strip.now - SEGENV.step > changePaletteMs)
{
SEGENV.step = millis();
SEGENV.step = strip.now;
uint8_t baseI = random8();
palettes[1] = CRGBPalette16(CHSV(baseI+random8(64), 255, random8(128,255)), CHSV(baseI+128, 255, random8(128,255)), CHSV(baseI+random8(92), 192, random8(128,255)), CHSV(baseI+random8(92), 255, random8(128,255)));
@ -4261,7 +4341,7 @@ uint16_t mode_dancing_shadows(void)
SEGMENT.fill(BLACK);
unsigned long time = millis();
unsigned long time = strip.now;
bool respawn = false;
for (size_t i = 0; i < numSpotlights; i++) {
@ -4455,8 +4535,8 @@ uint16_t mode_tv_simulator(void) {
}
// create a new sceene
if (((millis() - tvSimulator->sceeneStart) >= tvSimulator->sceeneDuration) || SEGENV.aux1 == 0) {
tvSimulator->sceeneStart = millis(); // remember the start of the new sceene
if (((strip.now - tvSimulator->sceeneStart) >= tvSimulator->sceeneDuration) || SEGENV.aux1 == 0) {
tvSimulator->sceeneStart = strip.now; // remember the start of the new sceene
tvSimulator->sceeneDuration = random16(60* 250* colorSpeed, 60* 750 * colorSpeed); // duration of a "movie sceene" which has similar colors (5 to 15 minutes with max speed slider)
tvSimulator->sceeneColorHue = random16( 0, 768); // random start color-tone for the sceene
tvSimulator->sceeneColorSat = random8 ( 100, 130 + colorIntensity); // random start color-saturation for the sceene
@ -4507,11 +4587,11 @@ uint16_t mode_tv_simulator(void) {
tvSimulator->fadeTime = random16(0, tvSimulator->totalTime); // Pixel-to-pixel transition time
if (random8(10) < 3) tvSimulator->fadeTime = 0; // Force scene cut 30% of time
tvSimulator->startTime = millis();
tvSimulator->startTime = strip.now;
} // end of initialization
// how much time is elapsed ?
tvSimulator->elapsed = millis() - tvSimulator->startTime;
tvSimulator->elapsed = strip.now - tvSimulator->startTime;
// fade from prev volor to next color
if (tvSimulator->elapsed < tvSimulator->fadeTime) {
@ -4715,7 +4795,7 @@ uint16_t mode_perlinmove(void) {
if (SEGLEN == 1) return mode_static();
SEGMENT.fade_out(255-SEGMENT.custom1);
for (int i = 0; i < SEGMENT.intensity/16 + 1; i++) {
uint16_t locn = inoise16(millis()*128/(260-SEGMENT.speed)+i*15000, millis()*128/(260-SEGMENT.speed)); // Get a new pixel location from moving noise.
uint16_t locn = inoise16(strip.now*128/(260-SEGMENT.speed)+i*15000, strip.now*128/(260-SEGMENT.speed)); // Get a new pixel location from moving noise.
uint16_t pixloc = map(locn, 50*256, 192*256, 0, SEGLEN-1); // Map that to the length of the strand, and ensure we don't go over.
SEGMENT.setPixelColor(pixloc, SEGMENT.color_from_palette(pixloc%255, false, PALETTE_SOLID_WRAP, 0));
}
@ -4732,7 +4812,7 @@ static const char _data_FX_MODE_PERLINMOVE[] PROGMEM = "Perlin Move@!,# of pixel
uint16_t mode_wavesins(void) {
for (int i = 0; i < SEGLEN; i++) {
uint8_t bri = sin8(millis()/4 + i * SEGMENT.intensity);
uint8_t bri = sin8(strip.now/4 + i * SEGMENT.intensity);
uint8_t index = beatsin8(SEGMENT.speed, SEGMENT.custom1, SEGMENT.custom1+SEGMENT.custom2, 0, i * (SEGMENT.custom3<<3)); // custom3 is reduced resolution slider
//SEGMENT.setPixelColor(i, ColorFromPalette(SEGPALETTE, index, bri, LINEARBLEND));
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0, bri));
@ -4750,8 +4830,8 @@ static const char _data_FX_MODE_WAVESINS[] PROGMEM = "Wavesins@!,Brightness vari
uint16_t mode_FlowStripe(void) {
const uint16_t hl = SEGLEN * 10 / 13;
uint8_t hue = millis() / (SEGMENT.speed+1);
uint32_t t = millis() / (SEGMENT.intensity/8+1);
uint8_t hue = strip.now / (SEGMENT.speed+1);
uint32_t t = strip.now / (SEGMENT.intensity/8+1);
for (int i = 0; i < SEGLEN; i++) {
int c = (abs(i - hl) / hl) * 127;
@ -4781,7 +4861,7 @@ uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulma
uint16_t x, y;
SEGMENT.fadeToBlackBy(16 + (SEGMENT.speed>>3)); // create fading trails
unsigned long t = millis()/128; // timebase
unsigned long t = strip.now/128; // timebase
// outer stars
for (size_t i = 0; i < 8; i++) {
x = beatsin8(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + t * i);
@ -4867,8 +4947,8 @@ uint16_t mode_2Ddna(void) { // dna originally by by ldirko at https://pa
SEGMENT.fadeToBlackBy(64);
for (int i = 0; i < cols; i++) {
SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4 ), ColorFromPalette(SEGPALETTE, i*5+millis()/17, beatsin8(5, 55, 255, 0, i*10), LINEARBLEND));
SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4+128), ColorFromPalette(SEGPALETTE, i*5+128+millis()/17, beatsin8(5, 55, 255, 0, i*10+128), LINEARBLEND));
SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4 ), ColorFromPalette(SEGPALETTE, i*5+strip.now/17, beatsin8(5, 55, 255, 0, i*10), LINEARBLEND));
SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4+128), ColorFromPalette(SEGPALETTE, i*5+128+strip.now/17, beatsin8(5, 55, 255, 0, i*10+128), LINEARBLEND));
}
SEGMENT.blur(SEGMENT.intensity>>3);
@ -4880,7 +4960,7 @@ static const char _data_FX_MODE_2DDNA[] PROGMEM = "DNA@Scroll speed,Blur;;!;2";
/////////////////////////
// 2D DNA Spiral //
/////////////////////////
uint16_t mode_2DDNASpiral() { // By: ldirko https://editor.soulmatelights.com/gallery/810 , modified by: Andrew Tuline
uint16_t mode_2DDNASpiral() { // By: ldirko https://editor.soulmatelights.com/gallery/512-dna-spiral-variation , modified by: Andrew Tuline
if (!strip.isMatrix || !SEGMENT.is2D()) return mode_static(); // not a 2D set-up
const uint16_t cols = SEGMENT.virtualWidth();
@ -4890,10 +4970,10 @@ uint16_t mode_2DDNASpiral() { // By: ldirko https://editor.soulma
SEGMENT.fill(BLACK);
}
uint8_t speeds = SEGMENT.speed/2 + 1;
uint8_t speeds = SEGMENT.speed/2 + 7;
uint8_t freq = SEGMENT.intensity/8;
uint32_t ms = millis() / 20;
uint32_t ms = strip.now / 20;
SEGMENT.fadeToBlackBy(135);
for (int i = 0; i < rows; i++) {
@ -4933,7 +5013,7 @@ uint16_t mode_2DDrift() { // By: Stepko https://editor.soulmateli
SEGMENT.fadeToBlackBy(128);
const uint16_t maxDim = MAX(cols, rows)/2;
unsigned long t = millis() / (32 - (SEGMENT.speed>>3));
unsigned long t = strip.now / (32 - (SEGMENT.speed>>3));
unsigned long t_20 = t/20; // softhack007: pre-calculating this gives about 10% speedup
for (float i = 1; i < maxDim; i += 0.25) {
float angle = radians(t * (maxDim - i));
@ -4972,7 +5052,7 @@ uint16_t mode_2Dfirenoise(void) { // firenoise2d. By Andrew Tuline
for (int j=0; j < cols; j++) {
for (int i=0; i < rows; i++) {
indexx = inoise8(j*yscale*rows/255, i*xscale+millis()/4); // We're moving along our Perlin map.
indexx = inoise8(j*yscale*rows/255, i*xscale+strip.now/4); // We're moving along our Perlin map.
SEGMENT.setPixelColorXY(j, i, ColorFromPalette(SEGPALETTE, min(i*(indexx)>>4, 255), i*255/cols, LINEARBLEND)); // With that value, look up the 8 bit colour palette value and assign it to the current LED.
} // for i
} // for j
@ -5203,8 +5283,8 @@ uint16_t mode_2DJulia(void) { // An animated Julia set
reAl = -0.94299f; // PixelBlaze example
imAg = 0.3162f;
reAl += sin_t((float)millis()/305.f)/20.f;
imAg += sin_t((float)millis()/405.f)/20.f;
reAl += sin_t((float)strip.now/305.f)/20.f;
imAg += sin_t((float)strip.now/405.f)/20.f;
dx = (xmax - xmin) / (cols); // Scale the delta x and y values to our matrix size.
dy = (ymax - ymin) / (rows);
@ -5263,7 +5343,7 @@ uint16_t mode_2DLissajous(void) { // By: Andrew Tuline
const uint16_t rows = SEGMENT.virtualHeight();
SEGMENT.fadeToBlackBy(SEGMENT.intensity);
uint_fast16_t phase = (millis() * (1 + SEGENV.custom3)) /32; // allow user to control rotation speed
uint_fast16_t phase = (strip.now * (1 + SEGENV.custom3)) /32; // allow user to control rotation speed
//for (int i=0; i < 4*(cols+rows); i ++) {
for (int i=0; i < 256; i ++) {
@ -5273,7 +5353,7 @@ uint16_t mode_2DLissajous(void) { // By: Andrew Tuline
uint_fast8_t ylocn = cos8(phase/2 + i*2);
xlocn = (cols < 2) ? 1 : (map(2*xlocn, 0,511, 0,2*(cols-1)) +1) /2; // softhack007: "(2* ..... +1) /2" for proper rounding
ylocn = (rows < 2) ? 1 : (map(2*ylocn, 0,511, 0,2*(rows-1)) +1) /2; // "rows > 1" is needed to avoid div/0 in map()
SEGMENT.setPixelColorXY((uint8_t)xlocn, (uint8_t)ylocn, SEGMENT.color_from_palette(millis()/100+i, false, PALETTE_SOLID_WRAP, 0));
SEGMENT.setPixelColorXY((uint8_t)xlocn, (uint8_t)ylocn, SEGMENT.color_from_palette(strip.now/100+i, false, PALETTE_SOLID_WRAP, 0));
}
return FRAMETIME;
@ -5423,7 +5503,7 @@ uint16_t mode_2Dnoise(void) { // By Andrew Tuline
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
uint8_t pixelHue8 = inoise8(x * scale, y * scale, millis() / (16 - SEGMENT.speed/16));
uint8_t pixelHue8 = inoise8(x * scale, y * scale, strip.now / (16 - SEGMENT.speed/16));
SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, pixelHue8));
}
}
@ -5443,7 +5523,7 @@ uint16_t mode_2DPlasmaball(void) { // By: Stepko https://edito
const uint16_t rows = SEGMENT.virtualHeight();
SEGMENT.fadeToBlackBy(SEGMENT.custom1>>2);
uint_fast32_t t = (millis() * 8) / (256 - SEGMENT.speed); // optimized to avoid float
uint_fast32_t t = (strip.now * 8) / (256 - SEGMENT.speed); // optimized to avoid float
for (int i = 0; i < cols; i++) {
uint16_t thisVal = inoise8(i * 30, t, t);
uint16_t thisMax = map(thisVal, 0, 255, 0, cols-1);
@ -5561,7 +5641,7 @@ uint16_t mode_2DSindots(void) { // By: ldirko http
SEGMENT.fadeToBlackBy(SEGMENT.custom1>>3);
byte t1 = millis() / (257 - SEGMENT.speed); // 20;
byte t1 = strip.now / (257 - SEGMENT.speed); // 20;
byte t2 = sin8(t1) / 4 * 2;
for (int i = 0; i < 13; i++) {
byte x = sin8(t1 + i * SEGMENT.intensity/8)*(cols-1)/255; // max index now 255x15/255=15!
@ -5600,11 +5680,9 @@ uint16_t mode_2Dsquaredswirl(void) { // By: Mark Kriegsman. https://g
uint8_t n = beatsin8(15, kBorderWidth, rows-kBorderWidth);
uint8_t p = beatsin8(20, kBorderWidth, rows-kBorderWidth);
uint16_t ms = millis();
SEGMENT.addPixelColorXY(i, m, ColorFromPalette(SEGPALETTE, ms/29, 255, LINEARBLEND));
SEGMENT.addPixelColorXY(j, n, ColorFromPalette(SEGPALETTE, ms/41, 255, LINEARBLEND));
SEGMENT.addPixelColorXY(k, p, ColorFromPalette(SEGPALETTE, ms/73, 255, LINEARBLEND));
SEGMENT.addPixelColorXY(i, m, ColorFromPalette(SEGPALETTE, strip.now/29, 255, LINEARBLEND));
SEGMENT.addPixelColorXY(j, n, ColorFromPalette(SEGPALETTE, strip.now/41, 255, LINEARBLEND));
SEGMENT.addPixelColorXY(k, p, ColorFromPalette(SEGPALETTE, strip.now/73, 255, LINEARBLEND));
return FRAMETIME;
} // mode_2Dsquaredswirl()
@ -5627,7 +5705,7 @@ uint16_t mode_2DSunradiation(void) { // By: ldirko https://edi
SEGMENT.fill(BLACK);
}
unsigned long t = millis() / 4;
unsigned long t = strip.now / 4;
int index = 0;
uint8_t someVal = SEGMENT.speed/4; // Was 25.
for (int j = 0; j < (rows + 2); j++) {
@ -5759,14 +5837,14 @@ uint16_t mode_2Dcrazybees(void) {
int8_t deltaX, deltaY, signX, signY, error;
void aimed(uint16_t w, uint16_t h) {
//random16_set_seed(millis());
aimX = random8(0, w);
aimY = random8(0, h);
hue = random8();
aimX = random8(0, w);
aimY = random8(0, h);
hue = random8();
deltaX = abs(aimX - posX);
deltaY = abs(aimY - posY);
signX = posX < aimX ? 1 : -1;
signY = posY < aimY ? 1 : -1;
error = deltaX - deltaY;
signX = posX < aimX ? 1 : -1;
signY = posY < aimY ? 1 : -1;
error = deltaX - deltaY;
};
} bee_t;
@ -5774,6 +5852,7 @@ uint16_t mode_2Dcrazybees(void) {
bee_t *bee = reinterpret_cast<bee_t*>(SEGENV.data);
if (SEGENV.call == 0) {
random16_set_seed(strip.now);
for (size_t i = 0; i < n; i++) {
bee[i].posX = random8(0, cols);
bee[i].posY = random8(0, rows);
@ -5781,8 +5860,8 @@ uint16_t mode_2Dcrazybees(void) {
}
}
if (millis() > SEGENV.step) {
SEGENV.step = millis() + (FRAMETIME * 16 / ((SEGMENT.speed>>4)+1));
if (strip.now > SEGENV.step) {
SEGENV.step = strip.now + (FRAMETIME * 16 / ((SEGMENT.speed>>4)+1));
SEGMENT.fadeToBlackBy(32);
@ -5859,8 +5938,8 @@ uint16_t mode_2Dghostrider(void) {
}
}
if (millis() > SEGENV.step) {
SEGENV.step = millis() + 1024 / (cols+rows);
if (strip.now > SEGENV.step) {
SEGENV.step = strip.now + 1024 / (cols+rows);
SEGMENT.fadeToBlackBy((SEGMENT.speed>>2)+64);
@ -5948,7 +6027,7 @@ uint16_t mode_2Dfloatingblobs(void) {
// Bounce balls around
for (size_t i = 0; i < Amount; i++) {
if (SEGENV.step < millis()) blob->color[i] = add8(blob->color[i], 4); // slowly change color
if (SEGENV.step < strip.now) blob->color[i] = add8(blob->color[i], 4); // slowly change color
// change radius if needed
if (blob->grow[i]) {
// enlarge radius until it is >= 4
@ -5995,7 +6074,7 @@ uint16_t mode_2Dfloatingblobs(void) {
}
SEGMENT.blur(SEGMENT.custom1>>2);
if (SEGENV.step < millis()) SEGENV.step = millis() + 2000; // change colors every 2 seconds
if (SEGENV.step < strip.now) SEGENV.step = strip.now + 2000; // change colors every 2 seconds
return FRAMETIME;
}
@ -6059,13 +6138,12 @@ uint16_t mode_2Dscrollingtext(void) {
}
const int numberOfLetters = strlen(text);
const unsigned long now = millis(); // reduce millis() calls
int width = (numberOfLetters * rotLW);
int yoffset = map(SEGMENT.intensity, 0, 255, -rows/2, rows/2) + (rows-rotLH)/2;
if (width <= cols) {
// scroll vertically (e.g. ^^ Way out ^^) if it fits
int speed = map(SEGMENT.speed, 0, 255, 5000, 1000);
int frac = now % speed + 1;
int frac = strip.now % speed + 1;
if (SEGMENT.intensity == 255) {
yoffset = (2 * frac * rows)/speed - rows;
} else if (SEGMENT.intensity == 0) {
@ -6073,7 +6151,7 @@ uint16_t mode_2Dscrollingtext(void) {
}
}
if (SEGENV.step < now) {
if (SEGENV.step < strip.now) {
// calculate start offset
if (width > cols) {
if (SEGMENT.check3) {
@ -6082,7 +6160,7 @@ uint16_t mode_2Dscrollingtext(void) {
} else ++SEGENV.aux0 %= width + cols;
} else SEGENV.aux0 = (cols + width)/2;
++SEGENV.aux1 &= 0xFF; // color shift
SEGENV.step = now + map(SEGMENT.speed, 0, 255, 250, 50); // shift letters every ~250ms to ~50ms
SEGENV.step = strip.now + map(SEGMENT.speed, 0, 255, 250, 50); // shift letters every ~250ms to ~50ms
}
if (!SEGMENT.check2) SEGMENT.fade_out(255 - (SEGMENT.custom1>>4)); // trail
@ -6130,6 +6208,51 @@ uint16_t mode_2Ddriftrose(void) {
}
static const char _data_FX_MODE_2DDRIFTROSE[] PROGMEM = "Drift Rose@Fade,Blur;;;2";
/////////////////////////////
// 2D PLASMA ROTOZOOMER //
/////////////////////////////
// Plasma Rotozoomer by ldirko (c)2020 [https://editor.soulmatelights.com/gallery/457-plasma-rotozoomer], adapted for WLED by Blaz Kristan (AKA blazoncek)
uint16_t mode_2Dplasmarotozoom() {
if (!strip.isMatrix || !SEGMENT.is2D()) return mode_static(); // not a 2D set-up
const uint16_t cols = SEGMENT.virtualWidth();
const uint16_t rows = SEGMENT.virtualHeight();
uint16_t dataSize = SEGMENT.length() + sizeof(float);
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
float *a = reinterpret_cast<float*>(SEGENV.data);
byte *plasma = reinterpret_cast<byte*>(SEGENV.data+sizeof(float));
uint16_t ms = strip.now/15;
// plasma
for (int j = 0; j < rows; j++) {
int index = j*cols;
for (int i = 0; i < cols; i++) {
if (SEGMENT.check1) plasma[index+i] = (i * 4 ^ j * 4) + ms / 6;
else plasma[index+i] = inoise8(i * 40, j * 40, ms);
}
}
// rotozoom
float f = (sin_t(*a/2)+((128-SEGMENT.intensity)/128.0f)+1.1f)/1.5f; // scale factor
float kosinus = cos_t(*a) * f;
float sinus = sin_t(*a) * f;
for (int i = 0; i < cols; i++) {
float u1 = i * kosinus;
float v1 = i * sinus;
for (int j = 0; j < rows; j++) {
byte u = abs8(u1 - j * sinus) % cols;
byte v = abs8(v1 + j * kosinus) % rows;
SEGMENT.setPixelColorXY(i, j, SEGMENT.color_from_palette(plasma[v*cols+u], false, PALETTE_SOLID_WRAP, 0));
}
}
*a -= 0.03f + float(SEGENV.speed-128)*0.0002f; // rotation speed
return FRAMETIME;
}
static const char _data_FX_MODE_2DPLASMAROTOZOOM[] PROGMEM = "Rotozoomer@!,Scale,,,,Alt;;!;2;pal=54";
#endif // WLED_DISABLE_2D
@ -6280,7 +6403,6 @@ uint16_t mode_2DSwirl(void) {
uint8_t j = beatsin8( 41*SEGMENT.speed/255, borderWidth, rows - borderWidth);
uint8_t ni = (cols - 1) - i;
uint8_t nj = (cols - 1) - j;
uint16_t ms = millis();
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
@ -6290,12 +6412,12 @@ uint16_t mode_2DSwirl(void) {
float volumeSmth = *(float*) um_data->u_data[0]; //ewowi: use instead of sampleAvg???
int16_t volumeRaw = *(int16_t*) um_data->u_data[1];
SEGMENT.addPixelColorXY( i, j, ColorFromPalette(SEGPALETTE, (ms / 11 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 11, 200, 255);
SEGMENT.addPixelColorXY( j, i, ColorFromPalette(SEGPALETTE, (ms / 13 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 13, 200, 255);
SEGMENT.addPixelColorXY(ni,nj, ColorFromPalette(SEGPALETTE, (ms / 17 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 17, 200, 255);
SEGMENT.addPixelColorXY(nj,ni, ColorFromPalette(SEGPALETTE, (ms / 29 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 29, 200, 255);
SEGMENT.addPixelColorXY( i,nj, ColorFromPalette(SEGPALETTE, (ms / 37 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 37, 200, 255);
SEGMENT.addPixelColorXY(ni, j, ColorFromPalette(SEGPALETTE, (ms / 41 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 41, 200, 255);
SEGMENT.addPixelColorXY( i, j, ColorFromPalette(SEGPALETTE, (strip.now / 11 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 11, 200, 255);
SEGMENT.addPixelColorXY( j, i, ColorFromPalette(SEGPALETTE, (strip.now / 13 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 13, 200, 255);
SEGMENT.addPixelColorXY(ni,nj, ColorFromPalette(SEGPALETTE, (strip.now / 17 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 17, 200, 255);
SEGMENT.addPixelColorXY(nj,ni, ColorFromPalette(SEGPALETTE, (strip.now / 29 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 29, 200, 255);
SEGMENT.addPixelColorXY( i,nj, ColorFromPalette(SEGPALETTE, (strip.now / 37 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 37, 200, 255);
SEGMENT.addPixelColorXY(ni, j, ColorFromPalette(SEGPALETTE, (strip.now / 41 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 41, 200, 255);
return FRAMETIME;
} // mode_2DSwirl()
@ -6321,7 +6443,7 @@ uint16_t mode_2DWaverly(void) {
SEGMENT.fadeToBlackBy(SEGMENT.speed);
long t = millis() / 2;
long t = strip.now / 2;
for (int i = 0; i < cols; i++) {
uint16_t thisVal = (1 + SEGMENT.intensity/64) * inoise8(i * 45 , t , t)/2;
// use audio if available
@ -6383,7 +6505,7 @@ uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline.
uint8_t gravity = 8 - SEGMENT.speed/32;
for (int i=0; i<tempsamp; i++) {
uint8_t index = inoise8(i*segmentSampleAvg+millis(), 5000+i*segmentSampleAvg);
uint8_t index = inoise8(i*segmentSampleAvg+strip.now, 5000+i*segmentSampleAvg);
SEGMENT.setPixelColor(i+SEGLEN/2, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0), segmentSampleAvg*8));
SEGMENT.setPixelColor(SEGLEN/2-i-1, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0), segmentSampleAvg*8));
}
@ -6394,8 +6516,8 @@ uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline.
gravcen->topLED--;
if (gravcen->topLED >= 0) {
SEGMENT.setPixelColor(gravcen->topLED+SEGLEN/2, SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0));
SEGMENT.setPixelColor(SEGLEN/2-1-gravcen->topLED, SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0));
SEGMENT.setPixelColor(gravcen->topLED+SEGLEN/2, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0));
SEGMENT.setPixelColor(SEGLEN/2-1-gravcen->topLED, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0));
}
gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity;
@ -6435,7 +6557,7 @@ uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew
uint8_t gravity = 8 - SEGMENT.speed/32;
for (int i=0; i<tempsamp; i++) {
uint8_t index = segmentSampleAvg*24+millis()/200;
uint8_t index = segmentSampleAvg*24+strip.now/200;
SEGMENT.setPixelColor(i+SEGLEN/2, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0));
SEGMENT.setPixelColor(SEGLEN/2-1-i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0));
}
@ -6484,7 +6606,7 @@ uint16_t mode_gravimeter(void) { // Gravmeter. By Andrew Tuline.
uint8_t gravity = 8 - SEGMENT.speed/32;
for (int i=0; i<tempsamp; i++) {
uint8_t index = inoise8(i*segmentSampleAvg+millis(), 5000+i*segmentSampleAvg);
uint8_t index = inoise8(i*segmentSampleAvg+strip.now, 5000+i*segmentSampleAvg);
SEGMENT.setPixelColor(i, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0), segmentSampleAvg*8));
}
@ -6494,7 +6616,7 @@ uint16_t mode_gravimeter(void) { // Gravmeter. By Andrew Tuline.
gravcen->topLED--;
if (gravcen->topLED > 0) {
SEGMENT.setPixelColor(gravcen->topLED, SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0));
SEGMENT.setPixelColor(gravcen->topLED, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0));
}
gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity;
@ -6519,7 +6641,7 @@ uint16_t mode_juggles(void) { // Juggles. By Andrew Tuline.
uint16_t my_sampleAgc = fmax(fmin(volumeSmth, 255.0), 0);
for (size_t i=0; i<SEGMENT.intensity/32+1U; i++) {
SEGMENT.setPixelColor(beatsin16(SEGMENT.speed/4+i*2,0,SEGLEN-1), color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(millis()/4+i*2, false, PALETTE_SOLID_WRAP, 0), my_sampleAgc));
SEGMENT.setPixelColor(beatsin16(SEGMENT.speed/4+i*2,0,SEGLEN-1), color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(strip.now/4+i*2, false, PALETTE_SOLID_WRAP, 0), my_sampleAgc));
}
return FRAMETIME;
@ -6551,7 +6673,7 @@ uint16_t mode_matripix(void) { // Matripix. By Andrew Tuline.
int pixBri = volumeRaw * SEGMENT.intensity / 64;
for (int i = 0; i < SEGLEN-1; i++) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i+1)); // shift left
SEGMENT.setPixelColor(SEGLEN-1, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0), pixBri));
SEGMENT.setPixelColor(SEGLEN-1, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0), pixBri));
}
return FRAMETIME;
@ -6615,7 +6737,7 @@ uint16_t mode_noisefire(void) { // Noisefire. By Andrew Tuline.
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
for (int i = 0; i < SEGLEN; i++) {
uint16_t index = inoise8(i*SEGMENT.speed/64,millis()*SEGMENT.speed/64*SEGLEN/255); // X location is constant, but we move along the Y at the rate of millis(). By Andrew Tuline.
uint16_t index = inoise8(i*SEGMENT.speed/64,strip.now*SEGMENT.speed/64*SEGLEN/255); // X location is constant, but we move along the Y at the rate of millis(). By Andrew Tuline.
index = (255 - i*256/SEGLEN) * index/(256-SEGMENT.intensity); // Now we need to scale index so that it gets blacker as we get close to one of the ends.
// This is a simple y=mx+b equation that's been scaled. index/128 is another scaling.
@ -6687,7 +6809,7 @@ uint16_t mode_pixelwave(void) { // Pixelwave. By Andrew Tuline.
int pixBri = volumeRaw * SEGMENT.intensity / 64;
SEGMENT.setPixelColor(SEGLEN/2, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0), pixBri));
SEGMENT.setPixelColor(SEGLEN/2, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0), pixBri));
for (int i = SEGLEN - 1; i > SEGLEN/2; i--) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i-1)); //move to the left
for (int i = 0; i < SEGLEN/2; i++) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i+1)); // move to the right
}
@ -6775,7 +6897,7 @@ uint16_t mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline.
}
for (int i=0; i<size; i++) { // Flash the LED's.
SEGMENT.setPixelColor(pos+i, SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0));
SEGMENT.setPixelColor(pos+i, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0));
}
return FRAMETIME;
@ -6807,7 +6929,7 @@ uint16_t mode_puddles(void) { // Puddles. By Andrew Tuline.
}
for (int i=0; i<size; i++) { // Flash the LED's.
SEGMENT.setPixelColor(pos+i, SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0));
SEGMENT.setPixelColor(pos+i, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0));
}
return FRAMETIME;
@ -6830,7 +6952,7 @@ uint16_t mode_pixels(void) { // Pixels. By Andrew Tuline.
}
float volumeSmth = *(float*) um_data->u_data[0];
myVals[millis()%32] = volumeSmth; // filling values semi randomly
myVals[strip.now%32] = volumeSmth; // filling values semi randomly
SEGMENT.fade_out(64+(SEGMENT.speed>>1));
@ -7188,7 +7310,7 @@ uint16_t mode_noisemove(void) { // Noisemove. By: Andrew Tuli
uint8_t numBins = map(SEGMENT.intensity,0,255,0,16); // Map slider to fftResult bins.
for (int i=0; i<numBins; i++) { // How many active bins are we using.
uint16_t locn = inoise16(millis()*SEGMENT.speed+i*50000, millis()*SEGMENT.speed); // Get a new pixel location from moving noise.
uint16_t locn = inoise16(strip.now*SEGMENT.speed+i*50000, strip.now*SEGMENT.speed); // Get a new pixel location from moving noise.
locn = map(locn, 7500, 58000, 0, SEGLEN-1); // Map that to the length of the strand, and ensure we don't go over.
SEGMENT.setPixelColor(locn, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(i*64, false, PALETTE_SOLID_WRAP, 0), fftResult[i % 16]*4));
}
@ -7313,8 +7435,8 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma.
if (SEGENV.call == 0) for (int i=0; i<cols; i++) previousBarHeight[i] = 0;
bool rippleTime = false;
if (millis() - SEGENV.step >= (256U - SEGMENT.intensity)) {
SEGENV.step = millis();
if (strip.now - SEGENV.step >= (256U - SEGMENT.intensity)) {
SEGENV.step = strip.now;
rippleTime = true;
}
@ -7522,7 +7644,7 @@ uint16_t mode_2Ddistortionwaves() {
uint8_t w = 2;
uint16_t a = millis()/32;
uint16_t a = strip.now/32;
uint16_t a2 = a/2;
uint16_t a3 = a/3;
@ -7740,7 +7862,7 @@ uint16_t mode_2Dwavingcell() {
const uint16_t cols = SEGMENT.virtualWidth();
const uint16_t rows = SEGMENT.virtualHeight();
uint32_t t = millis()/(257-SEGMENT.speed);
uint32_t t = strip.now/(257-SEGMENT.speed);
uint8_t aX = SEGMENT.custom1/16 + 9;
uint8_t aY = SEGMENT.custom2/16 + 1;
uint8_t aZ = SEGMENT.custom3 + 1;
@ -7945,6 +8067,7 @@ void WS2812FX::setupEffectData() {
// --- 2D effects ---
#ifndef WLED_DISABLE_2D
addEffect(FX_MODE_2DPLASMAROTOZOOM, &mode_2Dplasmarotozoom, _data_FX_MODE_2DPLASMAROTOZOOM);
addEffect(FX_MODE_2DSPACESHIPS, &mode_2Dspaceships, _data_FX_MODE_2DSPACESHIPS);
addEffect(FX_MODE_2DCRAZYBEES, &mode_2Dcrazybees, _data_FX_MODE_2DCRAZYBEES);
addEffect(FX_MODE_2DGHOSTRIDER, &mode_2Dghostrider, _data_FX_MODE_2DGHOSTRIDER);

View File

@ -241,7 +241,7 @@
#define FX_MODE_CHUNCHUN 111
#define FX_MODE_DANCING_SHADOWS 112
#define FX_MODE_WASHING_MACHINE 113
// #define FX_MODE_CANDY_CANE 114 // removed in 0.14!
#define FX_MODE_2DPLASMAROTOZOOM 114 // was Candy Cane prior to 0.14 (use Chase 2)
#define FX_MODE_BLENDS 115
#define FX_MODE_TV_SIMULATOR 116
#define FX_MODE_DYNAMIC_SMOOTH 117 // candidate for removal (check3 in dynamic)
@ -802,8 +802,7 @@ class WS2812FX { // 96 bytes
getActiveSegmentsNum(void),
getFirstSelectedSegId(void),
getLastActiveSegmentId(void),
getActiveSegsLightCapabilities(bool selectedOnly = false),
setPixelSegment(uint8_t n);
getActiveSegsLightCapabilities(bool selectedOnly = false);
inline uint8_t getBrightness(void) { return _brightness; } // returns current strip brightness
inline uint8_t getMaxSegments(void) { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value)

View File

@ -425,7 +425,7 @@ uint8_t IRAM_ATTR Segment::currentBri(bool useCct) {
uint32_t prog = progress();
if (prog < 0xFFFFU) {
uint32_t curBri = (useCct ? cct : (on ? opacity : 0)) * prog;
curBri += (useCct ? _t->_cctT : (on ? _t->_briT : 0)) * (0xFFFFU - prog);
curBri += (useCct ? _t->_cctT : _t->_briT) * (0xFFFFU - prog);
return curBri / 0xFFFFU;
}
return (useCct ? cct : (on ? opacity : 0));
@ -440,6 +440,7 @@ uint8_t IRAM_ATTR Segment::currentMode() {
}
uint32_t IRAM_ATTR Segment::currentColor(uint8_t slot) {
if (slot >= NUM_COLORS) slot = 0;
#ifndef WLED_DISABLE_MODE_BLEND
return isInTransition() ? color_blend(_t->_segT._colorT[slot], colors[slot], progress(), true) : colors[slot];
#else
@ -1025,7 +1026,7 @@ void Segment::blur(uint8_t blur_amount) {
* Inspired by the Adafruit examples.
*/
uint32_t Segment::color_wheel(uint8_t pos) {
if (palette) return color_from_palette(pos, false, true, 0);
if (palette) return color_from_palette(pos, false, true, 0); // perhaps "strip.paletteBlend < 2" should be better instead of "true"
uint8_t w = W(currentColor(0));
pos = 255 - pos;
if (pos < 85) {
@ -1056,6 +1057,7 @@ uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_
uint8_t paletteIndex = i;
if (mapping && virtualLength() > 1) paletteIndex = (i*255)/(virtualLength() -1);
// paletteBlend: 0 - wrap when moving, 1 - always wrap, 2 - never wrap, 3 - none (undefined)
if (!wrap && strip.paletteBlend != 3) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
CRGBPalette16 curPal;
curPal = currentPalette(curPal, palette);
@ -1140,7 +1142,7 @@ void WS2812FX::service() {
_isServicing = true;
_segment_index = 0;
Segment::handleRandomPalette(); // move it into for loop when each segment has individual random palette
for (segment &seg : _segments) {
if (_suspend) return; // immediately stop processing segments if suspend requested during service()
@ -1203,6 +1205,7 @@ void WS2812FX::service() {
#endif
if (doShow) {
yield();
Segment::handleRandomPalette(); // slowly transtion random palette; move it into for loop when each segment has individual random palette
show();
}
#ifdef WLED_DEBUG
@ -1453,6 +1456,7 @@ void WS2812FX::resetSegments() {
segment seg = Segment(0, _length);
#endif
_segments.push_back(seg);
_segments.shrink_to_fit(); // just in case ...
_mainSegment = 0;
}
@ -1571,18 +1575,7 @@ bool WS2812FX::checkSegmentAlignment() {
return true;
}
//After this function is called, setPixelColor() will use that segment (offsets, grouping, ... will apply)
//Note: If called in an interrupt (e.g. JSON API), original segment must be restored,
//otherwise it can lead to a crash on ESP32 because _segment_index is modified while in use by the main thread
uint8_t WS2812FX::setPixelSegment(uint8_t n) {
uint8_t prevSegId = _segment_index;
if (n < _segments.size()) {
_segment_index = n;
_virtualSegmentLength = _segments[_segment_index].virtualLength();
}
return prevSegId;
}
// used by analog clock overlay
void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) {
if (i2 < i) std::swap(i,i2);
for (unsigned x = i; x <= i2; x++) setPixelColor(x, col);

View File

@ -606,29 +606,34 @@ void BusNetwork::cleanup() {
//utility to get the approx. memory usage of a given BusConfig
uint32_t BusManager::memUsage(BusConfig &bc) {
uint8_t type = bc.type;
if (bc.type == TYPE_ONOFF || IS_PWM(bc.type)) return 5;
uint16_t len = bc.count + bc.skipAmount;
if (type > 15 && type < 32) { // digital types
if (type == TYPE_UCS8903 || type == TYPE_UCS8904) len *= 2; // 16-bit LEDs
uint16_t channels = 3;
uint16_t multiplier = 1;
if (IS_DIGITAL(bc.type)) { // digital types
if (IS_16BIT(bc.type)) len *= 2; // 16-bit LEDs
#ifdef ESP8266
if (bc.type > 28) channels = 4; //RGBW
if (bc.pins[0] == 3) { //8266 DMA uses 5x the mem
if (type > 28) return len*20; //RGBW
return len*15;
multiplier = 5;
}
if (type > 28) return len*4; //RGBW
return len*3;
#else //ESP32 RMT uses double buffer?
if (type > 28) return len*8; //RGBW
return len*6;
#else //ESP32 RMT uses double buffer, I2S uses 5x buffer
if (bc.type > 28) channels = 4; //RGBW
multiplier = 2;
#endif
}
if (type > 31 && type < 48) return 5;
return len*3; //RGB
if (IS_VIRTUAL(bc.type)) {
switch (bc.type) {
case TYPE_NET_DDP_RGBW: channels = 4; break;
}
}
return len * channels * multiplier; //RGB
}
int BusManager::add(BusConfig &bc) {
if (getNumBusses() - getNumVirtualBusses() >= WLED_MAX_BUSSES) return -1;
if (bc.type >= TYPE_NET_DDP_RGB && bc.type < 96) {
if (IS_VIRTUAL(bc.type)) {
busses[numBusses] = new BusNetwork(bc);
} else if (IS_DIGITAL(bc.type)) {
busses[numBusses] = new BusDigital(bc, numBusses, colorOrderMap);

View File

@ -129,10 +129,9 @@ class Bus {
virtual void setPixelColor(uint16_t pix, uint32_t c) = 0;
virtual uint32_t getPixelColor(uint16_t pix) { return 0; }
virtual void setBrightness(uint8_t b) { _bri = b; };
virtual void cleanup() = 0;
virtual uint8_t getPins(uint8_t* pinArray) { return 0; }
virtual uint16_t getLength() { return _len; }
virtual void setColorOrder() {}
virtual void setColorOrder(uint8_t co) {}
virtual uint8_t getColorOrder() { return COL_ORDER_RGB; }
virtual uint8_t skippedLeds() { return 0; }
virtual uint16_t getFrequency() { return 0U; }
@ -207,21 +206,21 @@ class BusDigital : public Bus {
BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com);
~BusDigital() { cleanup(); }
void show();
bool canShow();
void setBrightness(uint8_t b);
void setStatusPixel(uint32_t c);
void setPixelColor(uint16_t pix, uint32_t c);
void setColorOrder(uint8_t colorOrder);
uint32_t getPixelColor(uint16_t pix);
uint8_t getColorOrder() { return _colorOrder; }
uint8_t getPins(uint8_t* pinArray);
uint8_t skippedLeds() { return _skip; }
uint16_t getFrequency() { return _frequencykHz; }
void show() override;
bool canShow() override;
void setBrightness(uint8_t b) override;
void setStatusPixel(uint32_t c) override;
void setPixelColor(uint16_t pix, uint32_t c) override;
void setColorOrder(uint8_t colorOrder) override;
uint32_t getPixelColor(uint16_t pix) override;
uint8_t getColorOrder() override { return _colorOrder; }
uint8_t getPins(uint8_t* pinArray) override;
uint8_t skippedLeds() override { return _skip; }
uint16_t getFrequency() override { return _frequencykHz; }
uint8_t estimateCurrentAndLimitBri();
uint16_t getLEDCurrent() { return _milliAmpsPerLed; }
uint16_t getUsedCurrent() { return _milliAmpsTotal; }
uint16_t getMaxCurrent() { return _milliAmpsMax; }
uint16_t getLEDCurrent() override { return _milliAmpsPerLed; }
uint16_t getUsedCurrent() override { return _milliAmpsTotal; }
uint16_t getMaxCurrent() override { return _milliAmpsMax; }
void reinit();
void cleanup();
@ -256,11 +255,11 @@ class BusPwm : public Bus {
BusPwm(BusConfig &bc);
~BusPwm() { cleanup(); }
void setPixelColor(uint16_t pix, uint32_t c);
uint32_t getPixelColor(uint16_t pix); //does no index check
uint8_t getPins(uint8_t* pinArray);
uint16_t getFrequency() { return _frequency; }
void show();
void setPixelColor(uint16_t pix, uint32_t c) override;
uint32_t getPixelColor(uint16_t pix) override; //does no index check
uint8_t getPins(uint8_t* pinArray) override;
uint16_t getFrequency() override { return _frequency; }
void show() override;
void cleanup() { deallocatePins(); }
private:
@ -280,10 +279,10 @@ class BusOnOff : public Bus {
BusOnOff(BusConfig &bc);
~BusOnOff() { cleanup(); }
void setPixelColor(uint16_t pix, uint32_t c);
uint32_t getPixelColor(uint16_t pix);
uint8_t getPins(uint8_t* pinArray);
void show();
void setPixelColor(uint16_t pix, uint32_t c) override;
uint32_t getPixelColor(uint16_t pix) override;
uint8_t getPins(uint8_t* pinArray) override;
void show() override;
void cleanup() { pinManager.deallocatePin(_pin, PinOwner::BusOnOff); }
private:
@ -297,13 +296,13 @@ class BusNetwork : public Bus {
BusNetwork(BusConfig &bc);
~BusNetwork() { cleanup(); }
bool hasRGB() { return true; }
bool hasWhite() { return _rgbw; }
bool canShow() { return !_broadcastLock; } // this should be a return value from UDP routine if it is still sending data out
void setPixelColor(uint16_t pix, uint32_t c);
uint32_t getPixelColor(uint16_t pix);
uint8_t getPins(uint8_t* pinArray);
void show();
bool hasRGB() override { return true; }
bool hasWhite() override { return _rgbw; }
bool canShow() override { return !_broadcastLock; } // this should be a return value from UDP routine if it is still sending data out
void setPixelColor(uint16_t pix, uint32_t c) override;
uint32_t getPixelColor(uint16_t pix) override;
uint8_t getPins(uint8_t* pinArray) override;
void show() override;
void cleanup();
private:

View File

@ -225,7 +225,7 @@
#define TYPE_NONE 0 //light is not configured
#define TYPE_RESERVED 1 //unused. Might indicate a "virtual" light
//Digital types (data pin only) (16-31)
//Digital types (data pin only) (16-39)
#define TYPE_WS2812_1CH 18 //white-only chips (1 channel per IC) (unused)
#define TYPE_WS2812_1CH_X3 19 //white-only chips (3 channels per IC)
#define TYPE_WS2812_2CH_X3 20 //CCT chips (1st IC controls WW + CW of 1st zone and CW of 2nd zone, 2nd IC controls WW of 2nd zone and WW + CW of 3rd zone)
@ -236,11 +236,11 @@
#define TYPE_TM1829 25
#define TYPE_UCS8903 26
#define TYPE_APA106 27
#define TYPE_UCS8904 29
#define TYPE_UCS8904 29 //first RGBW digital type (hardcoded in busmanager.cpp, memUsage())
#define TYPE_SK6812_RGBW 30
#define TYPE_TM1814 31
//"Analog" types (PWM) (32-47)
#define TYPE_ONOFF 40 //binary output (relays etc.)
//"Analog" types (40-47)
#define TYPE_ONOFF 40 //binary output (relays etc.; NOT PWM)
#define TYPE_ANALOG_1CH 41 //single channel PWM. Uses value of brightest RGBW channel
#define TYPE_ANALOG_2CH 42 //analog WW + CW
#define TYPE_ANALOG_3CH 43 //analog RGB
@ -258,11 +258,13 @@
#define TYPE_NET_ARTNET_RGB 82 //network ArtNet RGB bus (master broadcast bus, unused)
#define TYPE_NET_DDP_RGBW 88 //network DDP RGBW bus (master broadcast bus)
#define IS_DIGITAL(t) ((t) < 80 && ((t) & 0x10)) //digital are 16-31 and 48-63
#define IS_PWM(t) ((t) > 40 && (t) < 46)
#define NUM_PWM_PINS(t) ((t) - 40) //for analog PWM 41-45 only
#define IS_2PIN(t) ((t) > 47)
#define IS_VIRTUAL(t) ((t) >= 80)
#define IS_TYPE_VALID(t) ((t) > 15 && (t) < 128)
#define IS_DIGITAL(t) (((t) > 15 && (t) < 40) || ((t) > 47 && (t) < 64)) //digital are 16-39 and 48-63
#define IS_2PIN(t) ((t) > 47 && (t) < 64)
#define IS_16BIT(t) ((t) == TYPE_UCS8903 || (t) == TYPE_UCS8904)
#define IS_PWM(t) ((t) > 40 && (t) < 46) //does not include on/Off type
#define NUM_PWM_PINS(t) ((t) - 40) //for analog PWM 41-45 only
#define IS_VIRTUAL(t) ((t) >= 80 && (t) < 96) //this was a poor choice a better would be 96-111
//Color orders
#define COL_ORDER_GRB 0 //GRB(w),defaut

View File

@ -2161,7 +2161,7 @@ function selGrp(g)
var sel = gId(`segcont`).querySelectorAll(`div[data-set="${g}"]`);
var obj = {"seg":[]};
for (let i=0; i<=lSeg; i++) if (gId(`seg${i}`)) obj.seg.push({"id":i,"sel":false});
if (sel) for (let s of sel||[]) {
for (let s of (sel||[])) {
let i = parseInt(s.id.substring(3));
obj.seg[i] = {"id":i,"sel":true};
}

38
wled00/data/settings_leds.htm Executable file → Normal file
View File

@ -16,11 +16,13 @@
function B(){window.open(getURL("/settings"),"_self");}
function gId(n){return d.getElementById(n);}
function off(n){d.getElementsByName(n)[0].value = -1;}
function isPWM(t) { return t > 40 && t < 46; } // is PWM type
function isAna(t) { return t == 40 || isPWM(t); } // is analog type
function isDig(t) { return t < 80 && (t & 0x10); }// is digital type
function isD2P(t) { return t > 47 && t < 64; } // is digital 2 pin type
function isVir(t) { return t >= 80; } // is virtual type
// these functions correspond to C macros found in const.h
function isPWM(t) { return t > 40 && t < 46; } // is PWM type
function isAna(t) { return t == 40 || isPWM(t); } // is analog type
function isDig(t) { return (t > 15 && t < 40) || isD2P(t); } // is digital type
function isD2P(t) { return t > 47 && t < 64; } // is digital 2 pin type
function is16b(t) { return t == 26 || t == 29 } // is digital 16 bit type
function isVir(t) { return t >= 80 && t < 96; } // is virtual type
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
@ -175,25 +177,25 @@
}
//returns mem usage
function getMem(t, n) {
if (isAna(t)) return 5; // analog
let len = parseInt(d.getElementsByName("LC"+n)[0].value);
len += parseInt(d.getElementsByName("SL"+n)[0].value); // skipped LEDs are allocated too
let dbl = 0;
if (d.Sf.LD.checked) dbl = len * 4; // double buffering
if (t < 32) {
if (t==26 || t==29) len *= 2; // 16 bit LEDs
let ch = 3;
let mul = 1;
if (isDig(t)) {
if (is16b(t)) len *= 2; // 16 bit LEDs
if (t > 28 && t < 40) ch = 4; //RGBW
if (maxM < 10000 && d.getElementsByName("L0"+n)[0].value == 3) { //8266 DMA uses 5x the mem
if (t > 28) return len*20 + dbl; //RGBW
return len*15 + dbl;
} else if (maxM >= 10000) //ESP32 RMT uses double buffer?
{
if (t > 28) return len*8 + dbl; //RGBW
return len*6 + dbl;
mul = 5;
}
if (t > 28) return len*4 + dbl; //RGBW
return len*3 + dbl;
if (maxM >= 10000) { //ESP32 RMT uses double buffer?
mul = 2;
}
if (d.Sf.LD.checked) dbl = len * ch; // double buffering
}
if (t > 31 && t < 48) return 5; // analog
return len*3 + dbl;
if (isVir(t) && t == 88) ch = 4;
return len * ch * mul + dbl;
}
function UI(change=false)

View File

@ -377,27 +377,27 @@ void updateFSInfo() {
//Un-comment any file types you need
static String getContentType(AsyncWebServerRequest* request, String filename){
if(request->hasArg("download")) return "application/octet-stream";
else if(filename.endsWith(".htm")) return "text/html";
else if(filename.endsWith(".html")) return "text/html";
else if(filename.endsWith(".css")) return "text/css";
else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".json")) return "application/json";
else if(filename.endsWith(".png")) return "image/png";
else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
// else if(filename.endsWith(".xml")) return "text/xml";
// else if(filename.endsWith(".pdf")) return "application/x-pdf";
// else if(filename.endsWith(".zip")) return "application/x-zip";
// else if(filename.endsWith(".gz")) return "application/x-gzip";
if(request->hasArg(F("download"))) return SET_F("application/octet-stream");
else if(filename.endsWith(F(".htm"))) return SET_F("text/html");
else if(filename.endsWith(F(".html"))) return SET_F("text/html");
else if(filename.endsWith(F(".css"))) return SET_F("text/css");
else if(filename.endsWith(F(".js"))) return SET_F("application/javascript");
else if(filename.endsWith(F(".json"))) return SET_F("application/json");
else if(filename.endsWith(F(".png"))) return SET_F("image/png");
else if(filename.endsWith(F(".gif"))) return SET_F("image/gif");
else if(filename.endsWith(F(".jpg"))) return SET_F("image/jpeg");
else if(filename.endsWith(F(".ico"))) return SET_F("image/x-icon");
// else if(filename.endsWith(F(".xml"))) return SET_F("text/xml");
// else if(filename.endsWith(F(".pdf"))) return SET_F("application/x-pdf");
// else if(filename.endsWith(F(".zip"))) return SET_F("application/x-zip");
// else if(filename.endsWith(F(".gz"))) return SET_F("application/x-gzip");
return "text/plain";
}
bool handleFileRead(AsyncWebServerRequest* request, String path){
DEBUG_PRINTLN("WS FileRead: " + path);
if(path.endsWith("/")) path += "index.htm";
if(path.indexOf("sec") > -1) return false;
if(path.indexOf(F("sec")) > -1) return false;
String contentType = getContentType(request, path);
/*String pathWithGz = path + ".gz";
if(WLED_FS.exists(pathWithGz)){

View File

@ -611,7 +611,7 @@ void serializeInfo(JsonObject root)
root[F("vid")] = VERSION;
root[F("cn")] = F(WLED_CODENAME);
JsonObject leds = root.createNestedObject("leds");
JsonObject leds = root.createNestedObject(F("leds"));
leds[F("count")] = strip.getLengthTotal();
leds[F("pwr")] = BusManager::currentMilliamps();
leds["fps"] = strip.getFps();
@ -622,7 +622,7 @@ void serializeInfo(JsonObject root)
#ifndef WLED_DISABLE_2D
if (strip.isMatrix) {
JsonObject matrix = leds.createNestedObject("matrix");
JsonObject matrix = leds.createNestedObject(F("matrix"));
matrix["w"] = Segment::maxWidth;
matrix["h"] = Segment::maxHeight;
}
@ -702,7 +702,7 @@ void serializeInfo(JsonObject root)
}
}
JsonObject wifi_info = root.createNestedObject("wifi");
JsonObject wifi_info = root.createNestedObject(F("wifi"));
wifi_info[F("bssid")] = WiFi.BSSIDstr();
int qrssi = WiFi.RSSI();
wifi_info[F("rssi")] = qrssi;

View File

@ -170,7 +170,7 @@
#endif
#ifdef USERMOD_KLIPPER_PERCENTAGE
#include "..\usermods\usermod_v2_klipper_percentage\usermod_v2_klipper_percentage.h"
#include "../usermods/usermod_v2_klipper_percentage/usermod_v2_klipper_percentage.h"
#endif
#ifdef USERMOD_BOBLIGHT

View File

@ -386,7 +386,7 @@ void WLED::setup()
//DEBUG_PRINT(F("LEDs inited. heap usage ~"));
//DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
#ifdef WLED_DEBUG
#if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST)
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
@ -537,6 +537,13 @@ void WLED::beginStrip()
else if (bri == 0) bri = 128;
} else {
// fix for #3196
if (bootPreset > 0) {
bool oldTransition = fadeTransition; // workaround if transitions are enabled
fadeTransition = false; // ignore transitions temporarily
strip.setColor(0, BLACK); // set all segments black
fadeTransition = oldTransition; // restore transitions
col[0] = col[1] = col[2] = col[3] = 0; // needed for colorUpdated()
}
briLast = briS; bri = 0;
strip.fill(BLACK);
strip.show();

View File

@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2401130
#define VERSION 2401270
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG
@ -364,7 +364,6 @@ WLED_GLOBAL char serverDescription[33] _INIT("WLED"); // Name of module - use d
#else
WLED_GLOBAL char serverDescription[33] _INIT(SERVERNAME); // use predefined name
#endif
//WLED_GLOBAL bool syncToggleReceive _INIT(false); // UIs which only have a single button for sync should toggle send+receive if this is true, only send otherwise
WLED_GLOBAL bool simplifiedUI _INIT(false); // enable simplified UI
WLED_GLOBAL byte cacheInvalidate _INIT(0); // used to invalidate browser cache

View File

@ -532,18 +532,18 @@ void serveSettings(AsyncWebServerRequest* request, bool post) {
const String& url = request->url();
if (url.indexOf("sett") >= 0) {
if (url.indexOf(".js") > 0) subPage = SUBPAGE_JS;
else if (url.indexOf(".css") > 0) subPage = SUBPAGE_CSS;
else if (url.indexOf("wifi") > 0) subPage = SUBPAGE_WIFI;
else if (url.indexOf("leds") > 0) subPage = SUBPAGE_LEDS;
else if (url.indexOf("ui") > 0) subPage = SUBPAGE_UI;
else if (url.indexOf("sync") > 0) subPage = SUBPAGE_SYNC;
else if (url.indexOf("time") > 0) subPage = SUBPAGE_TIME;
else if (url.indexOf("sec") > 0) subPage = SUBPAGE_SEC;
else if (url.indexOf("dmx") > 0) subPage = SUBPAGE_DMX;
else if (url.indexOf("um") > 0) subPage = SUBPAGE_UM;
else if (url.indexOf("2D") > 0) subPage = SUBPAGE_2D;
else if (url.indexOf("lock") > 0) subPage = SUBPAGE_LOCK;
if (url.indexOf(F(".js")) > 0) subPage = SUBPAGE_JS;
else if (url.indexOf(F(".css")) > 0) subPage = SUBPAGE_CSS;
else if (url.indexOf(F("wifi")) > 0) subPage = SUBPAGE_WIFI;
else if (url.indexOf(F("leds")) > 0) subPage = SUBPAGE_LEDS;
else if (url.indexOf(F("ui")) > 0) subPage = SUBPAGE_UI;
else if (url.indexOf( "sync") > 0) subPage = SUBPAGE_SYNC;
else if (url.indexOf( "time") > 0) subPage = SUBPAGE_TIME;
else if (url.indexOf(F("sec")) > 0) subPage = SUBPAGE_SEC;
else if (url.indexOf( "dmx") > 0) subPage = SUBPAGE_DMX;
else if (url.indexOf( "um") > 0) subPage = SUBPAGE_UM;
else if (url.indexOf( "2D") > 0) subPage = SUBPAGE_2D;
else if (url.indexOf(F("lock")) > 0) subPage = SUBPAGE_LOCK;
}
else if (url.indexOf("/update") >= 0) subPage = SUBPAGE_UPDATE; // update page, for PIN check
//else if (url.indexOf("/edit") >= 0) subPage = 10;

View File

@ -157,8 +157,8 @@ void appendGPIOinfo() {
oappend(SET_F(",2")); // DMX hardcoded pin
#endif
#ifdef WLED_DEBUG
oappend(SET_F(",")); oappend(itoa(hardwareTX,nS,10));// debug output (TX) pin
#if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST)
oappend(SET_F(",")); oappend(itoa(hardwareTX,nS,10)); // debug output (TX) pin
#endif
//Note: Using pin 3 (RX) disables Adalight / Serial JSON