From da79b93387cb80873d5dc65cd864be866a4b70bf Mon Sep 17 00:00:00 2001 From: Brandon502 <105077712+Brandon502@users.noreply.github.com> Date: Tue, 7 May 2024 18:04:29 -0400 Subject: [PATCH 01/25] Added Pinwheel Expand 1D Effect --- wled00/FX.h | 3 ++- wled00/FX_fcn.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++- wled00/data/index.js | 1 + 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 106a6712c..b1e6823ff 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -320,7 +320,8 @@ typedef enum mapping1D2D { M12_Pixels = 0, M12_pBar = 1, M12_pArc = 2, - M12_pCorner = 3 + M12_pCorner = 3, + M12_sPinwheel = 4 } mapping1D2D_t; // segment, 80 bytes diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index ce510f16e..7f8c1319a 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -637,6 +637,14 @@ uint16_t IRAM_ATTR Segment::nrOfVStrips() const { return vLen; } +// Constants for mapping mode "Pinwheel" +constexpr int Pinwheel_Steps_Medium = 208; // no holes up to 32x32; 60fps +constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big" +constexpr int Pinwheel_Steps_Big = 360; // no holes expected up to 58x58; 40fps +constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...208 to Radians +constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...360 to Radians + + // 1D strip uint16_t IRAM_ATTR Segment::virtualLength() const { #ifndef WLED_DISABLE_2D @@ -652,6 +660,12 @@ uint16_t IRAM_ATTR Segment::virtualLength() const { case M12_pArc: vLen = max(vW,vH); // get the longest dimension break; + case M12_sPinwheel: + if (max(vW,vH) <= Pinwheel_Size_Medium) + vLen = Pinwheel_Steps_Medium; + else + vLen = Pinwheel_Steps_Big; + break; } return vLen; } @@ -718,6 +732,38 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) for (int x = 0; x <= i; x++) setPixelColorXY(x, i, col); for (int y = 0; y < i; y++) setPixelColorXY(i, y, col); break; + case M12_sPinwheel: { + // i = angle --> 0 through 359 (Big), OR 0 through 208 (Medium) + float centerX = roundf((vW-1) / 2.0f); + float centerY = roundf((vH-1) / 2.0f); + // int maxDistance = sqrt(centerX * centerX + centerY * centerY) + 1; + float angleRad = (max(vW,vH) > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med; // angle in radians + float cosVal = cosf(angleRad); + float sinVal = sinf(angleRad); + + // draw line at angle, starting at center and ending at the segment edge + // we use fixed point math for better speed. Starting distance is 0.5 for better rounding + constexpr int_fast32_t Fixed_Scale = 512; // fixpoint scaling factor + int_fast32_t posx = (centerX + 0.5f * cosVal) * Fixed_Scale; // X starting position in fixed point + int_fast32_t posy = (centerY + 0.5f * sinVal) * Fixed_Scale; // Y starting position in fixed point + int_fast16_t inc_x = cosVal * Fixed_Scale; // X increment per step (fixed point) + int_fast16_t inc_y = sinVal * Fixed_Scale; // Y increment per step (fixed point) + + int32_t maxX = vW * Fixed_Scale; // X edge in fixedpoint + int32_t maxY = vH * Fixed_Scale; // Y edge in fixedpoint + // draw until we hit any edge + while ((posx > 0) && (posy > 0) && (posx < maxX) && (posy < maxY)) { + // scale down to integer (compiler will replace division with appropriate bitshift) + int x = posx / Fixed_Scale; + int y = posy / Fixed_Scale; + // set pixel + setPixelColorXY(x, y, col); + // advance to next position + posx += inc_x; + posy += inc_y; + } + break; + } } return; } else if (Segment::maxHeight!=1 && (width()==1 || height()==1)) { @@ -833,7 +879,17 @@ uint32_t IRAM_ATTR Segment::getPixelColor(int i) // use longest dimension return vW>vH ? getPixelColorXY(i, 0) : getPixelColorXY(0, i); break; - } + case M12_sPinwheel: + // not 100% accurate, returns outer edge of circle + float distance = max(1.0f, min(vH-1, vW-1) / 2.0f); + float centerX = (vW - 1) / 2.0f; + float centerY = (vH - 1) / 2.0f; + float angleRad = (max(vW,vH) > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med; // angle in radians + int x = roundf(centerX + distance * cosf(angleRad)); + int y = roundf(centerY + distance * sinf(angleRad)); + return getPixelColorXY(x, y); + break; + } return 0; } #endif diff --git a/wled00/data/index.js b/wled00/data/index.js index d33fb63f7..26d78b284 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -801,6 +801,7 @@ function populateSegments(s) ``+ ``+ ``+ + ``+ ``+ ``; let sndSim = `
Sound sim
`+ From bc5aadff7d73931f971b3d1ee534b7a2d4dc7f0a Mon Sep 17 00:00:00 2001 From: Adam Matthews Date: Thu, 9 May 2024 23:09:45 +0100 Subject: [PATCH 02/25] Update Usermod: Battery Issue: When taking the initial voltage reading after first powering on, voltage hasn't had chance to stabilize so the reading can be inaccurate, which in turn may incorrectly trigger the low-power preset. (Manifests when the user has selected a low read interval and/or is using a capacitor). Resolution: A non-blocking, fixed 10 second delay has been added to the initial voltage reading to give the voltage time to stabilize. This is a reworked version of the (now closed) PR here: https://github.com/Aircoookie/WLED/pull/3959 - Rebased the update for 0_15. - Added a constant so the delay can be modified via my_config.h. - Small adjustments to make the PR compatible again after the recent restructuring in this PR: (https://github.com/Aircoookie/WLED/pull/3003). Thankyou! --- usermods/Battery/battery_defaults.h | 6 ++++++ usermods/Battery/readme.md | 5 +++++ usermods/Battery/usermod_v2_Battery.h | 28 ++++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/usermods/Battery/battery_defaults.h b/usermods/Battery/battery_defaults.h index 8b56c6014..ddbd114e4 100644 --- a/usermods/Battery/battery_defaults.h +++ b/usermods/Battery/battery_defaults.h @@ -14,6 +14,12 @@ #endif #endif +// The initial delay before the first battery voltage reading after power-on. +// This allows the voltage to stabilize before readings are taken, improving accuracy of initial reading. +#ifndef USERMOD_BATTERY_INITIAL_DELAY + #define USERMOD_BATTERY_INITIAL_DELAY 10000 // (milliseconds) +#endif + // the frequency to check the battery, 30 sec #ifndef USERMOD_BATTERY_MEASUREMENT_INTERVAL #define USERMOD_BATTERY_MEASUREMENT_INTERVAL 30000 diff --git a/usermods/Battery/readme.md b/usermods/Battery/readme.md index b3607482a..efe25cc24 100644 --- a/usermods/Battery/readme.md +++ b/usermods/Battery/readme.md @@ -37,6 +37,7 @@ define `USERMOD_BATTERY` in `wled00/my_config.h` | ----------------------------------------------- | ----------- |-------------------------------------------------------------------------------------- | | `USERMOD_BATTERY` | | define this (in `my_config.h`) to have this usermod included wled00\usermods_list.cpp | | `USERMOD_BATTERY_MEASUREMENT_PIN` | | defaults to A0 on ESP8266 and GPIO35 on ESP32 | +| `USERMOD_BATTERY_INITIAL_DELAY` | ms | delay before initial reading. defaults to 10 seconds to allow voltage stabilization | `USERMOD_BATTERY_MEASUREMENT_INTERVAL` | ms | battery check interval. defaults to 30 seconds | | `USERMOD_BATTERY_{TYPE}_MIN_VOLTAGE` | v | minimum battery voltage. default is 2.6 (18650 battery standard) | | `USERMOD_BATTERY_{TYPE}_MAX_VOLTAGE` | v | maximum battery voltage. default is 4.2 (18650 battery standard) | @@ -88,6 +89,10 @@ Specification from: [Molicel INR18650-M35A, 3500mAh 10A Lithium-ion battery, 3. 2024-04-30 +- improved initial reading accuracy by delaying initial measurement to allow voltage to stabilize at power-on + +2024-04-30 + - integrate factory pattern to make it easier to add other / custom battery types - update readme diff --git a/usermods/Battery/usermod_v2_Battery.h b/usermods/Battery/usermod_v2_Battery.h index 88a879b72..35da337e1 100644 --- a/usermods/Battery/usermod_v2_Battery.h +++ b/usermods/Battery/usermod_v2_Battery.h @@ -22,6 +22,10 @@ class UsermodBattery : public Usermod UMBattery* bat = new UnkownUMBattery(); batteryConfig cfg; + // Initial delay before first reading to allow voltage stabilization + unsigned long initialDelay = USERMOD_BATTERY_INITIAL_DELAY; + bool initialDelayComplete = false; + bool isFirstVoltageReading = true; // how often to read the battery voltage unsigned long readingInterval = USERMOD_BATTERY_MEASUREMENT_INTERVAL; unsigned long nextReadTime = 0; @@ -137,7 +141,6 @@ class UsermodBattery : public Usermod if (pinManager.allocatePin(batteryPin, false, PinOwner::UM_Battery)) { DEBUG_PRINTLN(F("Battery pin allocation succeeded.")); success = true; - bat->setVoltage(readVoltage()); } if (!success) { @@ -148,10 +151,10 @@ class UsermodBattery : public Usermod } #else //ESP8266 boards have only one analog input pin A0 pinMode(batteryPin, INPUT); - bat->setVoltage(readVoltage()); #endif - nextReadTime = millis() + readingInterval; + // First voltage reading is delayed to allow voltage stabilization after powering up + nextReadTime = millis() + initialDelay; lastReadTime = millis(); initDone = true; @@ -178,6 +181,25 @@ class UsermodBattery : public Usermod lowPowerIndicator(); + // Handling the initial delay + if (!initialDelayComplete && millis() < nextReadTime) + return; // Continue to return until the initial delay is over + + // Once the initial delay is over, set it as complete + if (!initialDelayComplete) + { + initialDelayComplete = true; + // Set the regular interval after initial delay + nextReadTime = millis() + readingInterval; + } + + // Make the first voltage reading after the initial delay has elapsed + if (isFirstVoltageReading) + { + bat->setVoltage(readVoltage()); + isFirstVoltageReading = false; + } + // check the battery level every USERMOD_BATTERY_MEASUREMENT_INTERVAL (ms) if (millis() < nextReadTime) return; From 6a18ce078e3b2f31404d3309b39985638d53fcf4 Mon Sep 17 00:00:00 2001 From: Brandon502 <105077712+Brandon502@users.noreply.github.com> Date: Thu, 9 May 2024 20:38:41 -0400 Subject: [PATCH 03/25] Pinwheel Expand1D changes cosf/sinf changed to cos_t/sin_t. int_fast32_t and int_fast_16_t changed to int. --- wled00/FX_fcn.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 7f8c1319a..88ec78f3e 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -738,16 +738,17 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) float centerY = roundf((vH-1) / 2.0f); // int maxDistance = sqrt(centerX * centerX + centerY * centerY) + 1; float angleRad = (max(vW,vH) > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med; // angle in radians - float cosVal = cosf(angleRad); - float sinVal = sinf(angleRad); + float cosVal = cos_t(angleRad); + float sinVal = sin_t(angleRad); // draw line at angle, starting at center and ending at the segment edge // we use fixed point math for better speed. Starting distance is 0.5 for better rounding - constexpr int_fast32_t Fixed_Scale = 512; // fixpoint scaling factor - int_fast32_t posx = (centerX + 0.5f * cosVal) * Fixed_Scale; // X starting position in fixed point - int_fast32_t posy = (centerY + 0.5f * sinVal) * Fixed_Scale; // Y starting position in fixed point - int_fast16_t inc_x = cosVal * Fixed_Scale; // X increment per step (fixed point) - int_fast16_t inc_y = sinVal * Fixed_Scale; // Y increment per step (fixed point) + // int_fast16_t and int_fast32_t types changed to int, minimum bits commented + constexpr int Fixed_Scale = 512; // fixpoint scaling factor 18 bit + int posx = (centerX + 0.5f * cosVal) * Fixed_Scale; // X starting position in fixed point 18 bit + int posy = (centerY + 0.5f * sinVal) * Fixed_Scale; // Y starting position in fixed point 18 bit + int inc_x = cosVal * Fixed_Scale; // X increment per step (fixed point) 10 bit + int inc_y = sinVal * Fixed_Scale; // Y increment per step (fixed point) 10 bit int32_t maxX = vW * Fixed_Scale; // X edge in fixedpoint int32_t maxY = vH * Fixed_Scale; // Y edge in fixedpoint @@ -885,8 +886,8 @@ uint32_t IRAM_ATTR Segment::getPixelColor(int i) float centerX = (vW - 1) / 2.0f; float centerY = (vH - 1) / 2.0f; float angleRad = (max(vW,vH) > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med; // angle in radians - int x = roundf(centerX + distance * cosf(angleRad)); - int y = roundf(centerY + distance * sinf(angleRad)); + int x = roundf(centerX + distance * cos_t(angleRad)); + int y = roundf(centerY + distance * sin_t(angleRad)); return getPixelColorXY(x, y); break; } From d3492b5b6c38e6a8cb2136bc8d7654a4594b59df Mon Sep 17 00:00:00 2001 From: Brandon502 <105077712+Brandon502@users.noreply.github.com> Date: Fri, 10 May 2024 16:06:37 -0400 Subject: [PATCH 04/25] Pinwheel Expand 1D Bug Fix Removed holes on 31x31 and 32x32 grids. --- wled00/FX_fcn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 88ec78f3e..17a504ea0 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -639,7 +639,7 @@ uint16_t IRAM_ATTR Segment::nrOfVStrips() const { // Constants for mapping mode "Pinwheel" constexpr int Pinwheel_Steps_Medium = 208; // no holes up to 32x32; 60fps -constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big" +constexpr int Pinwheel_Size_Medium = 30; // larger than this -> use "Big" constexpr int Pinwheel_Steps_Big = 360; // no holes expected up to 58x58; 40fps constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...208 to Radians constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...360 to Radians From 43d024fe429c5f519fb50f80fe75c8d184c64aea Mon Sep 17 00:00:00 2001 From: Michael Bisbjerg Date: Fri, 10 May 2024 22:43:55 +0200 Subject: [PATCH 05/25] Make BME280 usermod i2c address changeable --- usermods/BME280_v2/README.md | 1 + usermods/BME280_v2/usermod_bme280.h | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/usermods/BME280_v2/README.md b/usermods/BME280_v2/README.md index 0a4afbf1f..51e93336d 100644 --- a/usermods/BME280_v2/README.md +++ b/usermods/BME280_v2/README.md @@ -7,6 +7,7 @@ This Usermod is designed to read a `BME280` or `BMP280` sensor and output the fo - Dew Point (`BME280` only) Configuration is performed via the Usermod menu. There are no parameters to set in code! The following settings can be configured in the Usermod Menu: +- The i2c address in decimal. Set it to either 118 (0x76, the default) or 119 (0x77). **Requires reboot**. - Temperature Decimals (number of decimal places to output) - Humidity Decimals - Pressure Decimals diff --git a/usermods/BME280_v2/usermod_bme280.h b/usermods/BME280_v2/usermod_bme280.h index ae6eba89d..0040c5efa 100644 --- a/usermods/BME280_v2/usermod_bme280.h +++ b/usermods/BME280_v2/usermod_bme280.h @@ -28,6 +28,7 @@ private: bool UseCelsius = true; // Use Celsius for Reporting bool HomeAssistantDiscovery = false; // Publish Home Assistant Device Information bool enabled = true; + BME280I2C::I2CAddr i2cAddress = BME280I2C::I2CAddr_0x76; // Default i2c address for BME280 // set the default pins based on the architecture, these get overridden by Usermod menu settings #ifdef ESP8266 @@ -48,7 +49,7 @@ private: BME280I2C::I2CAddr_0x76 // I2C address. I2C specific. Default 0x76 }; - BME280I2C bme{settings}; + BME280I2C bme; uint8_t sensorType; @@ -186,6 +187,9 @@ public: { if (i2c_scl<0 || i2c_sda<0) { enabled = false; sensorType = 0; return; } + settings.bme280Addr = i2cAddress; + bme = BME280I2C(settings); + if (!bme.begin()) { sensorType = 0; @@ -399,6 +403,7 @@ public: { JsonObject top = root.createNestedObject(FPSTR(_name)); top[FPSTR(_enabled)] = enabled; + top[F("I2CAddress")] = i2cAddress; top[F("TemperatureDecimals")] = TemperatureDecimals; top[F("HumidityDecimals")] = HumidityDecimals; top[F("PressureDecimals")] = PressureDecimals; @@ -426,6 +431,10 @@ public: configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled); // A 3-argument getJsonValue() assigns the 3rd argument as a default value if the Json value is missing + uint8_t tmpI2cAddress; + configComplete &= getJsonValue(top[F("I2CAddress")], tmpI2cAddress, 0x76); + i2cAddress = static_cast(tmpI2cAddress); + configComplete &= getJsonValue(top[F("TemperatureDecimals")], TemperatureDecimals, 1); configComplete &= getJsonValue(top[F("HumidityDecimals")], HumidityDecimals, 0); configComplete &= getJsonValue(top[F("PressureDecimals")], PressureDecimals, 0); From 9e468bd059510c66bbb99e41ed4855193a9cc05c Mon Sep 17 00:00:00 2001 From: Brandon502 <105077712+Brandon502@users.noreply.github.com> Date: Sat, 11 May 2024 13:57:21 -0400 Subject: [PATCH 06/25] Pinwheel Expand 1D Optimizations Added small pinwheel size. Adjusts medium and large values. --- wled00/FX_fcn.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 17a504ea0..ec0e087bc 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -638,9 +638,12 @@ uint16_t IRAM_ATTR Segment::nrOfVStrips() const { } // Constants for mapping mode "Pinwheel" -constexpr int Pinwheel_Steps_Medium = 208; // no holes up to 32x32; 60fps -constexpr int Pinwheel_Size_Medium = 30; // larger than this -> use "Big" -constexpr int Pinwheel_Steps_Big = 360; // no holes expected up to 58x58; 40fps +constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16; +constexpr int Pinwheel_Size_Small = 16; +constexpr int Pinwheel_Steps_Medium = 200; // no holes up to 32x32; 60fps +constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big" +constexpr int Pinwheel_Steps_Big = 296; // no holes expected up to 58x58; 40fps +constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...208 to Radians constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...208 to Radians constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...360 to Radians @@ -661,7 +664,9 @@ uint16_t IRAM_ATTR Segment::virtualLength() const { vLen = max(vW,vH); // get the longest dimension break; case M12_sPinwheel: - if (max(vW,vH) <= Pinwheel_Size_Medium) + if (max(vW,vH) <= Pinwheel_Size_Small) + vLen = Pinwheel_Steps_Small; + else if (max(vW,vH) <= Pinwheel_Size_Medium) vLen = Pinwheel_Steps_Medium; else vLen = Pinwheel_Steps_Big; @@ -736,8 +741,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) // i = angle --> 0 through 359 (Big), OR 0 through 208 (Medium) float centerX = roundf((vW-1) / 2.0f); float centerY = roundf((vH-1) / 2.0f); - // int maxDistance = sqrt(centerX * centerX + centerY * centerY) + 1; - float angleRad = (max(vW,vH) > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med; // angle in radians + float angleRad = (max(vW, vH) > Pinwheel_Size_Small ? (max(vW, vH) > Pinwheel_Size_Medium ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small); // angle in radians float cosVal = cos_t(angleRad); float sinVal = sin_t(angleRad); @@ -885,7 +889,7 @@ uint32_t IRAM_ATTR Segment::getPixelColor(int i) float distance = max(1.0f, min(vH-1, vW-1) / 2.0f); float centerX = (vW - 1) / 2.0f; float centerY = (vH - 1) / 2.0f; - float angleRad = (max(vW,vH) > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med; // angle in radians + float angleRad = (max(vW, vH) > Pinwheel_Size_Small ? (max(vW, vH) > Pinwheel_Size_Medium ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small); // angle in radians int x = roundf(centerX + distance * cos_t(angleRad)); int y = roundf(centerY + distance * sin_t(angleRad)); return getPixelColorXY(x, y); From 1ff5cb0596d4a355a96570a296b5c7f58ba7cf92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Sun, 12 May 2024 11:12:13 +0200 Subject: [PATCH 07/25] Experimental parallel I2S support for ESP32 - increased outputs to 17 - increased max possible color order overrides - use WLED_USE_PARALLEL_I2S during compile WARNING: Do not set up more than 256 LEDs per output when using parallel I2S with NeoPixelBus less than 2.9.0 --- wled00/bus_wrapper.h | 65 +++++++++++++++++++++----- wled00/cfg.cpp | 14 +++--- wled00/const.h | 6 ++- wled00/data/settings_leds.htm | 86 ++++++++++++++++++----------------- wled00/set.cpp | 51 +++++++++++---------- wled00/xml.cpp | 36 ++++++++------- 6 files changed, 156 insertions(+), 102 deletions(-) diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index 99ae4c5ef..57e98467e 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -224,8 +224,11 @@ //#define B_32_I0_NEO_3 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_NEO_3 NeoPixelBusLg -//#define B_32_I1_NEO_3 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_NEO_3 NeoPixelBusLg // parallel I2S + #endif #endif //RGBW #define B_32_RN_NEO_4 NeoPixelBusLg @@ -234,8 +237,11 @@ //#define B_32_I0_NEO_4 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_NEO_4 NeoPixelBusLg -//#define B_32_I1_NEO_4 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_NEO_4 NeoPixelBusLg // parallel I2S + #endif #endif //400Kbps #define B_32_RN_400_3 NeoPixelBusLg @@ -244,8 +250,11 @@ //#define B_32_I0_400_3 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_400_3 NeoPixelBusLg -//#define B_32_I1_400_3 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_400_3 NeoPixelBusLg // parallel I2S + #endif #endif //TM1814 (RGBW) #define B_32_RN_TM1_4 NeoPixelBusLg @@ -254,8 +263,11 @@ //#define B_32_I0_TM1_4 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_TM1_4 NeoPixelBusLg -//#define B_32_I1_TM1_4 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_TM1_4 NeoPixelBusLg // parallel I2S + #endif #endif //TM1829 (RGB) #define B_32_RN_TM2_3 NeoPixelBusLg @@ -264,8 +276,11 @@ //#define B_32_I0_TM2_3 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_TM2_3 NeoPixelBusLg -//#define B_32_I1_TM2_3 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_TM2_3 NeoPixelBusLg // parallel I2S + #endif #endif //UCS8903 #define B_32_RN_UCS_3 NeoPixelBusLg @@ -274,8 +289,11 @@ //#define B_32_I0_UCS_3 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_UCS_3 NeoPixelBusLg -//#define B_32_I1_UCS_3 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_UCS_3 NeoPixelBusLg // parallel I2S + #endif #endif //UCS8904 #define B_32_RN_UCS_4 NeoPixelBusLg @@ -284,8 +302,11 @@ //#define B_32_I0_UCS_4 NeoPixelBusLg// parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_UCS_4 NeoPixelBusLg -//#define B_32_I1_UCS_4 NeoPixelBusLg// parallel I2S + #else +#define B_32_I1_UCS_4 NeoPixelBusLg// parallel I2S + #endif #endif #define B_32_RN_APA106_3 NeoPixelBusLg #ifndef WLED_NO_I2S0_PIXELBUS @@ -293,8 +314,11 @@ //#define B_32_I0_APA106_3 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_APA106_3 NeoPixelBusLg -//#define B_32_I1_APA106_3 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_APA106_3 NeoPixelBusLg // parallel I2S + #endif #endif //FW1906 GRBCW #define B_32_RN_FW6_5 NeoPixelBusLg @@ -303,8 +327,11 @@ //#define B_32_I0_FW6_5 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_FW6_5 NeoPixelBusLg -//#define B_32_I1_FW6_5 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_FW6_5 NeoPixelBusLg // parallel I2S + #endif #endif //WS2805 RGBWC #define B_32_RN_2805_5 NeoPixelBusLg @@ -313,8 +340,11 @@ //#define B_32_I0_2805_5 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_2805_5 NeoPixelBusLg -//#define B_32_I1_2805_5 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_2805_5 NeoPixelBusLg // parallel I2S + #endif #endif //TM1914 (RGB) #define B_32_RN_TM1914_3 NeoPixelBusLg @@ -323,8 +353,11 @@ //#define B_32_I0_TM1914_3 NeoPixelBusLg #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_TM1914_3 NeoPixelBusLg -//#define B_32_I1_TM1914_3 NeoPixelBusLg + #else +#define B_32_I1_TM1914_3 NeoPixelBusLg + #endif #endif #endif @@ -541,7 +574,11 @@ class PolyBus { #if defined(ARDUINO_ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3)) // NOTE: "channel" is only used on ESP32 (and its variants) for RMT channel allocation // since 0.15.0-b3 I2S1 is favoured for classic ESP32 and moved to position 0 (channel 0) so we need to subtract 1 for correct RMT allocation + #ifdef WLED_USE_PARALLEL_I2S + if (channel > 7) channel -= 8; // accommodate parallel I2S1 which is used 1st on classic ESP32 + #else if (channel > 0) channel--; // accommodate I2S1 which is used as 1st bus on classic ESP32 + #endif #endif void* busPtr = nullptr; switch (busType) { @@ -1619,9 +1656,15 @@ class PolyBus { //if (num > 3) offset = num -4; // I2S not supported yet #else // standard ESP32 has 8 RMT and 2 I2S channels + #ifdef WLED_USE_PARALLEL_I2S + if (num > 16) return I_NONE; + if (num < 8) offset = 2; // prefer 8 parallel I2S1 channels + if (num == 16) offset = 1; + #else if (num > 9) return I_NONE; if (num > 8) offset = 1; if (num == 0) offset = 2; // prefer I2S1 for 1st bus (less flickering but more RAM needed) + #endif #endif switch (busType) { case TYPE_WS2812_1CH_X3: diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 22bfe577a..addd3fc5e 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -124,7 +124,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(strip.panels, matrix[F("mpc")]); strip.panel.clear(); JsonArray panels = matrix[F("panels")]; - uint8_t s = 0; + int s = 0; if (!panels.isNull()) { strip.panel.reserve(max(1U,min((size_t)strip.panels,(size_t)WLED_MAX_PANELS))); // pre-allocate memory for panels for (JsonObject pnl : panels) { @@ -156,7 +156,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { JsonArray ins = hw_led["ins"]; if (fromFS || !ins.isNull()) { - uint8_t s = 0; // bus iterator + int s = 0; // bus iterator if (fromFS) BusManager::removeAll(); // can't safely manipulate busses directly in network callback uint32_t mem = 0, globalBufMem = 0; uint16_t maxlen = 0; @@ -790,7 +790,7 @@ void serializeConfig() { JsonObject matrix = hw_led.createNestedObject(F("matrix")); matrix[F("mpc")] = strip.panels; JsonArray panels = matrix.createNestedArray(F("panels")); - for (uint8_t i=0; igetLength()==0) break; JsonObject ins = hw_led_ins.createNestedObject(); @@ -815,7 +815,7 @@ void serializeConfig() { JsonArray ins_pin = ins.createNestedArray("pin"); uint8_t pins[5]; uint8_t nPins = bus->getPins(pins); - for (uint8_t i = 0; i < nPins; i++) ins_pin.add(pins[i]); + for (int i = 0; i < nPins; i++) ins_pin.add(pins[i]); ins[F("order")] = bus->getColorOrder(); ins["rev"] = bus->isReversed(); ins[F("skip")] = bus->skippedLeds(); @@ -829,7 +829,7 @@ void serializeConfig() { JsonArray hw_com = hw.createNestedArray(F("com")); const ColorOrderMap& com = BusManager::getColorOrderMap(); - for (uint8_t s = 0; s < com.count(); s++) { + for (int s = 0; s < com.count(); s++) { const ColorOrderMapEntry *entry = com.get(s); if (!entry) break; @@ -846,7 +846,7 @@ void serializeConfig() { JsonArray hw_btn_ins = hw_btn.createNestedArray("ins"); // configuration for all buttons - for (uint8_t i=0; i LED Settings