diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml
index 285ad419e..6f010aa60 100644
--- a/.github/ISSUE_TEMPLATE/bug.yml
+++ b/.github/ISSUE_TEMPLATE/bug.yml
@@ -80,7 +80,7 @@ body:
id: terms
attributes:
label: Code of Conduct
- description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/Aircoookie/WLED/blob/master/CODE_OF_CONDUCT.md)
+ description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/wled-dev/WLED/blob/main/CODE_OF_CONDUCT.md)
options:
- label: I agree to follow this project's Code of Conduct
required: true
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index a5c80f22d..28a29833e 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -19,14 +19,6 @@ jobs:
uses: actions/download-artifact@v4
with:
merge-multiple: true
- - name: Show Files
- run: ls -la
- - name: "✏️ Generate release changelog"
- id: changelog
- uses: janheinrichmerker/action-github-changelog-generator@v2.3
- with:
- token: ${{ secrets.GITHUB_TOKEN }}
- sinceTag: v0.15.0
- name: Update Nightly Release
uses: andelf/nightly-release@main
env:
@@ -35,7 +27,7 @@ jobs:
tag_name: nightly
name: 'Nightly Release $$'
prerelease: true
- body: ${{ steps.changelog.outputs.changelog }}
+ body: 'nightly'
files: |
*.bin
*.bin.gz
diff --git a/.gitignore b/.gitignore
index 8f083e3f6..51d321d92 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@ wled-update.sh
/build_output/
/node_modules/
+/logs/
/wled00/extLibs
/wled00/LittleFS
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 670b5561d..e2078df71 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -27,7 +27,7 @@ Github will pick up the changes so your PR stays up-to-date.
> For example, we regularly lost review comments when the PR author force-pushes code changes. So, pretty please, do not force-push.
-You can find a collection of very useful tips and tricks here: https://github.com/Aircoookie/WLED/wiki/How-to-properly-submit-a-PR
+You can find a collection of very useful tips and tricks here: https://github.com/wled-dev/WLED/wiki/How-to-properly-submit-a-PR
### Code style
diff --git a/package.json b/package.json
index 68260982e..26d24127c 100644
--- a/package.json
+++ b/package.json
@@ -14,14 +14,14 @@
},
"repository": {
"type": "git",
- "url": "git+https://github.com/Aircoookie/WLED.git"
+ "url": "git+https://github.com/wled-dev/WLED.git"
},
"author": "",
"license": "ISC",
"bugs": {
- "url": "https://github.com/Aircoookie/WLED/issues"
+ "url": "https://github.com/wled-dev/WLED/issues"
},
- "homepage": "https://github.com/Aircoookie/WLED#readme",
+ "homepage": "https://github.com/wled-dev/WLED#readme",
"dependencies": {
"clean-css": "^5.3.3",
"html-minifier-terser": "^7.2.0",
diff --git a/pio-scripts/build_ui.py b/pio-scripts/build_ui.py
index f3688a5d4..047fac442 100644
--- a/pio-scripts/build_ui.py
+++ b/pio-scripts/build_ui.py
@@ -1,3 +1,21 @@
-Import('env')
+Import("env")
+import shutil
-env.Execute("npm run build")
\ No newline at end of file
+node_ex = shutil.which("node")
+# Check if Node.js is installed and present in PATH if it failed, abort the build
+if node_ex is None:
+ print('\x1b[0;31;43m' + 'Node.js is not installed or missing from PATH html css js will not be processed check https://kno.wled.ge/advanced/compiling-wled/' + '\x1b[0m')
+ exitCode = env.Execute("null")
+ exit(exitCode)
+else:
+ # Install the necessary node packages for the pre-build asset bundling script
+ print('\x1b[6;33;42m' + 'Installing node packages' + '\x1b[0m')
+ env.Execute("npm install")
+
+ # Call the bundling script
+ exitCode = env.Execute("npm run build")
+
+ # If it failed, abort the build
+ if (exitCode):
+ print('\x1b[0;31;43m' + 'npm run build fails check https://kno.wled.ge/advanced/compiling-wled/' + '\x1b[0m')
+ exit(exitCode)
\ No newline at end of file
diff --git a/platformio.ini b/platformio.ini
index e8ddd309c..47dfd42f5 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -139,7 +139,7 @@ lib_compat_mode = strict
lib_deps =
fastled/FastLED @ 3.6.0
IRremoteESP8266 @ 2.8.2
- makuna/NeoPixelBus @ 2.8.0
+ makuna/NeoPixelBus @ 2.8.3
#https://github.com/makuna/NeoPixelBus.git#CoreShaderBeta
https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.0
# for I2C interface
diff --git a/platformio_override.sample.ini b/platformio_override.sample.ini
index 60f9efe65..f3b4e1c65 100644
--- a/platformio_override.sample.ini
+++ b/platformio_override.sample.ini
@@ -280,7 +280,7 @@ lib_deps = ${esp32s2.lib_deps}
[env:esp32s3dev_8MB_PSRAM_qspi]
;; ESP32-TinyS3 development board, with 8MB FLASH and PSRAM (memory_type: qio_qspi)
extends = env:esp32s3dev_8MB_PSRAM_opi
-;board = um_tinys3 ; -> needs workaround from https://github.com/Aircoookie/WLED/pull/2905#issuecomment-1328049860
+;board = um_tinys3 ; -> needs workaround from https://github.com/wled-dev/WLED/pull/2905#issuecomment-1328049860
board = esp32-s3-devkitc-1 ;; generic dev board; the next line adds PSRAM support
board_build.arduino.memory_type = qio_qspi ;; use with PSRAM: 2MB or 4MB
diff --git a/readme.md b/readme.md
index 8c9a08801..c0d24cffa 100644
--- a/readme.md
+++ b/readme.md
@@ -1,12 +1,12 @@
-
-
+
+
-
+
diff --git a/tools/cdata.js b/tools/cdata.js
index c5d3c6aa5..b2feffee8 100644
--- a/tools/cdata.js
+++ b/tools/cdata.js
@@ -89,7 +89,7 @@ function adoptVersionAndRepo(html) {
repoUrl = repoUrl.replace(/^git\+/, "");
repoUrl = repoUrl.replace(/\.git$/, "");
html = html.replaceAll("https://github.com/atuline/WLED", repoUrl);
- html = html.replaceAll("https://github.com/Aircoookie/WLED", repoUrl);
+ html = html.replaceAll("https://github.com/wled-dev/WLED", repoUrl);
}
let version = packageJson.version;
if (version) {
diff --git a/usermods/EXAMPLE/usermod_v2_example.cpp b/usermods/EXAMPLE/usermod_v2_example.cpp
index be4528dee..fc50833ee 100644
--- a/usermods/EXAMPLE/usermod_v2_example.cpp
+++ b/usermods/EXAMPLE/usermod_v2_example.cpp
@@ -2,7 +2,7 @@
/*
* Usermods allow you to add own functionality to WLED more easily
- * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
+ * See: https://github.com/wled-dev/WLED/wiki/Add-own-functionality
*
* This is an example for a v2 usermod.
* v2 usermods are class inheritance based and can (but don't have to) implement more functions, each of them is shown in this example.
diff --git a/usermods/Fix_unreachable_netservices_v2/usermod_Fix_unreachable_netservices.cpp b/usermods/Fix_unreachable_netservices_v2/usermod_Fix_unreachable_netservices.cpp
index d1a5776c5..7fb8e9798 100644
--- a/usermods/Fix_unreachable_netservices_v2/usermod_Fix_unreachable_netservices.cpp
+++ b/usermods/Fix_unreachable_netservices_v2/usermod_Fix_unreachable_netservices.cpp
@@ -8,7 +8,7 @@
* By this procedure the net services of WLED remains accessible in some problematic WLAN environments.
*
* Usermods allow you to add own functionality to WLED more easily
- * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
+ * See: https://github.com/wled-dev/WLED/wiki/Add-own-functionality
*
* v2 usermods are class inheritance based and can (but don't have to) implement more functions, each of them is shown in this example.
* Multiple v2 usermods can be added to one compilation easily.
diff --git a/usermods/PIR_sensor_switch/PIR_Highlight_Standby b/usermods/PIR_sensor_switch/PIR_Highlight_Standby
index 152388e8b..4ca32bf4e 100644
--- a/usermods/PIR_sensor_switch/PIR_Highlight_Standby
+++ b/usermods/PIR_sensor_switch/PIR_Highlight_Standby
@@ -42,7 +42,7 @@
*
*
* Usermods allow you to add own functionality to WLED more easily
- * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
+ * See: https://github.com/wled-dev/WLED/wiki/Add-own-functionality
*
* v2 usermods are class inheritance based and can (but don't have to) implement more functions, each of them is shown in this example.
* Multiple v2 usermods can be added to one compilation easily.
diff --git a/usermods/PIR_sensor_switch/PIR_sensor_switch.cpp b/usermods/PIR_sensor_switch/PIR_sensor_switch.cpp
index 20e4bc148..6f09ce5be 100644
--- a/usermods/PIR_sensor_switch/PIR_sensor_switch.cpp
+++ b/usermods/PIR_sensor_switch/PIR_sensor_switch.cpp
@@ -24,7 +24,7 @@
* Maintained by: @blazoncek
*
* Usermods allow you to add own functionality to WLED more easily
- * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
+ * See: https://github.com/wled-dev/WLED/wiki/Add-own-functionality
*
* v2 usermods are class inheritance based and can (but don't have to) implement more functions, each of them is shown in this example.
* Multiple v2 usermods can be added to one compilation easily.
diff --git a/usermods/PIR_sensor_switch/readme.md b/usermods/PIR_sensor_switch/readme.md
index fac5419f0..be55406df 100644
--- a/usermods/PIR_sensor_switch/readme.md
+++ b/usermods/PIR_sensor_switch/readme.md
@@ -5,7 +5,7 @@ This usermod-v2 modification allows the connection of a PIR sensor to switch on
_Story:_
I use the PIR Sensor to automatically turn on the WLED analog clock in my home office room when I am there.
-The LED strip is switched [using a relay](https://github.com/Aircoookie/WLED/wiki/Control-a-relay-with-WLED) to keep the power consumption low when it is switched off.
+The LED strip is switched [using a relay](https://kno.wled.ge/features/relay-control/) to keep the power consumption low when it is switched off.
## Web interface
diff --git a/usermods/TTGO-T-Display/usermod.cpp b/usermods/TTGO-T-Display/usermod.cpp
index cbba07771..d8dcb2999 100644
--- a/usermods/TTGO-T-Display/usermod.cpp
+++ b/usermods/TTGO-T-Display/usermod.cpp
@@ -1,7 +1,7 @@
/*
* This file allows you to add own functionality to WLED more easily
- * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
+ * See: https://github.com/wled-dev/WLED/wiki/Add-own-functionality
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
* bytes 2400+ are currently unused, but might be used for future wled features
*/
diff --git a/usermods/TetrisAI_v2/readme.md b/usermods/TetrisAI_v2/readme.md
index b56f801a8..5ac802896 100644
--- a/usermods/TetrisAI_v2/readme.md
+++ b/usermods/TetrisAI_v2/readme.md
@@ -6,7 +6,7 @@ Version 1.0
## Installation
-Just activate the usermod with `-D USERMOD_TETRISAI` and the effect will become available under the name 'Tetris AI'. If you are running out of flash memory, use a different memory layout (e.g. [WLED_ESP32_4MB_256KB_FS.csv](https://github.com/Aircoookie/WLED/blob/main/tools/WLED_ESP32_4MB_256KB_FS.csv)).
+Just activate the usermod with `-D USERMOD_TETRISAI` and the effect will become available under the name 'Tetris AI'. If you are running out of flash memory, use a different memory layout (e.g. [WLED_ESP32_4MB_256KB_FS.csv](https://github.com/wled-dev/WLED/blob/main/tools/WLED_ESP32_4MB_256KB_FS.csv)).
If needed simply add to `platformio_override.ini` (or `platformio_override.ini`):
diff --git a/usermods/audioreactive/audio_reactive.cpp b/usermods/audioreactive/audio_reactive.cpp
index a5bf782ad..ee88287b5 100644
--- a/usermods/audioreactive/audio_reactive.cpp
+++ b/usermods/audioreactive/audio_reactive.cpp
@@ -18,7 +18,7 @@
/*
* Usermods allow you to add own functionality to WLED more easily
- * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
+ * See: https://github.com/wled-dev/WLED/wiki/Add-own-functionality
*
* This is an audioreactive v2 usermod.
* ....
diff --git a/usermods/buzzer/buzzer.cpp b/usermods/buzzer/buzzer.cpp
index e5a071e62..60db08abc 100644
--- a/usermods/buzzer/buzzer.cpp
+++ b/usermods/buzzer/buzzer.cpp
@@ -10,7 +10,7 @@
/*
* Usermods allow you to add own functionality to WLED more easily
- * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
+ * See: https://github.com/wled-dev/WLED/wiki/Add-own-functionality
*
* Using a usermod:
* 1. Copy the usermod into the sketch folder (same folder as wled00.ino)
diff --git a/usermods/photoresistor_sensor_mqtt_v1/usermod.cpp b/usermods/photoresistor_sensor_mqtt_v1/usermod.cpp
index fff7118f3..bbbefc101 100644
--- a/usermods/photoresistor_sensor_mqtt_v1/usermod.cpp
+++ b/usermods/photoresistor_sensor_mqtt_v1/usermod.cpp
@@ -1,7 +1,7 @@
#include "wled.h"
/*
* This v1 usermod file allows you to add own functionality to WLED more easily
- * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
+ * See: https://github.com/wled-dev/WLED/wiki/Add-own-functionality
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
* If you just need 8 bytes, use 2551-2559 (you do not need to increase EEPSIZE)
*
diff --git a/usermods/pixels_dice_tray/platformio_override.ini.sample b/usermods/pixels_dice_tray/platformio_override.ini.sample
index b712f8b2e..6b4fa7768 100644
--- a/usermods/pixels_dice_tray/platformio_override.ini.sample
+++ b/usermods/pixels_dice_tray/platformio_override.ini.sample
@@ -102,7 +102,7 @@ lib_deps = ${esp32s3.lib_deps}
# parallel. Also not clear exactly what difference between the ESP32 and the
# ESP32S3 would be causing this, though they do run different BLE versions.
# May be related to some of the issues discussed in:
-# https://github.com/Aircoookie/WLED/issues/1382
+# https://github.com/wled-dev/WLED/issues/1382
; [env:esp32dev_dice]
; extends = env:esp32dev
; build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=ESP32
diff --git a/usermods/stairway_wipe_basic/stairway_wipe_basic.cpp b/usermods/stairway_wipe_basic/stairway_wipe_basic.cpp
index cdb7cd662..cddd655d6 100644
--- a/usermods/stairway_wipe_basic/stairway_wipe_basic.cpp
+++ b/usermods/stairway_wipe_basic/stairway_wipe_basic.cpp
@@ -2,7 +2,7 @@
/*
* Usermods allow you to add own functionality to WLED more easily
- * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
+ * See: https://github.com/wled-dev/WLED/wiki/Add-own-functionality
*
* This is Stairway-Wipe as a v2 usermod.
*
diff --git a/usermods/usermod_v2_brightness_follow_sun/README.md b/usermods/usermod_v2_brightness_follow_sun/README.md
new file mode 100644
index 000000000..25daf0ba2
--- /dev/null
+++ b/usermods/usermod_v2_brightness_follow_sun/README.md
@@ -0,0 +1,35 @@
+# Update Brightness Follow Sun
+
+This UserMod can set brightness by mapping [minimum-maximum-minimum] from [sunrise-suntop-sunset], I use this UserMod to adjust the brightness of my plant growth light (pwm led), and I think it will make my plants happy.
+
+This UserMod will adjust brightness from sunrise to sunset, reaching maximum brightness at the zenith of the sun. It can also maintain the lowest brightness within 0-6 hours before sunrise and after sunset according to the settings.
+
+## Installation
+
+define `USERMOD_BRIGHTNESS_FOLLOW_SUN` e.g. `#define USERMOD_BRIGHTNESS_FOLLOW_SUN` in my_config.h
+
+or add `-D USERMOD_BRIGHTNESS_FOLLOW_SUN` to `build_flags` in platformio_override.ini
+
+
+### Options
+Open Usermod Settings in WLED to change settings:
+
+`Enable` - When checked `Enable`, turn on the `Brightness Follow Sun` Usermod, which will automatically turn on the lights, adjust the brightness, and turn off the lights. If you need to completely turn off the lights, please unchecked `Enable`.
+
+`Update Interval Sec` - The unit is seconds, and the brightness will be automatically refreshed according to the set parameters.
+
+`Min Brightness` - set brightness by map of min-max-min : sunrise-suntop-sunset
+
+`Max Brightness` - It needs to be set to a value greater than `Min Brightness`, otherwise it will always remain at `Min Brightness`.
+
+`Relax Hour` - The unit is in hours, with an effective range of 0-6. According to the settings, maintain the lowest brightness for 0-6 hours before sunrise and after sunset.
+
+
+### PlatformIO requirements
+
+No special requirements.
+
+## Change Log
+
+2025-01-02
+* init
diff --git a/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h
new file mode 100644
index 000000000..99f646b21
--- /dev/null
+++ b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h
@@ -0,0 +1,130 @@
+#pragma once
+
+#include "wled.h"
+
+//v2 usermod that allows to change brightness and color using a rotary encoder,
+//change between modes by pressing a button (many encoders have one included)
+class UsermodBrightnessFollowSun : public Usermod
+{
+private:
+ static const char _name[];
+ static const char _enabled[];
+ static const char _update_interval[];
+ static const char _min_bri[];
+ static const char _max_bri[];
+ static const char _relax_hour[];
+
+private:
+ bool enabled = false; //WLEDMM
+ unsigned long update_interval = 60;
+ unsigned long update_interval_ms = 60000;
+ int min_bri = 1;
+ int max_bri = 255;
+ float relax_hour = 0;
+ int relaxSec = 0;
+ unsigned long lastUMRun = 0;
+public:
+
+ void setup() {};
+
+ float mapFloat(float inputValue, float inMin, float inMax, float outMin, float outMax) {
+ if (inMax == inMin)
+ return outMin;
+
+ inputValue = constrain(inputValue, inMin, inMax);
+
+ return ((inputValue - inMin) * (outMax - outMin) / (inMax - inMin)) + outMin;
+ }
+
+ uint16_t getId() override
+ {
+ return USERMOD_ID_BRIGHTNESS_FOLLOW_SUN;
+ }
+
+ void update()
+ {
+ if (sunrise == 0 || sunset == 0 || localTime == 0)
+ return;
+
+ int curSec = elapsedSecsToday(localTime);
+ int sunriseSec = elapsedSecsToday(sunrise);
+ int sunsetSec = elapsedSecsToday(sunset);
+ int sunMiddleSec = sunriseSec + (sunsetSec-sunriseSec)/2;
+
+ int relaxSecH = sunriseSec-relaxSec;
+ int relaxSecE = sunsetSec+relaxSec;
+
+ int briSet = 0;
+ if (curSec >= relaxSecH && curSec <= relaxSecE) {
+ float timeMapToAngle = curSec < sunMiddleSec ?
+ mapFloat(curSec, sunriseSec, sunMiddleSec, 0, M_PI/2.0) :
+ mapFloat(curSec, sunMiddleSec, sunsetSec, M_PI/2.0, M_PI);
+ float sinValue = sin_t(timeMapToAngle);
+ briSet = min_bri + (max_bri-min_bri)*sinValue;
+ }
+
+ bri = briSet;
+ stateUpdated(CALL_MODE_DIRECT_CHANGE);
+}
+
+ void loop() override
+ {
+ if (!enabled || strip.isUpdating())
+ return;
+
+ if (millis() - lastUMRun < update_interval_ms)
+ return;
+ lastUMRun = millis();
+
+ update();
+ }
+
+ void addToConfig(JsonObject& root)
+ {
+ JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
+
+ top[FPSTR(_enabled)] = enabled;
+ top[FPSTR(_update_interval)] = update_interval;
+ top[FPSTR(_min_bri)] = min_bri;
+ top[FPSTR(_max_bri)] = max_bri;
+ top[FPSTR(_relax_hour)] = relax_hour;
+ }
+
+ bool readFromConfig(JsonObject& root)
+ {
+ JsonObject top = root[FPSTR(_name)];
+ if (top.isNull()) {
+ DEBUG_PRINTF("[%s] No config found. (Using defaults.)\n", _name);
+ return false;
+ }
+
+ bool configComplete = true;
+
+ configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled, false);
+ configComplete &= getJsonValue(top[FPSTR(_update_interval)], update_interval, 60);
+ configComplete &= getJsonValue(top[FPSTR(_min_bri)], min_bri, 1);
+ configComplete &= getJsonValue(top[FPSTR(_max_bri)], max_bri, 255);
+ configComplete &= getJsonValue(top[FPSTR(_relax_hour)], relax_hour, 0);
+
+ update_interval = constrain(update_interval, 1, SECS_PER_HOUR);
+ min_bri = constrain(min_bri, 1, 255);
+ max_bri = constrain(max_bri, 1, 255);
+ relax_hour = constrain(relax_hour, 0, 6);
+
+ update_interval_ms = update_interval*1000;
+ relaxSec = SECS_PER_HOUR*relax_hour;
+
+ lastUMRun = 0;
+ update();
+
+ return configComplete;
+ }
+};
+
+
+const char UsermodBrightnessFollowSun::_name[] PROGMEM = "Brightness Follow Sun";
+const char UsermodBrightnessFollowSun::_enabled[] PROGMEM = "Enabled";
+const char UsermodBrightnessFollowSun::_update_interval[] PROGMEM = "Update Interval Sec";
+const char UsermodBrightnessFollowSun::_min_bri[] PROGMEM = "Min Brightness";
+const char UsermodBrightnessFollowSun::_max_bri[] PROGMEM = "Max Brightness";
+const char UsermodBrightnessFollowSun::_relax_hour[] PROGMEM = "Relax Hour";
diff --git a/usermods/usermod_v2_word_clock/usermod_v2_word_clock.cpp b/usermods/usermod_v2_word_clock/usermod_v2_word_clock.cpp
index 789292387..5100da180 100644
--- a/usermods/usermod_v2_word_clock/usermod_v2_word_clock.cpp
+++ b/usermods/usermod_v2_word_clock/usermod_v2_word_clock.cpp
@@ -2,7 +2,7 @@
/*
* Usermods allow you to add own functionality to WLED more easily
- * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
+ * See: https://github.com/wled-dev/WLED/wiki/Add-own-functionality
*
* This usermod can be used to drive a wordclock with a 11x10 pixel matrix with WLED. There are also 4 additional dots for the minutes.
* The visualisation is described in 4 mask with LED numbers (single dots for minutes, minutes, hours and "clock/Uhr").
diff --git a/wled00/FX.cpp b/wled00/FX.cpp
index 594822641..0b9429ca1 100644
--- a/wled00/FX.cpp
+++ b/wled00/FX.cpp
@@ -1134,7 +1134,7 @@ uint16_t mode_running_random(void) {
unsigned z = it % zoneSize;
bool nzone = (!z && it != SEGENV.aux1);
- for (unsigned i=SEGLEN-1; i > 0; i--) {
+ for (int i=SEGLEN-1; i >= 0; i--) {
if (nzone || z >= zoneSize) {
unsigned lastrand = PRNG16 >> 8;
int16_t diff = 0;
@@ -1768,7 +1768,7 @@ uint16_t mode_random_chase(void) {
uint32_t color = SEGENV.step;
random16_set_seed(SEGENV.aux0);
- for (unsigned i = SEGLEN -1; i > 0; i--) {
+ for (int i = SEGLEN -1; i >= 0; i--) {
uint8_t r = random8(6) != 0 ? (color >> 16 & 0xFF) : random8();
uint8_t g = random8(6) != 0 ? (color >> 8 & 0xFF) : random8();
uint8_t b = random8(6) != 0 ? (color & 0xFF) : random8();
@@ -2358,12 +2358,14 @@ uint16_t mode_meteor() {
for (unsigned i = 0; i < SEGLEN; i++) {
uint32_t col;
if (hw_random8() <= 255 - SEGMENT.intensity) {
- if(meteorSmooth) {
- int change = trail[i] + 4 - hw_random8(24); //change each time between -20 and +4
- trail[i] = constrain(change, 0, max);
- col = SEGMENT.check1 ? SEGMENT.color_from_palette(i, true, false, 0, trail[i]) : SEGMENT.color_from_palette(trail[i], false, true, 255);
+ if(meteorSmooth) {
+ if (trail[i] > 0) {
+ int change = trail[i] + 4 - hw_random8(24); //change each time between -20 and +4
+ trail[i] = constrain(change, 0, max);
}
- else {
+ col = SEGMENT.check1 ? SEGMENT.color_from_palette(i, true, false, 0, trail[i]) : SEGMENT.color_from_palette(trail[i], false, true, 255);
+ }
+ else {
trail[i] = scale8(trail[i], 128 + hw_random8(127));
int index = trail[i];
int idx = 255;
@@ -3015,7 +3017,7 @@ static const char _data_FX_MODE_BOUNCINGBALLS[] PROGMEM = "Bouncing Balls@Gravit
/*
* bouncing balls on a track track Effect modified from Aircoookie's bouncing balls
* Courtesy of pjhatch (https://github.com/pjhatch)
- * https://github.com/Aircoookie/WLED/pull/1039
+ * https://github.com/wled-dev/WLED/pull/1039
*/
// modified for balltrack mode
typedef struct RollingBall {
@@ -4852,7 +4854,6 @@ static const char _data_FX_MODE_FLOWSTRIPE[] PROGMEM = "Flow Stripe@Hue speed,Ef
#ifndef WLED_DISABLE_2D
///////////////////////////////////////////////////////////////////////////////
//*************************** 2D routines ***********************************
-#define XY(x,y) SEGMENT.XY(x,y)
// Black hole
@@ -5101,6 +5102,7 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https:
const int cols = SEG_W;
const int rows = SEG_H;
+ const auto XY = [&](int x, int y) { return (x%cols) + (y%rows) * cols; };
const unsigned dataSize = sizeof(CRGB) * SEGMENT.length(); // using width*height prevents reallocation if mirroring is enabled
const int crcBufferLen = 2; //(SEGMENT.width() + SEGMENT.height())*71/100; // roughly sqrt(2)/2 for better repetition detection (Ewowi)
@@ -5374,6 +5376,7 @@ uint16_t mode_2Dmatrix(void) { // Matrix2D. By Jeremy Williams.
const int cols = SEG_W;
const int rows = SEG_H;
+ const auto XY = [&](int x, int y) { return (x%cols) + (y%rows) * cols; };
unsigned dataSize = (SEGMENT.length()+7) >> 3; //1 bit per LED for trails
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
@@ -7471,6 +7474,7 @@ uint16_t mode_2Dsoap() {
const int cols = SEG_W;
const int rows = SEG_H;
+ const auto XY = [&](int x, int y) { return (x%cols) + (y%rows) * cols; };
const size_t dataSize = SEGMENT.width() * SEGMENT.height() * sizeof(uint8_t); // prevent reallocation if mirrored or grouped
if (!SEGENV.allocateData(dataSize + sizeof(uint32_t)*3)) return mode_static(); //allocation failed
@@ -7583,6 +7587,7 @@ uint16_t mode_2Doctopus() {
const int cols = SEG_W;
const int rows = SEG_H;
+ const auto XY = [&](int x, int y) { return (x%cols) + (y%rows) * cols; };
const uint8_t mapp = 180 / MAX(cols,rows);
typedef struct {
diff --git a/wled00/FX.h b/wled00/FX.h
index 3b1f8f8f1..934742466 100644
--- a/wled00/FX.h
+++ b/wled00/FX.h
@@ -1,3 +1,4 @@
+#pragma once
/*
WS2812FX.h - Library for WS2812 LED effects.
Harm Aldick - 2016
@@ -8,12 +9,15 @@
Adapted from code originally licensed under the MIT license
Modified for WLED
+
+ Segment class/struct (c) 2022 Blaz Kristan (@blazoncek)
*/
#ifndef WS2812FX_h
#define WS2812FX_h
#include
+#include "wled.h"
#include "const.h"
#include "bus_manager.h"
@@ -71,18 +75,15 @@ extern byte realtimeMode; // used in getMappedPixelIndex()
/* each segment uses 82 bytes of SRAM memory, so if you're application fails because of
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
#ifdef ESP8266
- #define MAX_NUM_SEGMENTS 16
+ #define MAX_NUM_SEGMENTS 16
/* How much data bytes all segments combined may allocate */
#define MAX_SEGMENT_DATA 5120
+#elif defined(CONFIG_IDF_TARGET_ESP32S2)
+ #define MAX_NUM_SEGMENTS 20
+ #define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*512) // 10k by default (S2 is short on free RAM)
#else
- #ifndef MAX_NUM_SEGMENTS
- #define MAX_NUM_SEGMENTS 32
- #endif
- #if defined(ARDUINO_ARCH_ESP32S2)
- #define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*768) // 24k by default (S2 is short on free RAM)
- #else
- #define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*1280) // 40k by default
- #endif
+ #define MAX_NUM_SEGMENTS 32 // warning: going beyond 32 may consume too much RAM for stable operation
+ #define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*1280) // 40k by default
#endif
/* How much data bytes each segment should max allocate to leave enough space for other segments,
@@ -571,6 +572,8 @@ typedef struct Segment {
inline uint16_t groupLength() const { return grouping + spacing; }
inline uint8_t getLightCapabilities() const { return _capabilities; }
inline void deactivate() { setGeometry(0,0); }
+ inline Segment &clearName() { if (name) free(name); name = nullptr; return *this; }
+ inline Segment &setName(const String &name) { return setName(name.c_str()); }
inline static unsigned getUsedSegmentData() { return Segment::_usedSegmentData; }
inline static void addUsedSegmentData(int len) { Segment::_usedSegmentData += len; }
@@ -593,6 +596,7 @@ typedef struct Segment {
Segment &setOption(uint8_t n, bool val);
Segment &setMode(uint8_t fx, bool loadDefaults = false);
Segment &setPalette(uint8_t pal);
+ Segment &setName(const char* name);
uint8_t differs(const Segment& b) const;
void refreshLightCapabilities();
@@ -674,7 +678,6 @@ typedef struct Segment {
}
#ifndef WLED_DISABLE_2D
inline bool is2D() const { return (width()>1 && height()>1); }
- [[gnu::hot]] int XY(int x, int y) const; // support function to get relative index within segment
[[gnu::hot]] void setPixelColorXY(int x, int y, uint32_t c) const; // set relative pixel within segment with color
inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) const { setPixelColorXY(int(x), int(y), c); }
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) const { setPixelColorXY(x, y, RGBW32(r,g,b,w)); }
@@ -711,8 +714,7 @@ typedef struct Segment {
void wu_pixel(uint32_t x, uint32_t y, CRGB c);
inline void fill_solid(CRGB c) { fill(RGBW32(c.r,c.g,c.b,0)); }
#else
- inline constexpr bool is2D() const { return false; }
- inline int XY(int x, int y) const { return x; }
+ inline bool is2D() const { return false; }
inline void setPixelColorXY(int x, int y, uint32_t c) { setPixelColor(x, c); }
inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColor(int(x), c); }
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColor(x, RGBW32(r,g,b,w)); }
diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp
index 67624bac3..893123335 100644
--- a/wled00/FX_2Dfcn.cpp
+++ b/wled00/FX_2Dfcn.cpp
@@ -145,14 +145,6 @@ void WS2812FX::setUpMatrix() {
#ifndef WLED_DISABLE_2D
-// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
-int IRAM_ATTR_YN Segment::XY(int x, int y) const
-{
- const int vW = vWidth(); // segment width in logical pixels (can be 0 if segment is inactive)
- const int vH = vHeight(); // segment height in logical pixels (is always >= 1)
- return isActive() ? (x%vW) + (y%vH) * vW : 0;
-}
-
// raw setColor function without checks (checks are done in setPixelColorXY())
void IRAM_ATTR_YN Segment::_setPixelColorXY_raw(const int& x, const int& y, uint32_t& col) const
{
@@ -166,16 +158,11 @@ void IRAM_ATTR_YN Segment::_setPixelColorXY_raw(const int& x, const int& y, uint
// Apply mirroring
if (mirror || mirror_y) {
- auto setMirroredPixel = [&](int mx, int my) {
- strip.setPixelColorXY(mx, my, col);
- };
-
const int mirrorX = start + width() - x - 1;
const int mirrorY = startY + height() - y - 1;
-
- if (mirror) setMirroredPixel(transpose ? baseX : mirrorX, transpose ? mirrorY : baseY);
- if (mirror_y) setMirroredPixel(transpose ? mirrorX : baseX, transpose ? baseY : mirrorY);
- if (mirror && mirror_y) setMirroredPixel(mirrorX, mirrorY);
+ if (mirror) strip.setPixelColorXY(transpose ? baseX : mirrorX, transpose ? mirrorY : baseY, col);
+ if (mirror_y) strip.setPixelColorXY(transpose ? mirrorX : baseX, transpose ? baseY : mirrorY, col);
+ if (mirror && mirror_y) strip.setPixelColorXY(mirrorX, mirrorY, col);
}
}
diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp
index cf37a46c2..2e1c84412 100644
--- a/wled00/FX_fcn.cpp
+++ b/wled00/FX_fcn.cpp
@@ -649,6 +649,20 @@ Segment &Segment::setPalette(uint8_t pal) {
return *this;
}
+Segment &Segment::setName(const char *newName) {
+ if (newName) {
+ const int newLen = min(strlen(newName), (size_t)WLED_MAX_SEGNAME_LEN);
+ if (newLen) {
+ if (name) name = static_cast(realloc(name, newLen+1));
+ else name = static_cast(malloc(newLen+1));
+ if (name) strlcpy(name, newName, newLen+1);
+ name[newLen] = 0;
+ return *this;
+ }
+ }
+ return clearName();
+}
+
// 2D matrix
unsigned Segment::virtualWidth() const {
unsigned groupLen = groupLength();
@@ -754,7 +768,7 @@ bool IRAM_ATTR_YN Segment::isPixelClipped(int i) const {
//if (!invert && iInside) return _modeBlend;
//if ( invert && !iInside) return _modeBlend;
//return !_modeBlend;
- return !iInside ^ invert ^ _modeBlend; // thanks @willmmiles (https://github.com/Aircoookie/WLED/pull/3877#discussion_r1554633876)
+ return !iInside ^ invert ^ _modeBlend; // thanks @willmmiles (https://github.com/wled-dev/WLED/pull/3877#discussion_r1554633876)
}
#endif
return false;
@@ -1311,6 +1325,34 @@ void WS2812FX::finalizeInit() {
_hasWhiteChannel = _isOffRefreshRequired = false;
+ unsigned digitalCount = 0;
+ #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
+ // determine if it is sensible to use parallel I2S outputs on ESP32 (i.e. more than 5 outputs = 1 I2S + 4 RMT)
+ unsigned maxLedsOnBus = 0;
+ for (const auto &bus : busConfigs) {
+ if (Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type)) {
+ digitalCount++;
+ if (bus.count > maxLedsOnBus) maxLedsOnBus = bus.count;
+ }
+ }
+ DEBUG_PRINTF_P(PSTR("Maximum LEDs on a bus: %u\nDigital buses: %u\n"), maxLedsOnBus, digitalCount);
+ // we may remove 300 LEDs per bus limit when NeoPixelBus is updated beyond 2.9.0
+ if (maxLedsOnBus <= 300 && useParallelI2S) BusManager::useParallelOutput(); // must call before creating buses
+ else useParallelI2S = false; // enforce single I2S
+ #endif
+
+ // create buses/outputs
+ unsigned mem = 0;
+ digitalCount = 0;
+ for (const auto &bus : busConfigs) {
+ mem += bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount++ : 0); // includes global buffer
+ if (mem <= MAX_LED_MEMORY) {
+ if (BusManager::add(bus) == -1) break;
+ } else DEBUG_PRINTF_P(PSTR("Out of LED memory! Bus %d (%d) #%u not created."), (int)bus.type, (int)bus.count, digitalCount);
+ }
+ busConfigs.clear();
+ busConfigs.shrink_to_fit();
+
//if busses failed to load, add default (fresh install, FS issue, ...)
if (BusManager::getNumBusses() == 0) {
DEBUG_PRINTLN(F("No busses, init default"));
@@ -1326,6 +1368,7 @@ void WS2812FX::finalizeInit() {
unsigned prevLen = 0;
unsigned pinsIndex = 0;
+ digitalCount = 0;
for (unsigned i = 0; i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) {
uint8_t defPin[OUTPUT_MAX_PINS];
// if we have less types than requested outputs and they do not align, use last known type to set current type
@@ -1390,9 +1433,11 @@ void WS2812FX::finalizeInit() {
if (Bus::isPWM(dataType) || Bus::isOnOff(dataType)) count = 1;
prevLen += count;
BusConfig defCfg = BusConfig(dataType, defPin, start, count, DEFAULT_LED_COLOR_ORDER, false, 0, RGBW_MODE_MANUAL_ONLY, 0, useGlobalLedBuffer);
+ mem += defCfg.memUsage(Bus::isDigital(dataType) && !Bus::is2Pin(dataType) ? digitalCount++ : 0);
if (BusManager::add(defCfg) == -1) break;
}
}
+ DEBUG_PRINTF_P(PSTR("LED buffer size: %uB/%uB\n"), mem, BusManager::memUsage());
_length = 0;
for (int i=0; ibegin();
}
+ DEBUG_PRINTF_P(PSTR("Heap after buses: %d\n"), ESP.getFreeHeap());
Segment::maxWidth = _length;
Segment::maxHeight = 1;
diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp
index 3abf61412..6423a436b 100644
--- a/wled00/bus_manager.cpp
+++ b/wled00/bus_manager.cpp
@@ -21,10 +21,12 @@
#endif
#include "const.h"
#include "pin_manager.h"
-#include "bus_wrapper.h"
#include "bus_manager.h"
+#include "bus_wrapper.h"
+#include
extern bool cctICused;
+extern bool useParallelI2S;
//colors.cpp
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
@@ -32,28 +34,6 @@ uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
//udp.cpp
uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, const uint8_t* buffer, uint8_t bri=255, bool isRGBW=false);
-// enable additional debug output
-#if defined(WLED_DEBUG_HOST)
- #include "net_debug.h"
- #define DEBUGOUT NetDebug
-#else
- #define DEBUGOUT Serial
-#endif
-
-#ifdef WLED_DEBUG
- #ifndef ESP8266
- #include
- #endif
- #define DEBUG_PRINT(x) DEBUGOUT.print(x)
- #define DEBUG_PRINTLN(x) DEBUGOUT.println(x)
- #define DEBUG_PRINTF(x...) DEBUGOUT.printf(x)
- #define DEBUG_PRINTF_P(x...) DEBUGOUT.printf_P(x)
-#else
- #define DEBUG_PRINT(x)
- #define DEBUG_PRINTLN(x)
- #define DEBUG_PRINTF(x...)
- #define DEBUG_PRINTF_P(x...)
-#endif
//color mangling macros
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
@@ -66,6 +46,7 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, const
bool ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) {
if (count() >= WLED_MAX_COLOR_ORDER_MAPPINGS || len == 0 || (colorOrder & 0x0F) > COL_ORDER_MAX) return false; // upper nibble contains W swap information
_mappings.push_back({start,len,colorOrder});
+ DEBUGBUS_PRINTF_P(PSTR("Bus: Add COM (%d,%d,%d)\n"), (int)start, (int)len, (int)colorOrder);
return true;
}
@@ -119,10 +100,14 @@ uint32_t Bus::autoWhiteCalc(uint32_t c) const {
}
uint8_t *Bus::allocateData(size_t size) {
- if (_data) free(_data); // should not happen, but for safety
+ freeData(); // should not happen, but for safety
return _data = (uint8_t *)(size>0 ? calloc(size, sizeof(uint8_t)) : nullptr);
}
+void Bus::freeData() {
+ if (_data) free(_data);
+ _data = nullptr;
+}
BusDigital::BusDigital(const BusConfig &bc, uint8_t nr, const ColorOrderMap &com)
: Bus(bc.type, bc.start, bc.autoWhite, bc.count, bc.reversed, (bc.refreshReq || bc.type == TYPE_TM1814))
@@ -132,30 +117,41 @@ BusDigital::BusDigital(const BusConfig &bc, uint8_t nr, const ColorOrderMap &com
, _milliAmpsMax(bc.milliAmpsMax)
, _colorOrderMap(com)
{
- if (!isDigital(bc.type) || !bc.count) return;
- if (!PinManager::allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return;
+ DEBUGBUS_PRINTLN(F("Bus: Creating digital bus."));
+ if (!isDigital(bc.type) || !bc.count) { DEBUGBUS_PRINTLN(F("Not digial or empty bus!")); return; }
+ if (!PinManager::allocatePin(bc.pins[0], true, PinOwner::BusDigital)) { DEBUGBUS_PRINTLN(F("Pin 0 allocated!")); return; }
_frequencykHz = 0U;
_pins[0] = bc.pins[0];
if (is2Pin(bc.type)) {
if (!PinManager::allocatePin(bc.pins[1], true, PinOwner::BusDigital)) {
cleanup();
+ DEBUGBUS_PRINTLN(F("Pin 1 allocated!"));
return;
}
_pins[1] = bc.pins[1];
_frequencykHz = bc.frequency ? bc.frequency : 2000U; // 2MHz clock if undefined
}
_iType = PolyBus::getI(bc.type, _pins, nr);
- if (_iType == I_NONE) return;
+ if (_iType == I_NONE) { DEBUGBUS_PRINTLN(F("Incorrect iType!")); return; }
_hasRgb = hasRGB(bc.type);
_hasWhite = hasWhite(bc.type);
_hasCCT = hasCCT(bc.type);
- if (bc.doubleBuffer && !allocateData(bc.count * Bus::getNumberOfChannels(bc.type))) return;
+ if (bc.doubleBuffer && !allocateData(bc.count * Bus::getNumberOfChannels(bc.type))) { DEBUGBUS_PRINTLN(F("Buffer allocation failed!")); return; }
//_buffering = bc.doubleBuffer;
uint16_t lenToCreate = bc.count;
if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(bc.count); // only needs a third of "RGB" LEDs for NeoPixelBus
_busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr);
_valid = (_busPtr != nullptr);
- DEBUG_PRINTF_P(PSTR("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u). mA=%d/%d\n"), _valid?"S":"Uns", nr, bc.count, bc.type, _pins[0], is2Pin(bc.type)?_pins[1]:255, _iType, _milliAmpsPerLed, _milliAmpsMax);
+ DEBUGBUS_PRINTF_P(PSTR("Bus: %successfully inited #%u (len:%u, type:%u (RGB:%d, W:%d, CCT:%d), pins:%u,%u [itype:%u] mA=%d/%d)\n"),
+ _valid?"S":"Uns",
+ (int)nr,
+ (int)bc.count,
+ (int)bc.type,
+ (int)_hasRgb, (int)_hasWhite, (int)_hasCCT,
+ (unsigned)_pins[0], is2Pin(bc.type)?(unsigned)_pins[1]:255U,
+ (unsigned)_iType,
+ (int)_milliAmpsPerLed, (int)_milliAmpsMax
+ );
}
//DISCLAIMER
@@ -166,7 +162,7 @@ BusDigital::BusDigital(const BusConfig &bc, uint8_t nr, const ColorOrderMap &com
//I am NOT to be held liable for burned down garages or houses!
// To disable brightness limiter we either set output max current to 0 or single LED current to 0
-uint8_t BusDigital::estimateCurrentAndLimitBri() {
+uint8_t BusDigital::estimateCurrentAndLimitBri() const {
bool useWackyWS2815PowerModel = false;
byte actualMilliampsPerLed = _milliAmpsPerLed;
@@ -179,7 +175,7 @@ uint8_t BusDigital::estimateCurrentAndLimitBri() {
actualMilliampsPerLed = 12; // from testing an actual strip
}
- size_t powerBudget = (_milliAmpsMax - MA_FOR_ESP/BusManager::getNumBusses()); //80/120mA for ESP power
+ unsigned powerBudget = (_milliAmpsMax - MA_FOR_ESP/BusManager::getNumBusses()); //80/120mA for ESP power
if (powerBudget > getLength()) { //each LED uses about 1mA in standby, exclude that from power budget
powerBudget -= getLength();
} else {
@@ -204,26 +200,25 @@ uint8_t BusDigital::estimateCurrentAndLimitBri() {
}
// powerSum has all the values of channels summed (max would be getLength()*765 as white is excluded) so convert to milliAmps
- busPowerSum = (busPowerSum * actualMilliampsPerLed) / 765;
- _milliAmpsTotal = busPowerSum * _bri / 255;
+ BusDigital::_milliAmpsTotal = (busPowerSum * actualMilliampsPerLed * _bri) / (765*255);
uint8_t newBri = _bri;
- if (busPowerSum * _bri / 255 > powerBudget) { //scale brightness down to stay in current limit
- float scale = (float)(powerBudget * 255) / (float)(busPowerSum * _bri);
- if (scale >= 1.0f) return _bri;
- _milliAmpsTotal = ceilf((float)_milliAmpsTotal * scale);
- uint8_t scaleB = min((int)(scale * 255), 255);
- newBri = unsigned(_bri * scaleB) / 256 + 1;
+ if (BusDigital::_milliAmpsTotal > powerBudget) {
+ //scale brightness down to stay in current limit
+ unsigned scaleB = powerBudget * 255 / BusDigital::_milliAmpsTotal;
+ newBri = (_bri * scaleB) / 256 + 1;
+ BusDigital::_milliAmpsTotal = powerBudget;
+ //_milliAmpsTotal = (busPowerSum * actualMilliampsPerLed * newBri) / (765*255);
}
return newBri;
}
void BusDigital::show() {
- _milliAmpsTotal = 0;
+ BusDigital::_milliAmpsTotal = 0;
if (!_valid) return;
uint8_t cctWW = 0, cctCW = 0;
- unsigned newBri = estimateCurrentAndLimitBri(); // will fill _milliAmpsTotal
+ unsigned newBri = estimateCurrentAndLimitBri(); // will fill _milliAmpsTotal (TODO: could use PolyBus::CalcTotalMilliAmpere())
if (newBri < _bri) PolyBus::setBrightness(_busPtr, _iType, newBri); // limit brightness to stay within current limits
if (_data) {
@@ -249,6 +244,7 @@ void BusDigital::show() {
// TODO: there is an issue if CCT is calculated from RGB value (_cct==-1), we cannot do that with double buffer
Bus::_cct = _data[offset+channels-1];
Bus::calculateCCT(c, cctWW, cctCW);
+ if (_type == TYPE_WS2812_WWA) c = RGBW32(cctWW, cctCW, 0, W(c)); // may need swapping
}
unsigned pix = i;
if (_reversed) pix = _len - pix -1;
@@ -334,8 +330,8 @@ void IRAM_ATTR BusDigital::setPixelColor(unsigned pix, uint32_t c) {
uint8_t cctWW = 0, cctCW = 0;
Bus::calculateCCT(c, cctWW, cctCW);
wwcw = (cctCW<<8) | cctWW;
+ if (_type == TYPE_WS2812_WWA) c = RGBW32(cctWW, cctCW, 0, W(c)); // may need swapping
}
-
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co, wwcw);
}
}
@@ -367,23 +363,31 @@ uint32_t IRAM_ATTR BusDigital::getPixelColor(unsigned pix) const {
case 2: c = RGBW32(b, b, b, b); break;
}
}
+ if (_type == TYPE_WS2812_WWA) {
+ uint8_t w = R(c) | G(c);
+ c = RGBW32(w, w, 0, w);
+ }
return c;
}
}
-uint8_t BusDigital::getPins(uint8_t* pinArray) const {
+unsigned BusDigital::getPins(uint8_t* pinArray) const {
unsigned numPins = is2Pin(_type) + 1;
if (pinArray) for (unsigned i = 0; i < numPins; i++) pinArray[i] = _pins[i];
return numPins;
}
+unsigned BusDigital::getBusSize() const {
+ return sizeof(BusDigital) + (isOk() ? PolyBus::getDataSize(_busPtr, _iType) + (_data ? _len * getNumberOfChannels() : 0) : 0);
+}
+
void BusDigital::setColorOrder(uint8_t colorOrder) {
// upper nibble contains W swap information
if ((colorOrder & 0x0F) > 5) return;
_colorOrder = colorOrder;
}
-// credit @willmmiles & @netmindz https://github.com/Aircoookie/WLED/pull/4056
+// credit @willmmiles & @netmindz https://github.com/wled-dev/WLED/pull/4056
std::vector BusDigital::getLEDTypes() {
return {
{TYPE_WS2812_RGB, "D", PSTR("WS281x")},
@@ -399,8 +403,8 @@ std::vector BusDigital::getLEDTypes() {
{TYPE_WS2805, "D", PSTR("WS2805 RGBCW")},
{TYPE_SM16825, "D", PSTR("SM16825 RGBCW")},
{TYPE_WS2812_1CH_X3, "D", PSTR("WS2811 White")},
- //{TYPE_WS2812_2CH_X3, "D", PSTR("WS2811 CCT")}, // not implemented
- //{TYPE_WS2812_WWA, "D", PSTR("WS2811 WWA")}, // not implemented
+ //{TYPE_WS2812_2CH_X3, "D", PSTR("WS281x CCT")}, // not implemented
+ {TYPE_WS2812_WWA, "D", PSTR("WS281x WWA")}, // amber ignored
{TYPE_WS2801, "2P", PSTR("WS2801")},
{TYPE_APA102, "2P", PSTR("APA102")},
{TYPE_LPD8806, "2P", PSTR("LPD8806")},
@@ -415,12 +419,13 @@ void BusDigital::begin() {
}
void BusDigital::cleanup() {
- DEBUG_PRINTLN(F("Digital Cleanup."));
+ DEBUGBUS_PRINTLN(F("Digital Cleanup."));
PolyBus::cleanup(_busPtr, _iType);
_iType = I_NONE;
_valid = false;
_busPtr = nullptr;
- if (_data != nullptr) freeData();
+ freeData();
+ //PinManager::deallocateMultiplePins(_pins, 2, PinOwner::BusDigital);
PinManager::deallocatePin(_pins[1], PinOwner::BusDigital);
PinManager::deallocatePin(_pins[0], PinOwner::BusDigital);
}
@@ -492,9 +497,9 @@ BusPwm::BusPwm(const BusConfig &bc)
_hasRgb = hasRGB(bc.type);
_hasWhite = hasWhite(bc.type);
_hasCCT = hasCCT(bc.type);
- _data = _pwmdata; // avoid malloc() and use stack
+ _data = _pwmdata; // avoid malloc() and use already allocated memory
_valid = true;
- DEBUG_PRINTF_P(PSTR("%successfully inited PWM strip with type %u, frequency %u, bit depth %u and pins %u,%u,%u,%u,%u\n"), _valid?"S":"Uns", bc.type, _frequency, _depth, _pins[0], _pins[1], _pins[2], _pins[3], _pins[4]);
+ DEBUGBUS_PRINTF_P(PSTR("%successfully inited PWM strip with type %u, frequency %u, bit depth %u and pins %u,%u,%u,%u,%u\n"), _valid?"S":"Uns", bc.type, _frequency, _depth, _pins[0], _pins[1], _pins[2], _pins[3], _pins[4]);
}
void BusPwm::setPixelColor(unsigned pix, uint32_t c) {
@@ -564,7 +569,7 @@ void BusPwm::show() {
constexpr unsigned bitShift = 8; // 256 clocks for dead time, ~3us at 80MHz
#else
// if _needsRefresh is true (UI hack) we are using dithering (credit @dedehai & @zalatnaicsongor)
- // https://github.com/Aircoookie/WLED/pull/4115 and https://github.com/zalatnaicsongor/WLED/pull/1)
+ // https://github.com/wled-dev/WLED/pull/4115 and https://github.com/zalatnaicsongor/WLED/pull/1)
const bool dithering = _needsRefresh; // avoid working with bitfield
const unsigned maxBri = (1<<_depth); // possible values: 16384 (14), 8192 (13), 4096 (12), 2048 (11), 1024 (10), 512 (9) and 256 (8)
const unsigned bitShift = dithering * 4; // if dithering, _depth is 12 bit but LEDC channel is set to 8 bit (using 4 fractional bits)
@@ -623,14 +628,14 @@ void BusPwm::show() {
}
}
-uint8_t BusPwm::getPins(uint8_t* pinArray) const {
+unsigned BusPwm::getPins(uint8_t* pinArray) const {
if (!_valid) return 0;
unsigned numPins = numPWMPins(_type);
if (pinArray) for (unsigned i = 0; i < numPins; i++) pinArray[i] = _pins[i];
return numPins;
}
-// credit @willmmiles & @netmindz https://github.com/Aircoookie/WLED/pull/4056
+// credit @willmmiles & @netmindz https://github.com/wled-dev/WLED/pull/4056
std::vector BusPwm::getLEDTypes() {
return {
{TYPE_ANALOG_1CH, "A", PSTR("PWM White")},
@@ -676,7 +681,7 @@ BusOnOff::BusOnOff(const BusConfig &bc)
_hasCCT = false;
_data = &_onoffdata; // avoid malloc() and use stack
_valid = true;
- DEBUG_PRINTF_P(PSTR("%successfully inited On/Off strip with pin %u\n"), _valid?"S":"Uns", _pin);
+ DEBUGBUS_PRINTF_P(PSTR("%successfully inited On/Off strip with pin %u\n"), _valid?"S":"Uns", _pin);
}
void BusOnOff::setPixelColor(unsigned pix, uint32_t c) {
@@ -699,13 +704,13 @@ void BusOnOff::show() {
digitalWrite(_pin, _reversed ? !(bool)_data[0] : (bool)_data[0]);
}
-uint8_t BusOnOff::getPins(uint8_t* pinArray) const {
+unsigned BusOnOff::getPins(uint8_t* pinArray) const {
if (!_valid) return 0;
if (pinArray) pinArray[0] = _pin;
return 1;
}
-// credit @willmmiles & @netmindz https://github.com/Aircoookie/WLED/pull/4056
+// credit @willmmiles & @netmindz https://github.com/wled-dev/WLED/pull/4056
std::vector BusOnOff::getLEDTypes() {
return {
{TYPE_ONOFF, "", PSTR("On/Off")},
@@ -736,7 +741,7 @@ BusNetwork::BusNetwork(const BusConfig &bc)
_UDPchannels = _hasWhite + 3;
_client = IPAddress(bc.pins[0],bc.pins[1],bc.pins[2],bc.pins[3]);
_valid = (allocateData(_len * _UDPchannels) != nullptr);
- DEBUG_PRINTF_P(PSTR("%successfully inited virtual strip with type %u and IP %u.%u.%u.%u\n"), _valid?"S":"Uns", bc.type, bc.pins[0], bc.pins[1], bc.pins[2], bc.pins[3]);
+ DEBUGBUS_PRINTF_P(PSTR("%successfully inited virtual strip with type %u and IP %u.%u.%u.%u\n"), _valid?"S":"Uns", bc.type, bc.pins[0], bc.pins[1], bc.pins[2], bc.pins[3]);
}
void BusNetwork::setPixelColor(unsigned pix, uint32_t c) {
@@ -763,12 +768,12 @@ void BusNetwork::show() {
_broadcastLock = false;
}
-uint8_t BusNetwork::getPins(uint8_t* pinArray) const {
+unsigned BusNetwork::getPins(uint8_t* pinArray) const {
if (pinArray) for (unsigned i = 0; i < 4; i++) pinArray[i] = _client[i];
return 4;
}
-// credit @willmmiles & @netmindz https://github.com/Aircoookie/WLED/pull/4056
+// credit @willmmiles & @netmindz https://github.com/wled-dev/WLED/pull/4056
std::vector BusNetwork::getLEDTypes() {
return {
{TYPE_NET_DDP_RGB, "N", PSTR("DDP RGB (network)")}, // should be "NNNN" to determine 4 "pin" fields
@@ -779,11 +784,12 @@ std::vector BusNetwork::getLEDTypes() {
//{TYPE_VIRTUAL_I2C_W, "V", PSTR("I2C White (virtual)")}, // allows setting I2C address in _pin[0]
//{TYPE_VIRTUAL_I2C_CCT, "V", PSTR("I2C CCT (virtual)")}, // allows setting I2C address in _pin[0]
//{TYPE_VIRTUAL_I2C_RGB, "VVV", PSTR("I2C RGB (virtual)")}, // allows setting I2C address in _pin[0] and 2 additional values in _pin[1] & _pin[2]
- //{TYPE_USERMOD, "VVVVV", PSTR("Usermod (virtual)")}, // 5 data fields (see https://github.com/Aircoookie/WLED/pull/4123)
+ //{TYPE_USERMOD, "VVVVV", PSTR("Usermod (virtual)")}, // 5 data fields (see https://github.com/wled-dev/WLED/pull/4123)
};
}
void BusNetwork::cleanup() {
+ DEBUGBUS_PRINTLN(F("Virtual Cleanup."));
_type = I_NONE;
_valid = false;
freeData();
@@ -791,43 +797,66 @@ void BusNetwork::cleanup() {
//utility to get the approx. memory usage of a given BusConfig
-uint32_t BusManager::memUsage(const BusConfig &bc) {
- if (Bus::isOnOff(bc.type) || Bus::isPWM(bc.type)) return OUTPUT_MAX_PINS;
-
- unsigned len = bc.count + bc.skipAmount;
- unsigned channels = Bus::getNumberOfChannels(bc.type);
- unsigned multiplier = 1;
- if (Bus::isDigital(bc.type)) { // digital types
- if (Bus::is16bit(bc.type)) len *= 2; // 16-bit LEDs
- #ifdef ESP8266
- if (bc.pins[0] == 3) { //8266 DMA uses 5x the mem
- multiplier = 5;
- }
- #else //ESP32 RMT uses double buffer, parallel I2S uses 8x buffer (3 times)
- multiplier = PolyBus::isParallelI2S1Output() ? 24 : 2;
- #endif
+unsigned BusConfig::memUsage(unsigned nr) const {
+ if (Bus::isVirtual(type)) {
+ return sizeof(BusNetwork) + (count * Bus::getNumberOfChannels(type));
+ } else if (Bus::isDigital(type)) {
+ return sizeof(BusDigital) + PolyBus::memUsage(count + skipAmount, PolyBus::getI(type, pins, nr)) + doubleBuffer * (count + skipAmount) * Bus::getNumberOfChannels(type);
+ } else if (Bus::isOnOff(type)) {
+ return sizeof(BusOnOff);
+ } else {
+ return sizeof(BusPwm);
}
- return (len * multiplier + bc.doubleBuffer * (bc.count + bc.skipAmount)) * channels;
}
-uint32_t BusManager::memUsage(unsigned maxChannels, unsigned maxCount, unsigned minBuses) {
- //ESP32 RMT uses double buffer, parallel I2S uses 8x buffer (3 times)
- unsigned multiplier = PolyBus::isParallelI2S1Output() ? 3 : 2;
- return (maxChannels * maxCount * minBuses * multiplier);
+
+unsigned BusManager::memUsage() {
+ // when ESP32, S2 & S3 use parallel I2S only the largest bus determines the total memory requirements for back buffers
+ // front buffers are always allocated per bus
+ unsigned size = 0;
+ unsigned maxI2S = 0;
+ #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(ESP8266)
+ unsigned digitalCount = 0;
+ #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
+ #define MAX_RMT 4
+ #else
+ #define MAX_RMT 8
+ #endif
+ #endif
+ for (const auto &bus : busses) {
+ unsigned busSize = bus->getBusSize();
+ #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(ESP8266)
+ if (bus->isDigital() && !bus->is2Pin()) digitalCount++;
+ if (PolyBus::isParallelI2S1Output() && digitalCount > MAX_RMT) {
+ unsigned i2sCommonSize = 3 * bus->getLength() * bus->getNumberOfChannels() * (bus->is16bit()+1);
+ if (i2sCommonSize > maxI2S) maxI2S = i2sCommonSize;
+ busSize -= i2sCommonSize;
+ }
+ #endif
+ size += busSize;
+ }
+ return size + maxI2S;
}
int BusManager::add(const BusConfig &bc) {
+ DEBUGBUS_PRINTF_P(PSTR("Bus: Adding bus (%d - %d >= %d)\n"), getNumBusses(), getNumVirtualBusses(), WLED_MAX_BUSSES);
if (getNumBusses() - getNumVirtualBusses() >= WLED_MAX_BUSSES) return -1;
+ unsigned numDigital = 0;
+ for (const auto &bus : busses) if (bus->isDigital() && !bus->is2Pin()) numDigital++;
if (Bus::isVirtual(bc.type)) {
- busses[numBusses] = new BusNetwork(bc);
+ //busses.push_back(std::make_unique(bc)); // when C++ >11
+ busses.push_back(new BusNetwork(bc));
} else if (Bus::isDigital(bc.type)) {
- busses[numBusses] = new BusDigital(bc, numBusses, colorOrderMap);
+ //busses.push_back(std::make_unique(bc, numDigital, colorOrderMap));
+ busses.push_back(new BusDigital(bc, numDigital, colorOrderMap));
} else if (Bus::isOnOff(bc.type)) {
- busses[numBusses] = new BusOnOff(bc);
+ //busses.push_back(std::make_unique(bc));
+ busses.push_back(new BusOnOff(bc));
} else {
- busses[numBusses] = new BusPwm(bc);
+ //busses.push_back(std::make_unique(bc));
+ busses.push_back(new BusPwm(bc));
}
- return numBusses++;
+ return busses.size();
}
// credit @willmmiles
@@ -843,7 +872,7 @@ static String LEDTypesToJson(const std::vector& types) {
return json;
}
-// credit @willmmiles & @netmindz https://github.com/Aircoookie/WLED/pull/4056
+// credit @willmmiles & @netmindz https://github.com/wled-dev/WLED/pull/4056
String BusManager::getLEDTypesJSONString() {
String json = "[";
json += LEDTypesToJson(BusDigital::getLEDTypes());
@@ -856,18 +885,21 @@ String BusManager::getLEDTypesJSONString() {
}
void BusManager::useParallelOutput() {
- _parallelOutputs = 8; // hardcoded since we use NPB I2S x8 methods
+ DEBUGBUS_PRINTLN(F("Bus: Enabling parallel I2S."));
PolyBus::setParallelI2S1Output();
}
+bool BusManager::hasParallelOutput() {
+ return PolyBus::isParallelI2S1Output();
+}
+
//do not call this method from system context (network callback)
void BusManager::removeAll() {
- DEBUG_PRINTLN(F("Removing all."));
+ DEBUGBUS_PRINTLN(F("Removing all."));
//prevents crashes due to deleting busses while in use.
while (!canAllShow()) yield();
- for (unsigned i = 0; i < numBusses; i++) delete busses[i];
- numBusses = 0;
- _parallelOutputs = 1;
+ for (auto &bus : busses) delete bus; // needed when not using std::unique_ptr C++ >11
+ busses.clear();
PolyBus::setParallelI2S1Output(false);
}
@@ -878,7 +910,9 @@ void BusManager::removeAll() {
void BusManager::esp32RMTInvertIdle() {
bool idle_out;
unsigned rmt = 0;
- for (unsigned u = 0; u < numBusses(); u++) {
+ unsigned u = 0;
+ for (auto &bus : busses) {
+ if (bus->getLength()==0 || !bus->isDigital() || bus->is2Pin()) continue;
#if defined(CONFIG_IDF_TARGET_ESP32C3) // 2 RMT, only has 1 I2S but NPB does not support it ATM
if (u > 1) return;
rmt = u;
@@ -889,11 +923,11 @@ void BusManager::esp32RMTInvertIdle() {
if (u > 3) return;
rmt = u;
#else
- if (u < _parallelOutputs) continue;
- if (u >= _parallelOutputs + 8) return; // only 8 RMT channels
- rmt = u - _parallelOutputs;
+ unsigned numI2S = !PolyBus::isParallelI2S1Output(); // if using parallel I2S, RMT is used 1st
+ if (numI2S > u) continue;
+ if (u > 7 + numI2S) return;
+ rmt = u - numI2S;
#endif
- if (busses[u]->getLength()==0 || !busses[u]->isDigital() || busses[u]->is2Pin()) continue;
//assumes that bus number to rmt channel mapping stays 1:1
rmt_channel_t ch = static_cast(rmt);
rmt_idle_level_t lvl;
@@ -902,6 +936,7 @@ void BusManager::esp32RMTInvertIdle() {
else if (lvl == RMT_IDLE_LEVEL_LOW) lvl = RMT_IDLE_LEVEL_HIGH;
else continue;
rmt_set_idle_level(ch, idle_out, lvl);
+ u++
}
}
#endif
@@ -910,12 +945,12 @@ void BusManager::on() {
#ifdef ESP8266
//Fix for turning off onboard LED breaking bus
if (PinManager::getPinOwner(LED_BUILTIN) == PinOwner::BusDigital) {
- for (unsigned i = 0; i < numBusses; i++) {
+ for (auto &bus : busses) {
uint8_t pins[2] = {255,255};
- if (busses[i]->isDigital() && busses[i]->getPins(pins)) {
+ if (bus->isDigital() && bus->getPins(pins)) {
if (pins[0] == LED_BUILTIN || pins[1] == LED_BUILTIN) {
- BusDigital *bus = static_cast(busses[i]);
- bus->begin();
+ BusDigital *b = static_cast(bus);
+ b->begin();
break;
}
}
@@ -932,7 +967,7 @@ void BusManager::off() {
// turn off built-in LED if strip is turned off
// this will break digital bus so will need to be re-initialised on On
if (PinManager::getPinOwner(LED_BUILTIN) == PinOwner::BusDigital) {
- for (unsigned i = 0; i < numBusses; i++) if (busses[i]->isOffRefreshRequired()) return;
+ for (const auto &bus : busses) if (bus->isOffRefreshRequired()) return;
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
}
@@ -944,30 +979,26 @@ void BusManager::off() {
void BusManager::show() {
_milliAmpsUsed = 0;
- for (unsigned i = 0; i < numBusses; i++) {
- busses[i]->show();
- _milliAmpsUsed += busses[i]->getUsedCurrent();
+ for (auto &bus : busses) {
+ bus->show();
+ _milliAmpsUsed += bus->getUsedCurrent();
}
}
void BusManager::setStatusPixel(uint32_t c) {
- for (unsigned i = 0; i < numBusses; i++) {
- busses[i]->setStatusPixel(c);
- }
+ for (auto &bus : busses) bus->setStatusPixel(c);
}
void IRAM_ATTR BusManager::setPixelColor(unsigned pix, uint32_t c) {
- for (unsigned i = 0; i < numBusses; i++) {
- unsigned bstart = busses[i]->getStart();
- if (pix < bstart || pix >= bstart + busses[i]->getLength()) continue;
- busses[i]->setPixelColor(pix - bstart, c);
+ for (auto &bus : busses) {
+ unsigned bstart = bus->getStart();
+ if (pix < bstart || pix >= bstart + bus->getLength()) continue;
+ bus->setPixelColor(pix - bstart, c);
}
}
void BusManager::setBrightness(uint8_t b) {
- for (unsigned i = 0; i < numBusses; i++) {
- busses[i]->setBrightness(b);
- }
+ for (auto &bus : busses) bus->setBrightness(b);
}
void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) {
@@ -980,34 +1011,32 @@ void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) {
}
uint32_t BusManager::getPixelColor(unsigned pix) {
- for (unsigned i = 0; i < numBusses; i++) {
- unsigned bstart = busses[i]->getStart();
- if (!busses[i]->containsPixel(pix)) continue;
- return busses[i]->getPixelColor(pix - bstart);
+ for (auto &bus : busses) {
+ unsigned bstart = bus->getStart();
+ if (!bus->containsPixel(pix)) continue;
+ return bus->getPixelColor(pix - bstart);
}
return 0;
}
bool BusManager::canAllShow() {
- for (unsigned i = 0; i < numBusses; i++) {
- if (!busses[i]->canShow()) return false;
- }
+ for (const auto &bus : busses) if (!bus->canShow()) return false;
return true;
}
Bus* BusManager::getBus(uint8_t busNr) {
- if (busNr >= numBusses) return nullptr;
+ if (busNr >= busses.size()) return nullptr;
return busses[busNr];
}
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
uint16_t BusManager::getTotalLength() {
unsigned len = 0;
- for (unsigned i=0; igetLength();
+ for (const auto &bus : busses) len += bus->getLength();
return len;
}
-bool PolyBus::useParallelI2S = false;
+bool PolyBus::_useParallelI2S = false;
// Bus static member definition
int16_t Bus::_cct = -1;
@@ -1016,9 +1045,8 @@ uint8_t Bus::_gAWM = 255;
uint16_t BusDigital::_milliAmpsTotal = 0;
-uint8_t BusManager::numBusses = 0;
-Bus* BusManager::busses[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES];
+//std::vector> BusManager::busses;
+std::vector BusManager::busses;
ColorOrderMap BusManager::colorOrderMap = {};
uint16_t BusManager::_milliAmpsUsed = 0;
uint16_t BusManager::_milliAmpsMax = ABL_MILLIAMPS_DEFAULT;
-uint8_t BusManager::_parallelOutputs = 1;
diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h
index 9aed01308..59e574cb0 100644
--- a/wled00/bus_manager.h
+++ b/wled00/bus_manager.h
@@ -1,3 +1,4 @@
+#pragma once
#ifndef BusManager_h
#define BusManager_h
@@ -8,6 +9,30 @@
#include "const.h"
#include "pin_manager.h"
#include
+#include
+
+// enable additional debug output
+#if defined(WLED_DEBUG_HOST)
+ #include "net_debug.h"
+ #define DEBUGOUT NetDebug
+#else
+ #define DEBUGOUT Serial
+#endif
+
+#ifdef WLED_DEBUG_BUS
+ #ifndef ESP8266
+ #include
+ #endif
+ #define DEBUGBUS_PRINT(x) DEBUGOUT.print(x)
+ #define DEBUGBUS_PRINTLN(x) DEBUGOUT.println(x)
+ #define DEBUGBUS_PRINTF(x...) DEBUGOUT.printf(x)
+ #define DEBUGBUS_PRINTF_P(x...) DEBUGOUT.printf_P(x)
+#else
+ #define DEBUGBUS_PRINT(x)
+ #define DEBUGBUS_PRINTLN(x)
+ #define DEBUGBUS_PRINTF(x...)
+ #define DEBUGBUS_PRINTF_P(x...)
+#endif
//colors.cpp
uint16_t approximateKelvinFromRGB(uint32_t rgb);
@@ -78,50 +103,51 @@ class Bus {
_autoWhiteMode = Bus::hasWhite(type) ? aw : RGBW_MODE_MANUAL_ONLY;
};
- virtual ~Bus() {} //throw the bus under the bus
+ virtual ~Bus() {} //throw the bus under the bus (derived class needs to freeData())
- virtual void begin() {};
+ virtual void begin() {};
virtual void show() = 0;
- virtual bool canShow() const { return true; }
- virtual void setStatusPixel(uint32_t c) {}
+ virtual bool canShow() const { return true; }
+ virtual void setStatusPixel(uint32_t c) {}
virtual void setPixelColor(unsigned pix, uint32_t c) = 0;
- virtual void setBrightness(uint8_t b) { _bri = b; };
- virtual void setColorOrder(uint8_t co) {}
- virtual uint32_t getPixelColor(unsigned pix) const { return 0; }
- virtual uint8_t getPins(uint8_t* pinArray = nullptr) const { return 0; }
- virtual uint16_t getLength() const { return isOk() ? _len : 0; }
- virtual uint8_t getColorOrder() const { return COL_ORDER_RGB; }
- virtual uint8_t skippedLeds() const { return 0; }
- virtual uint16_t getFrequency() const { return 0U; }
- virtual uint16_t getLEDCurrent() const { return 0; }
- virtual uint16_t getUsedCurrent() const { return 0; }
- virtual uint16_t getMaxCurrent() const { return 0; }
+ virtual void setBrightness(uint8_t b) { _bri = b; };
+ virtual void setColorOrder(uint8_t co) {}
+ virtual uint32_t getPixelColor(unsigned pix) const { return 0; }
+ virtual unsigned getPins(uint8_t* pinArray = nullptr) const { return 0; }
+ virtual uint16_t getLength() const { return isOk() ? _len : 0; }
+ virtual uint8_t getColorOrder() const { return COL_ORDER_RGB; }
+ virtual unsigned skippedLeds() const { return 0; }
+ virtual uint16_t getFrequency() const { return 0U; }
+ virtual uint16_t getLEDCurrent() const { return 0; }
+ virtual uint16_t getUsedCurrent() const { return 0; }
+ virtual uint16_t getMaxCurrent() const { return 0; }
+ virtual unsigned getBusSize() const { return sizeof(Bus); }
- inline bool hasRGB() const { return _hasRgb; }
- inline bool hasWhite() const { return _hasWhite; }
- inline bool hasCCT() const { return _hasCCT; }
- inline bool isDigital() const { return isDigital(_type); }
- inline bool is2Pin() const { return is2Pin(_type); }
- inline bool isOnOff() const { return isOnOff(_type); }
- inline bool isPWM() const { return isPWM(_type); }
- inline bool isVirtual() const { return isVirtual(_type); }
- inline bool is16bit() const { return is16bit(_type); }
- inline bool mustRefresh() const { return mustRefresh(_type); }
- inline void setReversed(bool reversed) { _reversed = reversed; }
- inline void setStart(uint16_t start) { _start = start; }
- inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; }
- inline uint8_t getAutoWhiteMode() const { return _autoWhiteMode; }
- inline uint32_t getNumberOfChannels() const { return hasWhite() + 3*hasRGB() + hasCCT(); }
- inline uint16_t getStart() const { return _start; }
- inline uint8_t getType() const { return _type; }
- inline bool isOk() const { return _valid; }
- inline bool isReversed() const { return _reversed; }
- inline bool isOffRefreshRequired() const { return _needsRefresh; }
- inline bool containsPixel(uint16_t pix) const { return pix >= _start && pix < _start + _len; }
+ inline bool hasRGB() const { return _hasRgb; }
+ inline bool hasWhite() const { return _hasWhite; }
+ inline bool hasCCT() const { return _hasCCT; }
+ inline bool isDigital() const { return isDigital(_type); }
+ inline bool is2Pin() const { return is2Pin(_type); }
+ inline bool isOnOff() const { return isOnOff(_type); }
+ inline bool isPWM() const { return isPWM(_type); }
+ inline bool isVirtual() const { return isVirtual(_type); }
+ inline bool is16bit() const { return is16bit(_type); }
+ inline bool mustRefresh() const { return mustRefresh(_type); }
+ inline void setReversed(bool reversed) { _reversed = reversed; }
+ inline void setStart(uint16_t start) { _start = start; }
+ inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; }
+ inline uint8_t getAutoWhiteMode() const { return _autoWhiteMode; }
+ inline unsigned getNumberOfChannels() const { return hasWhite() + 3*hasRGB() + hasCCT(); }
+ inline uint16_t getStart() const { return _start; }
+ inline uint8_t getType() const { return _type; }
+ inline bool isOk() const { return _valid; }
+ inline bool isReversed() const { return _reversed; }
+ inline bool isOffRefreshRequired() const { return _needsRefresh; }
+ inline bool containsPixel(uint16_t pix) const { return pix >= _start && pix < _start + _len; }
- static inline std::vector getLEDTypes() { return {{TYPE_NONE, "", PSTR("None")}}; } // not used. just for reference for derived classes
- static constexpr uint32_t getNumberOfPins(uint8_t type) { return isVirtual(type) ? 4 : isPWM(type) ? numPWMPins(type) : is2Pin(type) + 1; } // credit @PaoloTK
- static constexpr uint32_t getNumberOfChannels(uint8_t type) { return hasWhite(type) + 3*hasRGB(type) + hasCCT(type); }
+ static inline std::vector getLEDTypes() { return {{TYPE_NONE, "", PSTR("None")}}; } // not used. just for reference for derived classes
+ static constexpr unsigned getNumberOfPins(uint8_t type) { return isVirtual(type) ? 4 : isPWM(type) ? numPWMPins(type) : is2Pin(type) + 1; } // credit @PaoloTK
+ static constexpr unsigned getNumberOfChannels(uint8_t type) { return hasWhite(type) + 3*hasRGB(type) + hasCCT(type); }
static constexpr bool hasRGB(uint8_t type) {
return !((type >= TYPE_WS2812_1CH && type <= TYPE_WS2812_WWA) || type == TYPE_ANALOG_1CH || type == TYPE_ANALOG_2CH || type == TYPE_ONOFF);
}
@@ -153,7 +179,7 @@ class Bus {
static inline uint8_t getGlobalAWMode() { return _gAWM; }
static inline void setCCT(int16_t cct) { _cct = cct; }
static inline uint8_t getCCTBlend() { return _cctBlend; }
- static inline void setCCTBlend(uint8_t b) {
+ static inline void setCCTBlend(uint8_t b) {
_cctBlend = (std::min((int)b,100) * 127) / 100;
//compile-time limiter for hardware that can't power both white channels at max
#ifdef WLED_MAX_CCT_BLEND
@@ -192,7 +218,7 @@ class Bus {
uint32_t autoWhiteCalc(uint32_t c) const;
uint8_t *allocateData(size_t size = 1);
- void freeData() { if (_data != nullptr) free(_data); _data = nullptr; }
+ void freeData();
};
@@ -209,12 +235,13 @@ class BusDigital : public Bus {
void setColorOrder(uint8_t colorOrder) override;
[[gnu::hot]] uint32_t getPixelColor(unsigned pix) const override;
uint8_t getColorOrder() const override { return _colorOrder; }
- uint8_t getPins(uint8_t* pinArray = nullptr) const override;
- uint8_t skippedLeds() const override { return _skip; }
+ unsigned getPins(uint8_t* pinArray = nullptr) const override;
+ unsigned skippedLeds() const override { return _skip; }
uint16_t getFrequency() const override { return _frequencykHz; }
uint16_t getLEDCurrent() const override { return _milliAmpsPerLed; }
uint16_t getUsedCurrent() const override { return _milliAmpsTotal; }
uint16_t getMaxCurrent() const override { return _milliAmpsMax; }
+ unsigned getBusSize() const override;
void begin() override;
void cleanup();
@@ -244,7 +271,7 @@ class BusDigital : public Bus {
return c;
}
- uint8_t estimateCurrentAndLimitBri();
+ uint8_t estimateCurrentAndLimitBri() const;
};
@@ -255,10 +282,11 @@ class BusPwm : public Bus {
void setPixelColor(unsigned pix, uint32_t c) override;
uint32_t getPixelColor(unsigned pix) const override; //does no index check
- uint8_t getPins(uint8_t* pinArray = nullptr) const override;
+ unsigned getPins(uint8_t* pinArray = nullptr) const override;
uint16_t getFrequency() const override { return _frequency; }
+ unsigned getBusSize() const override { return sizeof(BusPwm); }
void show() override;
- void cleanup() { deallocatePins(); }
+ inline void cleanup() { deallocatePins(); _data = nullptr; }
static std::vector getLEDTypes();
@@ -282,9 +310,10 @@ class BusOnOff : public Bus {
void setPixelColor(unsigned pix, uint32_t c) override;
uint32_t getPixelColor(unsigned pix) const override;
- uint8_t getPins(uint8_t* pinArray) const override;
+ unsigned getPins(uint8_t* pinArray) const override;
+ unsigned getBusSize() const override { return sizeof(BusOnOff); }
void show() override;
- void cleanup() { PinManager::deallocatePin(_pin, PinOwner::BusOnOff); }
+ inline void cleanup() { PinManager::deallocatePin(_pin, PinOwner::BusOnOff); _data = nullptr; }
static std::vector getLEDTypes();
@@ -300,9 +329,10 @@ class BusNetwork : public Bus {
~BusNetwork() { cleanup(); }
bool canShow() const override { return !_broadcastLock; } // this should be a return value from UDP routine if it is still sending data out
- void setPixelColor(unsigned pix, uint32_t c) override;
- uint32_t getPixelColor(unsigned pix) const override;
- uint8_t getPins(uint8_t* pinArray = nullptr) const override;
+ [[gnu::hot]] void setPixelColor(unsigned pix, uint32_t c) override;
+ [[gnu::hot]] uint32_t getPixelColor(unsigned pix) const override;
+ unsigned getPins(uint8_t* pinArray = nullptr) const override;
+ unsigned getBusSize() const override { return sizeof(BusNetwork) + (isOk() ? _len * _UDPchannels : 0); }
void show() override;
void cleanup();
@@ -348,6 +378,16 @@ struct BusConfig {
type = busType & 0x7F; // bit 7 may be/is hacked to include refresh info (1=refresh in off state, 0=no refresh)
size_t nPins = Bus::getNumberOfPins(type);
for (size_t i = 0; i < nPins; i++) pins[i] = ppins[i];
+ DEBUGBUS_PRINTF_P(PSTR("Bus: Config (%d-%d, type:%d, CO:%d, rev:%d, skip:%d, AW:%d kHz:%d, mA:%d/%d)\n"),
+ (int)start, (int)(start+len),
+ (int)type,
+ (int)colorOrder,
+ (int)reversed,
+ (int)skipAmount,
+ (int)autoWhite,
+ (int)frequency,
+ (int)milliAmpsPerLed, (int)milliAmpsMax
+ );
}
//validates start and length and extends total if needed
@@ -361,6 +401,8 @@ struct BusConfig {
if (start + count > total) total = start + count;
return true;
}
+
+ unsigned memUsage(unsigned nr = 0) const;
};
@@ -378,14 +420,13 @@ class BusManager {
public:
BusManager() {};
- //utility to get the approx. memory usage of a given BusConfig
- static uint32_t memUsage(const BusConfig &bc);
- static uint32_t memUsage(unsigned channels, unsigned count, unsigned buses = 1);
+ static unsigned memUsage();
static uint16_t currentMilliamps() { return _milliAmpsUsed + MA_FOR_ESP; }
static uint16_t ablMilliampsMax() { return _milliAmpsMax; }
static int add(const BusConfig &bc);
static void useParallelOutput(); // workaround for inaccessible PolyBus
+ static bool hasParallelOutput(); // workaround for inaccessible PolyBus
//do not call this method from system context (network callback)
static void removeAll();
@@ -409,25 +450,24 @@ class BusManager {
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
static uint16_t getTotalLength();
- static inline uint8_t getNumBusses() { return numBusses; }
+ static inline uint8_t getNumBusses() { return busses.size(); }
static String getLEDTypesJSONString();
static inline ColorOrderMap& getColorOrderMap() { return colorOrderMap; }
private:
- static uint8_t numBusses;
- static Bus* busses[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES];
+ //static std::vector> busses; // we'd need C++ >11
+ static std::vector busses;
static ColorOrderMap colorOrderMap;
static uint16_t _milliAmpsUsed;
static uint16_t _milliAmpsMax;
- static uint8_t _parallelOutputs;
#ifdef ESP32_DATA_IDLE_HIGH
static void esp32RMTInvertIdle() ;
#endif
static uint8_t getNumVirtualBusses() {
int j = 0;
- for (int i=0; iisVirtual()) j++;
+ for (const auto &bus : busses) j += bus->isVirtual();
return j;
}
};
diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h
index d2a18c9d8..577aaeb82 100644
--- a/wled00/bus_wrapper.h
+++ b/wled00/bus_wrapper.h
@@ -1,23 +1,9 @@
+#pragma once
#ifndef BusWrapper_h
#define BusWrapper_h
+//#define NPB_CONF_4STEP_CADENCE
#include "NeoPixelBusLg.h"
-#include "bus_manager.h"
-
-// temporary - these defines should actually be set in platformio.ini
-// C3: I2S0 and I2S1 methods not supported (has one I2S bus)
-// S2: I2S1 methods not supported (has one I2S bus)
-// S3: I2S0 and I2S1 methods not supported yet (has two I2S buses)
-// https://github.com/Makuna/NeoPixelBus/blob/b32f719e95ef3c35c46da5c99538017ef925c026/src/internal/Esp32_i2s.h#L4
-// https://github.com/Makuna/NeoPixelBus/blob/b32f719e95ef3c35c46da5c99538017ef925c026/src/internal/NeoEsp32RmtMethod.h#L857
-
-#if !defined(WLED_NO_I2S0_PIXELBUS) && (defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3))
-#define WLED_NO_I2S0_PIXELBUS
-#endif
-#if !defined(WLED_NO_I2S1_PIXELBUS) && (defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2))
-#define WLED_NO_I2S1_PIXELBUS
-#endif
-// temporary end
//Hardware SPI Pins
#define P_8266_HS_MOSI 13
@@ -55,110 +41,98 @@
#define I_8266_DM_TM2_3 19
#define I_8266_BB_TM2_3 20
//UCS8903 (RGB)
-#define I_8266_U0_UCS_3 49
-#define I_8266_U1_UCS_3 50
-#define I_8266_DM_UCS_3 51
-#define I_8266_BB_UCS_3 52
+#define I_8266_U0_UCS_3 21
+#define I_8266_U1_UCS_3 22
+#define I_8266_DM_UCS_3 23
+#define I_8266_BB_UCS_3 24
//UCS8904 (RGBW)
-#define I_8266_U0_UCS_4 53
-#define I_8266_U1_UCS_4 54
-#define I_8266_DM_UCS_4 55
-#define I_8266_BB_UCS_4 56
+#define I_8266_U0_UCS_4 25
+#define I_8266_U1_UCS_4 26
+#define I_8266_DM_UCS_4 27
+#define I_8266_BB_UCS_4 28
//FW1906 GRBCW
-#define I_8266_U0_FW6_5 66
-#define I_8266_U1_FW6_5 67
-#define I_8266_DM_FW6_5 68
-#define I_8266_BB_FW6_5 69
+#define I_8266_U0_FW6_5 29
+#define I_8266_U1_FW6_5 30
+#define I_8266_DM_FW6_5 31
+#define I_8266_BB_FW6_5 32
//ESP8266 APA106
-#define I_8266_U0_APA106_3 81
-#define I_8266_U1_APA106_3 82
-#define I_8266_DM_APA106_3 83
-#define I_8266_BB_APA106_3 84
+#define I_8266_U0_APA106_3 33
+#define I_8266_U1_APA106_3 34
+#define I_8266_DM_APA106_3 35
+#define I_8266_BB_APA106_3 36
//WS2805 (RGBCW)
-#define I_8266_U0_2805_5 89
-#define I_8266_U1_2805_5 90
-#define I_8266_DM_2805_5 91
-#define I_8266_BB_2805_5 92
+#define I_8266_U0_2805_5 37
+#define I_8266_U1_2805_5 38
+#define I_8266_DM_2805_5 39
+#define I_8266_BB_2805_5 40
//TM1914 (RGB)
-#define I_8266_U0_TM1914_3 99
-#define I_8266_U1_TM1914_3 100
-#define I_8266_DM_TM1914_3 101
-#define I_8266_BB_TM1914_3 102
+#define I_8266_U0_TM1914_3 41
+#define I_8266_U1_TM1914_3 42
+#define I_8266_DM_TM1914_3 43
+#define I_8266_BB_TM1914_3 44
//SM16825 (RGBCW)
-#define I_8266_U0_SM16825_5 103
-#define I_8266_U1_SM16825_5 104
-#define I_8266_DM_SM16825_5 105
-#define I_8266_BB_SM16825_5 106
+#define I_8266_U0_SM16825_5 45
+#define I_8266_U1_SM16825_5 46
+#define I_8266_DM_SM16825_5 47
+#define I_8266_BB_SM16825_5 48
/*** ESP32 Neopixel methods ***/
//RGB
-#define I_32_RN_NEO_3 21
-#define I_32_I0_NEO_3 22
-#define I_32_I1_NEO_3 23
+#define I_32_RN_NEO_3 1
+#define I_32_I2_NEO_3 2
//RGBW
-#define I_32_RN_NEO_4 25
-#define I_32_I0_NEO_4 26
-#define I_32_I1_NEO_4 27
+#define I_32_RN_NEO_4 5
+#define I_32_I2_NEO_4 6
//400Kbps
-#define I_32_RN_400_3 29
-#define I_32_I0_400_3 30
-#define I_32_I1_400_3 31
+#define I_32_RN_400_3 9
+#define I_32_I2_400_3 10
//TM1814 (RGBW)
-#define I_32_RN_TM1_4 33
-#define I_32_I0_TM1_4 34
-#define I_32_I1_TM1_4 35
+#define I_32_RN_TM1_4 13
+#define I_32_I2_TM1_4 14
//TM1829 (RGB)
-#define I_32_RN_TM2_3 36
-#define I_32_I0_TM2_3 37
-#define I_32_I1_TM2_3 38
+#define I_32_RN_TM2_3 17
+#define I_32_I2_TM2_3 18
//UCS8903 (RGB)
-#define I_32_RN_UCS_3 57
-#define I_32_I0_UCS_3 58
-#define I_32_I1_UCS_3 59
+#define I_32_RN_UCS_3 21
+#define I_32_I2_UCS_3 22
//UCS8904 (RGBW)
-#define I_32_RN_UCS_4 60
-#define I_32_I0_UCS_4 61
-#define I_32_I1_UCS_4 62
+#define I_32_RN_UCS_4 25
+#define I_32_I2_UCS_4 26
//FW1906 GRBCW
-#define I_32_RN_FW6_5 63
-#define I_32_I0_FW6_5 64
-#define I_32_I1_FW6_5 65
+#define I_32_RN_FW6_5 29
+#define I_32_I2_FW6_5 30
//APA106
-#define I_32_RN_APA106_3 85
-#define I_32_I0_APA106_3 86
-#define I_32_I1_APA106_3 87
+#define I_32_RN_APA106_3 33
+#define I_32_I2_APA106_3 34
//WS2805 (RGBCW)
-#define I_32_RN_2805_5 93
-#define I_32_I0_2805_5 94
-#define I_32_I1_2805_5 95
+#define I_32_RN_2805_5 37
+#define I_32_I2_2805_5 38
//TM1914 (RGB)
-#define I_32_RN_TM1914_3 96
-#define I_32_I0_TM1914_3 97
-#define I_32_I1_TM1914_3 98
+#define I_32_RN_TM1914_3 41
+#define I_32_I2_TM1914_3 42
//SM16825 (RGBCW)
-#define I_32_RN_SM16825_5 107
-#define I_32_I0_SM16825_5 108
-#define I_32_I1_SM16825_5 109
+#define I_32_RN_SM16825_5 45
+#define I_32_I2_SM16825_5 46
//APA102
-#define I_HS_DOT_3 39 //hardware SPI
-#define I_SS_DOT_3 40 //soft SPI
+#define I_HS_DOT_3 101 //hardware SPI
+#define I_SS_DOT_3 102 //soft SPI
//LPD8806
-#define I_HS_LPD_3 41
-#define I_SS_LPD_3 42
+#define I_HS_LPD_3 103
+#define I_SS_LPD_3 104
//WS2801
-#define I_HS_WS1_3 43
-#define I_SS_WS1_3 44
+#define I_HS_WS1_3 105
+#define I_SS_WS1_3 106
//P9813
-#define I_HS_P98_3 45
-#define I_SS_P98_3 46
+#define I_HS_P98_3 107
+#define I_SS_P98_3 108
//LPD6803
-#define I_HS_LPO_3 47
-#define I_SS_LPO_3 48
+#define I_HS_LPO_3 109
+#define I_SS_LPO_3 110
// In the following NeoGammaNullMethod can be replaced with NeoGammaWLEDMethod to perform Gamma correction implicitly
@@ -230,66 +204,95 @@
/*** ESP32 Neopixel methods ***/
#ifdef ARDUINO_ARCH_ESP32
+// C3: I2S0 and I2S1 methods not supported (has one I2S bus)
+// S2: I2S0 methods supported (single & parallel), I2S1 methods not supported (has one I2S bus)
+// S3: I2S0 methods not supported, I2S1 supports LCD parallel methods (has two I2S buses)
+// https://github.com/Makuna/NeoPixelBus/blob/b32f719e95ef3c35c46da5c99538017ef925c026/src/internal/Esp32_i2s.h#L4
+// https://github.com/Makuna/NeoPixelBus/blob/b32f719e95ef3c35c46da5c99538017ef925c026/src/internal/NeoEsp32RmtMethod.h#L857
+#if defined(CONFIG_IDF_TARGET_ESP32S3)
+ // S3 will always use LCD parallel output
+ typedef X8Ws2812xMethod X1Ws2812xMethod;
+ typedef X8Sk6812Method X1Sk6812Method;
+ typedef X8400KbpsMethod X1400KbpsMethod;
+ typedef X8800KbpsMethod X1800KbpsMethod;
+ typedef X8Tm1814Method X1Tm1814Method;
+ typedef X8Tm1829Method X1Tm1829Method;
+ typedef X8Apa106Method X1Apa106Method;
+ typedef X8Ws2805Method X1Ws2805Method;
+ typedef X8Tm1914Method X1Tm1914Method;
+#elif defined(CONFIG_IDF_TARGET_ESP32S2)
+ // S2 will use I2S0
+ typedef NeoEsp32I2s0Ws2812xMethod X1Ws2812xMethod;
+ typedef NeoEsp32I2s0Sk6812Method X1Sk6812Method;
+ typedef NeoEsp32I2s0400KbpsMethod X1400KbpsMethod;
+ typedef NeoEsp32I2s0800KbpsMethod X1800KbpsMethod;
+ typedef NeoEsp32I2s0Tm1814Method X1Tm1814Method;
+ typedef NeoEsp32I2s0Tm1829Method X1Tm1829Method;
+ typedef NeoEsp32I2s0Apa106Method X1Apa106Method;
+ typedef NeoEsp32I2s0Ws2805Method X1Ws2805Method;
+ typedef NeoEsp32I2s0Tm1914Method X1Tm1914Method;
+#elif !defined(CONFIG_IDF_TARGET_ESP32C3)
+ // regular ESP32 will use I2S1
+ typedef NeoEsp32I2s1Ws2812xMethod X1Ws2812xMethod;
+ typedef NeoEsp32I2s1Sk6812Method X1Sk6812Method;
+ typedef NeoEsp32I2s1400KbpsMethod X1400KbpsMethod;
+ typedef NeoEsp32I2s1800KbpsMethod X1800KbpsMethod;
+ typedef NeoEsp32I2s1Tm1814Method X1Tm1814Method;
+ typedef NeoEsp32I2s1Tm1829Method X1Tm1829Method;
+ typedef NeoEsp32I2s1Apa106Method X1Apa106Method;
+ typedef NeoEsp32I2s1Ws2805Method X1Ws2805Method;
+ typedef NeoEsp32I2s1Tm1914Method X1Tm1914Method;
+#endif
+
//RGB
-#define B_32_RN_NEO_3 NeoPixelBusLg
-#define B_32_I0_NEO_3 NeoPixelBusLg
-#define B_32_I1_NEO_3 NeoPixelBusLg
-#define B_32_I1_NEO_3P NeoPixelBusLg // parallel I2S
+#define B_32_RN_NEO_3 NeoPixelBusLg // ESP32, S2, S3, C3
+//#define B_32_IN_NEO_3 NeoPixelBusLg // ESP32 (dynamic I2S selection)
+#define B_32_I2_NEO_3 NeoPixelBusLg // ESP32, S2, S3 (automatic I2S selection, see typedef above)
+#define B_32_IP_NEO_3 NeoPixelBusLg // parallel I2S (ESP32, S2, S3)
//RGBW
#define B_32_RN_NEO_4 NeoPixelBusLg
-#define B_32_I0_NEO_4 NeoPixelBusLg
-#define B_32_I1_NEO_4 NeoPixelBusLg
-#define B_32_I1_NEO_4P NeoPixelBusLg // parallel I2S
+#define B_32_I2_NEO_4 NeoPixelBusLg
+#define B_32_IP_NEO_4 NeoPixelBusLg // parallel I2S
//400Kbps
#define B_32_RN_400_3 NeoPixelBusLg
-#define B_32_I0_400_3 NeoPixelBusLg
-#define B_32_I1_400_3 NeoPixelBusLg
-#define B_32_I1_400_3P NeoPixelBusLg // parallel I2S
+#define B_32_I2_400_3 NeoPixelBusLg
+#define B_32_IP_400_3 NeoPixelBusLg // parallel I2S
//TM1814 (RGBW)
#define B_32_RN_TM1_4 NeoPixelBusLg
-#define B_32_I0_TM1_4 NeoPixelBusLg
-#define B_32_I1_TM1_4 NeoPixelBusLg
-#define B_32_I1_TM1_4P NeoPixelBusLg // parallel I2S
+#define B_32_I2_TM1_4 NeoPixelBusLg
+#define B_32_IP_TM1_4 NeoPixelBusLg // parallel I2S
//TM1829 (RGB)
#define B_32_RN_TM2_3 NeoPixelBusLg
-#define B_32_I0_TM2_3 NeoPixelBusLg
-#define B_32_I1_TM2_3 NeoPixelBusLg
-#define B_32_I1_TM2_3P NeoPixelBusLg // parallel I2S
+#define B_32_I2_TM2_3 NeoPixelBusLg
+#define B_32_IP_TM2_3 NeoPixelBusLg // parallel I2S
//UCS8903
#define B_32_RN_UCS_3 NeoPixelBusLg
-#define B_32_I0_UCS_3 NeoPixelBusLg
-#define B_32_I1_UCS_3 NeoPixelBusLg
-#define B_32_I1_UCS_3P NeoPixelBusLg // parallel I2S
+#define B_32_I2_UCS_3 NeoPixelBusLg
+#define B_32_IP_UCS_3 NeoPixelBusLg // parallel I2S
//UCS8904
#define B_32_RN_UCS_4 NeoPixelBusLg
-#define B_32_I0_UCS_4 NeoPixelBusLg
-#define B_32_I1_UCS_4 NeoPixelBusLg
-#define B_32_I1_UCS_4P NeoPixelBusLg// parallel I2S
+#define B_32_I2_UCS_4 NeoPixelBusLg
+#define B_32_IP_UCS_4 NeoPixelBusLg// parallel I2S
//APA106
#define B_32_RN_APA106_3 NeoPixelBusLg
-#define B_32_I0_APA106_3 NeoPixelBusLg
-#define B_32_I1_APA106_3 NeoPixelBusLg
-#define B_32_I1_APA106_3P NeoPixelBusLg // parallel I2S
+#define B_32_I2_APA106_3 NeoPixelBusLg
+#define B_32_IP_APA106_3 NeoPixelBusLg // parallel I2S
//FW1906 GRBCW
#define B_32_RN_FW6_5 NeoPixelBusLg
-#define B_32_I0_FW6_5 NeoPixelBusLg
-#define B_32_I1_FW6_5 NeoPixelBusLg
-#define B_32_I1_FW6_5P NeoPixelBusLg // parallel I2S
+#define B_32_I2_FW6_5 NeoPixelBusLg
+#define B_32_IP_FW6_5 NeoPixelBusLg // parallel I2S
//WS2805 RGBWC
#define B_32_RN_2805_5 NeoPixelBusLg
-#define B_32_I0_2805_5 NeoPixelBusLg
-#define B_32_I1_2805_5 NeoPixelBusLg
-#define B_32_I1_2805_5P NeoPixelBusLg // parallel I2S
+#define B_32_I2_2805_5 NeoPixelBusLg
+#define B_32_IP_2805_5 NeoPixelBusLg // parallel I2S
//TM1914 (RGB)
#define B_32_RN_TM1914_3 NeoPixelBusLg
-#define B_32_I0_TM1914_3 NeoPixelBusLg
-#define B_32_I1_TM1914_3 NeoPixelBusLg
-#define B_32_I1_TM1914_3P NeoPixelBusLg // parallel I2S
+#define B_32_I2_TM1914_3 NeoPixelBusLg
+#define B_32_IP_TM1914_3 NeoPixelBusLg // parallel I2S
//Sm16825 (RGBWC)
#define B_32_RN_SM16825_5 NeoPixelBusLg
-#define B_32_I0_SM16825_5 NeoPixelBusLg
-#define B_32_I1_SM16825_5 NeoPixelBusLg
-#define B_32_I1_SM16825_5P NeoPixelBusLg // parallel I2S
+#define B_32_I2_SM16825_5 NeoPixelBusLg
+#define B_32_IP_SM16825_5 NeoPixelBusLg // parallel I2S
#endif
//APA102
@@ -328,11 +331,11 @@
//handles pointer type conversion for all possible bus types
class PolyBus {
private:
- static bool useParallelI2S;
+ static bool _useParallelI2S;
public:
- static inline void setParallelI2S1Output(bool b = true) { useParallelI2S = b; }
- static inline bool isParallelI2S1Output(void) { return useParallelI2S; }
+ static inline void setParallelI2S1Output(bool b = true) { _useParallelI2S = b; }
+ static inline bool isParallelI2S1Output(void) { return _useParallelI2S; }
// initialize SPI bus speed for DotStar methods
template
@@ -436,34 +439,19 @@ class PolyBus {
case I_32_RN_TM1914_3: beginTM1914(busPtr); break;
case I_32_RN_SM16825_5: (static_cast(busPtr))->Begin(); break;
// I2S1 bus or parellel buses
- #ifndef WLED_NO_I2S1_PIXELBUS
- case I_32_I1_NEO_3: if (useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
- case I_32_I1_NEO_4: if (useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
- case I_32_I1_400_3: if (useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
- case I_32_I1_TM1_4: if (useParallelI2S) beginTM1814(busPtr); else beginTM1814(busPtr); break;
- case I_32_I1_TM2_3: if (useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
- case I_32_I1_UCS_3: if (useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
- case I_32_I1_UCS_4: if (useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
- case I_32_I1_FW6_5: if (useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
- case I_32_I1_APA106_3: if (useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
- case I_32_I1_2805_5: if (useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
- case I_32_I1_TM1914_3: if (useParallelI2S) beginTM1914(busPtr); else beginTM1914(busPtr); break;
- case I_32_I1_SM16825_5: if (useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
- #endif
- // I2S0 bus
- #ifndef WLED_NO_I2S0_PIXELBUS
- case I_32_I0_NEO_3: (static_cast(busPtr))->Begin(); break;
- case I_32_I0_NEO_4: (static_cast(busPtr))->Begin(); break;
- case I_32_I0_400_3: (static_cast(busPtr))->Begin(); break;
- case I_32_I0_TM1_4: beginTM1814(busPtr); break;
- case I_32_I0_TM2_3: (static_cast(busPtr))->Begin(); break;
- case I_32_I0_UCS_3: (static_cast(busPtr))->Begin(); break;
- case I_32_I0_UCS_4: (static_cast(busPtr))->Begin(); break;
- case I_32_I0_FW6_5: (static_cast(busPtr))->Begin(); break;
- case I_32_I0_APA106_3: (static_cast(busPtr))->Begin(); break;
- case I_32_I0_2805_5: (static_cast(busPtr))->Begin(); break;
- case I_32_I0_TM1914_3: beginTM1914(busPtr); break;
- case I_32_I0_SM16825_5: (static_cast(busPtr))->Begin(); break;
+ #ifndef CONFIG_IDF_TARGET_ESP32C3
+ case I_32_I2_NEO_3: if (_useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
+ case I_32_I2_NEO_4: if (_useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
+ case I_32_I2_400_3: if (_useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
+ case I_32_I2_TM1_4: if (_useParallelI2S) beginTM1814(busPtr); else beginTM1814(busPtr); break;
+ case I_32_I2_TM2_3: if (_useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
+ case I_32_I2_UCS_3: if (_useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
+ case I_32_I2_UCS_4: if (_useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
+ case I_32_I2_FW6_5: if (_useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
+ case I_32_I2_APA106_3: if (_useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
+ case I_32_I2_2805_5: if (_useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
+ case I_32_I2_TM1914_3: if (_useParallelI2S) beginTM1914(busPtr); else beginTM1914(busPtr); break;
+ case I_32_I2_SM16825_5: if (_useParallelI2S) (static_cast(busPtr))->Begin(); else (static_cast(busPtr))->Begin(); break;
#endif
// ESP32 can (and should, to avoid inadvertantly driving the chip select signal) specify the pins used for SPI, but only in begin()
case I_HS_DOT_3: beginDotStar(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break;
@@ -484,8 +472,8 @@ 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
- if (useParallelI2S && 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
+ if (!_useParallelI2S && channel > 0) channel--; // accommodate I2S1 which is used as 1st bus on classic ESP32
+ // if user selected parallel I2S, RMT is used 1st (8 channels) followed by parallel I2S (8 channels)
#endif
void* busPtr = nullptr;
switch (busType) {
@@ -555,34 +543,19 @@ class PolyBus {
case I_32_RN_TM1914_3: busPtr = new B_32_RN_TM1914_3(len, pins[0], (NeoBusChannel)channel); break;
case I_32_RN_SM16825_5: busPtr = new B_32_RN_SM16825_5(len, pins[0], (NeoBusChannel)channel); break;
// I2S1 bus or paralell buses
- #ifndef WLED_NO_I2S1_PIXELBUS
- case I_32_I1_NEO_3: if (useParallelI2S) busPtr = new B_32_I1_NEO_3P(len, pins[0]); else busPtr = new B_32_I1_NEO_3(len, pins[0]); break;
- case I_32_I1_NEO_4: if (useParallelI2S) busPtr = new B_32_I1_NEO_4P(len, pins[0]); else busPtr = new B_32_I1_NEO_4(len, pins[0]); break;
- case I_32_I1_400_3: if (useParallelI2S) busPtr = new B_32_I1_400_3P(len, pins[0]); else busPtr = new B_32_I1_400_3(len, pins[0]); break;
- case I_32_I1_TM1_4: if (useParallelI2S) busPtr = new B_32_I1_TM1_4P(len, pins[0]); else busPtr = new B_32_I1_TM1_4(len, pins[0]); break;
- case I_32_I1_TM2_3: if (useParallelI2S) busPtr = new B_32_I1_TM2_3P(len, pins[0]); else busPtr = new B_32_I1_TM2_3(len, pins[0]); break;
- case I_32_I1_UCS_3: if (useParallelI2S) busPtr = new B_32_I1_UCS_3P(len, pins[0]); else busPtr = new B_32_I1_UCS_3(len, pins[0]); break;
- case I_32_I1_UCS_4: if (useParallelI2S) busPtr = new B_32_I1_UCS_4P(len, pins[0]); else busPtr = new B_32_I1_UCS_4(len, pins[0]); break;
- case I_32_I1_APA106_3: if (useParallelI2S) busPtr = new B_32_I1_APA106_3P(len, pins[0]); else busPtr = new B_32_I1_APA106_3(len, pins[0]); break;
- case I_32_I1_FW6_5: if (useParallelI2S) busPtr = new B_32_I1_FW6_5P(len, pins[0]); else busPtr = new B_32_I1_FW6_5(len, pins[0]); break;
- case I_32_I1_2805_5: if (useParallelI2S) busPtr = new B_32_I1_2805_5P(len, pins[0]); else busPtr = new B_32_I1_2805_5(len, pins[0]); break;
- case I_32_I1_TM1914_3: if (useParallelI2S) busPtr = new B_32_I1_TM1914_3P(len, pins[0]); else busPtr = new B_32_I1_TM1914_3(len, pins[0]); break;
- case I_32_I1_SM16825_5: if (useParallelI2S) busPtr = new B_32_I1_SM16825_5P(len, pins[0]); else busPtr = new B_32_I1_SM16825_5(len, pins[0]); break;
- #endif
- // I2S0 bus
- #ifndef WLED_NO_I2S0_PIXELBUS
- case I_32_I0_NEO_3: busPtr = new B_32_I0_NEO_3(len, pins[0]); break;
- case I_32_I0_NEO_4: busPtr = new B_32_I0_NEO_4(len, pins[0]); break;
- case I_32_I0_400_3: busPtr = new B_32_I0_400_3(len, pins[0]); break;
- case I_32_I0_TM1_4: busPtr = new B_32_I0_TM1_4(len, pins[0]); break;
- case I_32_I0_TM2_3: busPtr = new B_32_I0_TM2_3(len, pins[0]); break;
- case I_32_I0_UCS_3: busPtr = new B_32_I0_UCS_3(len, pins[0]); break;
- case I_32_I0_UCS_4: busPtr = new B_32_I0_UCS_4(len, pins[0]); break;
- case I_32_I0_APA106_3: busPtr = new B_32_I0_APA106_3(len, pins[0]); break;
- case I_32_I0_FW6_5: busPtr = new B_32_I0_FW6_5(len, pins[0]); break;
- case I_32_I0_2805_5: busPtr = new B_32_I0_2805_5(len, pins[0]); break;
- case I_32_I0_TM1914_3: busPtr = new B_32_I0_TM1914_3(len, pins[0]); break;
- case I_32_I0_SM16825_5: busPtr = new B_32_I0_SM16825_5(len, pins[0]); break;
+ #ifndef CONFIG_IDF_TARGET_ESP32C3
+ case I_32_I2_NEO_3: if (_useParallelI2S) busPtr = new B_32_IP_NEO_3(len, pins[0]); else busPtr = new B_32_I2_NEO_3(len, pins[0]); break;
+ case I_32_I2_NEO_4: if (_useParallelI2S) busPtr = new B_32_IP_NEO_4(len, pins[0]); else busPtr = new B_32_I2_NEO_4(len, pins[0]); break;
+ case I_32_I2_400_3: if (_useParallelI2S) busPtr = new B_32_IP_400_3(len, pins[0]); else busPtr = new B_32_I2_400_3(len, pins[0]); break;
+ case I_32_I2_TM1_4: if (_useParallelI2S) busPtr = new B_32_IP_TM1_4(len, pins[0]); else busPtr = new B_32_I2_TM1_4(len, pins[0]); break;
+ case I_32_I2_TM2_3: if (_useParallelI2S) busPtr = new B_32_IP_TM2_3(len, pins[0]); else busPtr = new B_32_I2_TM2_3(len, pins[0]); break;
+ case I_32_I2_UCS_3: if (_useParallelI2S) busPtr = new B_32_IP_UCS_3(len, pins[0]); else busPtr = new B_32_I2_UCS_3(len, pins[0]); break;
+ case I_32_I2_UCS_4: if (_useParallelI2S) busPtr = new B_32_IP_UCS_4(len, pins[0]); else busPtr = new B_32_I2_UCS_4(len, pins[0]); break;
+ case I_32_I2_APA106_3: if (_useParallelI2S) busPtr = new B_32_IP_APA106_3(len, pins[0]); else busPtr = new B_32_I2_APA106_3(len, pins[0]); break;
+ case I_32_I2_FW6_5: if (_useParallelI2S) busPtr = new B_32_IP_FW6_5(len, pins[0]); else busPtr = new B_32_I2_FW6_5(len, pins[0]); break;
+ case I_32_I2_2805_5: if (_useParallelI2S) busPtr = new B_32_IP_2805_5(len, pins[0]); else busPtr = new B_32_I2_2805_5(len, pins[0]); break;
+ case I_32_I2_TM1914_3: if (_useParallelI2S) busPtr = new B_32_IP_TM1914_3(len, pins[0]); else busPtr = new B_32_I2_TM1914_3(len, pins[0]); break;
+ case I_32_I2_SM16825_5: if (_useParallelI2S) busPtr = new B_32_IP_SM16825_5(len, pins[0]); else busPtr = new B_32_I2_SM16825_5(len, pins[0]); break;
#endif
#endif
// for 2-wire: pins[1] is clk, pins[0] is dat. begin expects (len, clk, dat)
@@ -669,34 +642,19 @@ class PolyBus {
case I_32_RN_TM1914_3: (static_cast(busPtr))->Show(consistent); break;
case I_32_RN_SM16825_5: (static_cast(busPtr))->Show(consistent); break;
// I2S1 bus or paralell buses
- #ifndef WLED_NO_I2S1_PIXELBUS
- case I_32_I1_NEO_3: if (useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
- case I_32_I1_NEO_4: if (useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
- case I_32_I1_400_3: if (useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
- case I_32_I1_TM1_4: if (useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
- case I_32_I1_TM2_3: if (useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
- case I_32_I1_UCS_3: if (useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
- case I_32_I1_UCS_4: if (useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
- case I_32_I1_APA106_3: if (useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
- case I_32_I1_FW6_5: if (useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
- case I_32_I1_2805_5: if (useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
- case I_32_I1_TM1914_3: if (useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
- case I_32_I1_SM16825_5: if (useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
- #endif
- // I2S0 bus
- #ifndef WLED_NO_I2S0_PIXELBUS
- case I_32_I0_NEO_3: (static_cast(busPtr))->Show(consistent); break;
- case I_32_I0_NEO_4: (static_cast(busPtr))->Show(consistent); break;
- case I_32_I0_400_3: (static_cast(busPtr))->Show(consistent); break;
- case I_32_I0_TM1_4: (static_cast(busPtr))->Show(consistent); break;
- case I_32_I0_TM2_3: (static_cast(busPtr))->Show(consistent); break;
- case I_32_I0_UCS_3: (static_cast(busPtr))->Show(consistent); break;
- case I_32_I0_UCS_4: (static_cast(busPtr))->Show(consistent); break;
- case I_32_I0_APA106_3: (static_cast(busPtr))->Show(consistent); break;
- case I_32_I0_FW6_5: (static_cast(busPtr))->Show(consistent); break;
- case I_32_I0_2805_5: (static_cast(busPtr))->Show(consistent); break;
- case I_32_I0_TM1914_3: (static_cast(busPtr))->Show(consistent); break;
- case I_32_I0_SM16825_5: (static_cast(busPtr))->Show(consistent); break;
+ #ifndef CONFIG_IDF_TARGET_ESP32C3
+ case I_32_I2_NEO_3: if (_useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
+ case I_32_I2_NEO_4: if (_useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
+ case I_32_I2_400_3: if (_useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
+ case I_32_I2_TM1_4: if (_useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
+ case I_32_I2_TM2_3: if (_useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
+ case I_32_I2_UCS_3: if (_useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
+ case I_32_I2_UCS_4: if (_useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
+ case I_32_I2_APA106_3: if (_useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
+ case I_32_I2_FW6_5: if (_useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
+ case I_32_I2_2805_5: if (_useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
+ case I_32_I2_TM1914_3: if (_useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
+ case I_32_I2_SM16825_5: if (_useParallelI2S) (static_cast(busPtr))->Show(consistent); else (static_cast(busPtr))->Show(consistent); break;
#endif
#endif
case I_HS_DOT_3: (static_cast(busPtr))->Show(consistent); break;
@@ -743,6 +701,7 @@ class PolyBus {
case I_8266_U0_UCS_4: return (static_cast(busPtr))->CanShow(); break;
case I_8266_U1_UCS_4: return (static_cast(busPtr))->CanShow(); break;
case I_8266_DM_UCS_4: return (static_cast(busPtr))->CanShow(); break;
+ case I_8266_BB_UCS_4: return (static_cast(busPtr))->CanShow(); break;
case I_8266_U0_APA106_3: return (static_cast(busPtr))->CanShow(); break;
case I_8266_U1_APA106_3: return (static_cast(busPtr))->CanShow(); break;
case I_8266_DM_APA106_3: return (static_cast(busPtr))->CanShow(); break;
@@ -779,34 +738,19 @@ class PolyBus {
case I_32_RN_TM1914_3: return (static_cast(busPtr))->CanShow(); break;
case I_32_RN_SM16825_5: return (static_cast(busPtr))->CanShow(); break;
// I2S1 bus or paralell buses
- #ifndef WLED_NO_I2S1_PIXELBUS
- case I_32_I1_NEO_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_NEO_4: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_400_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_TM1_4: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_TM2_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break;
- case I_32_I1_UCS_3: if (useParallelI2S) return (static_cast