From 6ad6acfe0827dcd44e476872a1c98e5e5a0b358d Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 25 Jan 2026 15:06:27 +0100 Subject: [PATCH 01/12] align DMX output drivers with upstream imports a few DMX serial output improvement from upstream --- wled00/src/dependencies/dmx/ESPDMX.cpp | 9 +++++---- wled00/src/dependencies/dmx/SparkFunDMX.cpp | 6 ++++-- wled00/wled.h | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/wled00/src/dependencies/dmx/ESPDMX.cpp b/wled00/src/dependencies/dmx/ESPDMX.cpp index d0d652c825..ca54260135 100644 --- a/wled00/src/dependencies/dmx/ESPDMX.cpp +++ b/wled00/src/dependencies/dmx/ESPDMX.cpp @@ -11,12 +11,13 @@ // - - - - - /* ----- LIBRARIES ----- */ -#ifdef ESP8266 +#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) #include #include "ESPDMX.h" +#pragma message "using ESPDMX" #define dmxMaxChannel 512 @@ -30,8 +31,8 @@ bool dmxStarted = false; int sendPin = 2; //default on ESP8266 -//DMX value array and size. Entry 0 will hold startbyte -uint8_t dmxDataStore[dmxMaxChannel] = {}; +//DMX value array and size. Entry 0 will hold startbyte, so we need 512+1 elements +uint8_t dmxDataStore[dmxMaxChannel+1] = {}; int channelSize; @@ -106,4 +107,4 @@ void DMXESPSerial::update() { // Function to update the DMX bus -#endif \ No newline at end of file +#endif diff --git a/wled00/src/dependencies/dmx/SparkFunDMX.cpp b/wled00/src/dependencies/dmx/SparkFunDMX.cpp index dbc9b15909..f97bd1d430 100644 --- a/wled00/src/dependencies/dmx/SparkFunDMX.cpp +++ b/wled00/src/dependencies/dmx/SparkFunDMX.cpp @@ -22,6 +22,8 @@ Distributed as-is; no warranty is given. #include "SparkFunDMX.h" #include +#pragma message "using SparkFunDMX" + #define dmxMaxChannel 512 #define defaultMax 32 @@ -34,8 +36,8 @@ static const int enablePin = -1; // disable the enable pin because it is not ne static const int rxPin = -1; // disable the receiving pin because it is not needed - softhack007: Pin=-1 means "use default" not "disable" static const int txPin = 2; // transmit DMX data over this pin (default is pin 2) -//DMX value array and size. Entry 0 will hold startbyte -static uint8_t dmxData[dmxMaxChannel] = { 0 }; +//DMX value array and size. Entry 0 will hold startbyte, so we need 512+1 elements +static uint8_t dmxData[dmxMaxChannel+1] = { 0 }; static int chanSize = 0; #if !defined(DMX_SEND_ONLY) static int currentChannel = 0; diff --git a/wled00/wled.h b/wled00/wled.h index e5047aa590..9daf4a8d01 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -164,7 +164,7 @@ #endif #ifdef WLED_ENABLE_DMX - #ifdef ESP8266 + #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) #include "src/dependencies/dmx/ESPDMX.h" #else //ESP32 #include "src/dependencies/dmx/SparkFunDMX.h" From 900178cd70d387bfcbb36de382095acfd666f9f7 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 25 Jan 2026 15:08:40 +0100 Subject: [PATCH 02/12] only build DMX drivers when WLED_ENABLE_DMX both ESPDMX and SparkFunDMX have their own global buffers. Conditional compile prevents that these buffers are consuming RAM when not needed. --- wled00/src/dependencies/dmx/ESPDMX.cpp | 2 +- wled00/src/dependencies/dmx/SparkFunDMX.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/src/dependencies/dmx/ESPDMX.cpp b/wled00/src/dependencies/dmx/ESPDMX.cpp index ca54260135..31adefdbec 100644 --- a/wled00/src/dependencies/dmx/ESPDMX.cpp +++ b/wled00/src/dependencies/dmx/ESPDMX.cpp @@ -11,7 +11,7 @@ // - - - - - /* ----- LIBRARIES ----- */ -#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) +#if defined(WLED_ENABLE_DMX) && (defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2)) #include diff --git a/wled00/src/dependencies/dmx/SparkFunDMX.cpp b/wled00/src/dependencies/dmx/SparkFunDMX.cpp index f97bd1d430..b299cf7042 100644 --- a/wled00/src/dependencies/dmx/SparkFunDMX.cpp +++ b/wled00/src/dependencies/dmx/SparkFunDMX.cpp @@ -14,7 +14,7 @@ Distributed as-is; no warranty is given. ******************************************************************************/ /* ----- LIBRARIES ----- */ -#if defined(ARDUINO_ARCH_ESP32) +#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_ENABLE_DMX) #include #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) From fb738883fae6d705b8f8f42ebfee43f4c1f0af1a Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 25 Jan 2026 15:43:53 +0100 Subject: [PATCH 03/12] safeguards against array bounds violation --- wled00/src/dependencies/dmx/SparkFunDMX.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/wled00/src/dependencies/dmx/SparkFunDMX.cpp b/wled00/src/dependencies/dmx/SparkFunDMX.cpp index b299cf7042..fc20da12d1 100644 --- a/wled00/src/dependencies/dmx/SparkFunDMX.cpp +++ b/wled00/src/dependencies/dmx/SparkFunDMX.cpp @@ -124,6 +124,7 @@ void SparkFunDMX::initWrite (int chanQuant) { // Function to read DMX data uint8_t SparkFunDMX::read(int Channel) { if (Channel > chanSize) Channel = chanSize; + if ((Channel > dmxMaxChannel) || (Channel < 1)) return 0; // WLEDMM prevent array out-of-bounds access return(dmxData[Channel - 1]); //subtract one to account for start byte } #endif @@ -132,6 +133,7 @@ uint8_t SparkFunDMX::read(int Channel) { void SparkFunDMX::write(int Channel, uint8_t value) { if (Channel < 0) Channel = 0; if (Channel > chanSize) chanSize = Channel; + if (Channel > dmxMaxChannel) Channel = dmxMaxChannel; // WLEDMM prevent array out-of-bounds access dmxData[0] = 0; dmxData[Channel] = value; //add one to account for start byte } @@ -151,7 +153,7 @@ void SparkFunDMX::update() { //Send DMX data DMXSerial.begin(DMXSPEED, DMXFORMAT, rxPin, txPin);//Begin the Serial port - DMXSerial.write(dmxData, chanSize); + DMXSerial.write(dmxData, min(dmxMaxChannel, chanSize)); DMXSerial.flush(); DMXSerial.end();//clear our DMX array, end the Hardware Serial port } @@ -162,9 +164,11 @@ void SparkFunDMX::update() { { while (DMXSerial.available()) { - dmxData[currentChannel++] = DMXSerial.read(); + uint8_t newdata = DMXSerial.read(); + if (currentChannel <= dmxMaxChannel) + dmxData[currentChannel++] = newdata; } - if (currentChannel > chanSize) //Set the channel counter back to 0 if we reach the known end size of our packet + if ((currentChannel > chanSize) || (currentChannel > dmxMaxChannel)) //Set the channel counter back to 0 if we reach the known end size of our packet { portENTER_CRITICAL(&timerMux); From 279d48a3d11e6b36f5cd4f7ba5e4c9d0e5c82ed1 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 25 Jan 2026 15:44:40 +0100 Subject: [PATCH 04/12] (minor) clarify compile-time messages for DMX drivers --- wled00/dmx_input.cpp | 2 +- wled00/dmx_output.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index 3be973cc34..86bdf490ad 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -1,7 +1,7 @@ #include "wled.h" #ifdef WLED_ENABLE_DMX_INPUT -#pragma message "DMX physical input driver enabled" +#pragma message "DMX physical input driver (esp-dmx) enabled" #ifdef ESP8266 #error DMX input is only supported on ESP32 diff --git a/wled00/dmx_output.cpp b/wled00/dmx_output.cpp index 6caa3ec88a..2fdc826ade 100644 --- a/wled00/dmx_output.cpp +++ b/wled00/dmx_output.cpp @@ -11,7 +11,7 @@ */ #ifdef WLED_ENABLE_DMX -#pragma message "DMX network output enabled" +#pragma message "DMX output enabled" #define MAX_DMX_RATE 44 // max DMX update rate in Hz From 82f713093e4e5e35fc9591a43e90a43e5d36a77b Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 25 Jan 2026 15:46:57 +0100 Subject: [PATCH 05/12] indentation --- wled00/src/dependencies/dmx/SparkFunDMX.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wled00/src/dependencies/dmx/SparkFunDMX.cpp b/wled00/src/dependencies/dmx/SparkFunDMX.cpp index fc20da12d1..d862f2b8f7 100644 --- a/wled00/src/dependencies/dmx/SparkFunDMX.cpp +++ b/wled00/src/dependencies/dmx/SparkFunDMX.cpp @@ -164,9 +164,9 @@ void SparkFunDMX::update() { { while (DMXSerial.available()) { - uint8_t newdata = DMXSerial.read(); - if (currentChannel <= dmxMaxChannel) - dmxData[currentChannel++] = newdata; + uint8_t newdata = DMXSerial.read(); + if (currentChannel <= dmxMaxChannel) + dmxData[currentChannel++] = newdata; } if ((currentChannel > chanSize) || (currentChannel > dmxMaxChannel)) //Set the channel counter back to 0 if we reach the known end size of our packet { From 2628e9167da2de283a87105c73a9827785293b0d Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 25 Jan 2026 16:15:24 +0100 Subject: [PATCH 06/12] fix max number of bytes to be sent --- wled00/src/dependencies/dmx/SparkFunDMX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/src/dependencies/dmx/SparkFunDMX.cpp b/wled00/src/dependencies/dmx/SparkFunDMX.cpp index d862f2b8f7..1241dba6dc 100644 --- a/wled00/src/dependencies/dmx/SparkFunDMX.cpp +++ b/wled00/src/dependencies/dmx/SparkFunDMX.cpp @@ -153,7 +153,7 @@ void SparkFunDMX::update() { //Send DMX data DMXSerial.begin(DMXSPEED, DMXFORMAT, rxPin, txPin);//Begin the Serial port - DMXSerial.write(dmxData, min(dmxMaxChannel, chanSize)); + DMXSerial.write(dmxData, min(dmxMaxChannel+1, chanSize)); // send max 513 bytes = start byte + 512 channels DMXSerial.flush(); DMXSerial.end();//clear our DMX array, end the Hardware Serial port } From f0753d6cf6601d7b7c9836152214326d473496b5 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 25 Jan 2026 16:18:30 +0100 Subject: [PATCH 07/12] robustness improvement bounds check before changing global variables --- wled00/src/dependencies/dmx/SparkFunDMX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/src/dependencies/dmx/SparkFunDMX.cpp b/wled00/src/dependencies/dmx/SparkFunDMX.cpp index 1241dba6dc..da91b40204 100644 --- a/wled00/src/dependencies/dmx/SparkFunDMX.cpp +++ b/wled00/src/dependencies/dmx/SparkFunDMX.cpp @@ -123,8 +123,8 @@ void SparkFunDMX::initWrite (int chanQuant) { #if !defined(DMX_SEND_ONLY) // Function to read DMX data uint8_t SparkFunDMX::read(int Channel) { - if (Channel > chanSize) Channel = chanSize; if ((Channel > dmxMaxChannel) || (Channel < 1)) return 0; // WLEDMM prevent array out-of-bounds access + if (Channel > chanSize) Channel = chanSize; return(dmxData[Channel - 1]); //subtract one to account for start byte } #endif From 8faa88e05b1c1cf55931c215e212c8e0e137dda7 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 25 Jan 2026 17:02:06 +0100 Subject: [PATCH 08/12] chanSize expansion must account for start byte --- wled00/src/dependencies/dmx/SparkFunDMX.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/src/dependencies/dmx/SparkFunDMX.cpp b/wled00/src/dependencies/dmx/SparkFunDMX.cpp index da91b40204..b9870e883a 100644 --- a/wled00/src/dependencies/dmx/SparkFunDMX.cpp +++ b/wled00/src/dependencies/dmx/SparkFunDMX.cpp @@ -132,8 +132,8 @@ uint8_t SparkFunDMX::read(int Channel) { // Function to send DMX data void SparkFunDMX::write(int Channel, uint8_t value) { if (Channel < 0) Channel = 0; - if (Channel > chanSize) chanSize = Channel; - if (Channel > dmxMaxChannel) Channel = dmxMaxChannel; // WLEDMM prevent array out-of-bounds access + if (Channel+1 > chanSize) chanSize = min(dmxMaxChannel +1, Channel+1); // WLEDMM "+1" as we need to account for start byte + if (Channel > dmxMaxChannel) Channel = dmxMaxChannel; // WLEDMM prevent array out-of-bounds access dmxData[0] = 0; dmxData[Channel] = value; //add one to account for start byte } From 3150f3b448a492a39ec26edb11a99ea1226e7280 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 25 Jan 2026 17:12:04 +0100 Subject: [PATCH 09/12] use correct DMXSerial object on -S2 and -C3 --- wled00/dmx_output.cpp | 2 +- wled00/wled.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wled00/dmx_output.cpp b/wled00/dmx_output.cpp index 2fdc826ade..dae82256ed 100644 --- a/wled00/dmx_output.cpp +++ b/wled00/dmx_output.cpp @@ -99,7 +99,7 @@ void handleDMXOutput() } void initDMXOutput() { - #ifdef ESP8266 + #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) dmx.init(512); // initialize with bus length #else dmx.initWrite(512); // initialize with bus length diff --git a/wled00/wled.h b/wled00/wled.h index 9daf4a8d01..73a4286da6 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -166,7 +166,7 @@ #ifdef WLED_ENABLE_DMX #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) #include "src/dependencies/dmx/ESPDMX.h" - #else //ESP32 + #else //ESP32 or ESP32-S3 #include "src/dependencies/dmx/SparkFunDMX.h" #endif #endif @@ -468,7 +468,7 @@ WLED_GLOBAL bool arlsDisableGammaCorrection _INIT(true); // activate if WLED_GLOBAL bool arlsForceMaxBri _INIT(false); // enable to force max brightness if source has very dark colors that would be black #ifdef WLED_ENABLE_DMX - #ifdef ESP8266 + #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) WLED_GLOBAL DMXESPSerial dmx; #else //ESP32 WLED_GLOBAL SparkFunDMX dmx; From e6e23484836d6a611ee9be4118950838b5c5e13e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20M=C3=B6hle?= <91616163+softhack007@users.noreply.github.com> Date: Sun, 25 Jan 2026 17:29:10 +0100 Subject: [PATCH 10/12] protect start byte If Channel is less than 0, it's clamped to 0 on line 134. Then on line 138, dmxData[0] is written with the value, overwriting the start byte that was just set on line 137. DMX Channel numbers should be 1-based (1-512). The bounds check should clamp Channel to a minimum of 1, not 0, to prevent corrupting the start byte Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- wled00/src/dependencies/dmx/SparkFunDMX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/src/dependencies/dmx/SparkFunDMX.cpp b/wled00/src/dependencies/dmx/SparkFunDMX.cpp index b9870e883a..1ef121216b 100644 --- a/wled00/src/dependencies/dmx/SparkFunDMX.cpp +++ b/wled00/src/dependencies/dmx/SparkFunDMX.cpp @@ -131,7 +131,7 @@ uint8_t SparkFunDMX::read(int Channel) { // Function to send DMX data void SparkFunDMX::write(int Channel, uint8_t value) { - if (Channel < 0) Channel = 0; + if (Channel < 1) Channel = 1; if (Channel+1 > chanSize) chanSize = min(dmxMaxChannel +1, Channel+1); // WLEDMM "+1" as we need to account for start byte if (Channel > dmxMaxChannel) Channel = dmxMaxChannel; // WLEDMM prevent array out-of-bounds access dmxData[0] = 0; From 0718a6d2651bf01d9bc214cee51d7dc23eca1296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20M=C3=B6hle?= <91616163+softhack007@users.noreply.github.com> Date: Sun, 25 Jan 2026 17:30:03 +0100 Subject: [PATCH 11/12] comment clarification Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- wled00/wled.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/wled.h b/wled00/wled.h index 73a4286da6..222f23b359 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -470,7 +470,7 @@ WLED_GLOBAL bool arlsForceMaxBri _INIT(false); // enable to f #ifdef WLED_ENABLE_DMX #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) WLED_GLOBAL DMXESPSerial dmx; - #else //ESP32 + #else //ESP32 or ESP32-S3 WLED_GLOBAL SparkFunDMX dmx; #endif WLED_GLOBAL uint16_t e131ProxyUniverse _INIT(0); // output this E1.31 (sACN) / ArtNet universe via MAX485 (0 = disabled) From 57d63b7362a8bd266b38f015de52b4a07a6d7714 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 25 Jan 2026 17:45:08 +0100 Subject: [PATCH 12/12] ESPDMX robustness improvements * clamp channel to dmxMaxChannel (write) * ensure that all data get sent, including start byte --- wled00/src/dependencies/dmx/ESPDMX.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wled00/src/dependencies/dmx/ESPDMX.cpp b/wled00/src/dependencies/dmx/ESPDMX.cpp index 31adefdbec..0ac3a5c749 100644 --- a/wled00/src/dependencies/dmx/ESPDMX.cpp +++ b/wled00/src/dependencies/dmx/ESPDMX.cpp @@ -73,6 +73,7 @@ void DMXESPSerial::write(int Channel, uint8_t value) { if (Channel < 1) Channel = 1; if (Channel > channelSize) Channel = channelSize; + if (Channel > dmxMaxChannel) Channel = dmxMaxChannel; // WLEDMM protect against array bounds violation if (value < 0) value = 0; if (value > 255) value = 255; @@ -99,7 +100,7 @@ void DMXESPSerial::update() { //send data Serial1.begin(DMXSPEED, DMXFORMAT); digitalWrite(sendPin, LOW); - Serial1.write(dmxDataStore, channelSize); + Serial1.write(dmxDataStore, min(dmxMaxChannel+1, channelSize+1)); Serial1.flush(); delay(1); Serial1.end();