From 96491255f1adde9d670aa109a74154257842932f Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 8 Nov 2025 13:33:18 +0000 Subject: [PATCH 01/83] Disable other envs to save CI build time --- platformio.ini | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/platformio.ini b/platformio.ini index 90a6f2a0d3..76af745bfb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -10,21 +10,22 @@ # ------------------------------------------------------------------------------ # CI/release binaries -default_envs = nodemcuv2 - esp8266_2m - esp01_1m_full - nodemcuv2_160 - esp8266_2m_160 - esp01_1m_full_160 - nodemcuv2_compat - esp8266_2m_compat - esp01_1m_full_compat - esp32dev - esp32dev_debug - esp32_eth - esp32_wrover +default_envs = + ;nodemcuv2 + ;esp8266_2m + ;esp01_1m_full + ;nodemcuv2_160 + ;esp8266_2m_160 + ;esp01_1m_full_160 + ;nodemcuv2_compat + ;esp8266_2m_compat + ;esp01_1m_full_compat + ;esp32dev + ;esp32dev_debug + ;esp32_eth + ;esp32_wrover ; lolin_s2_mini ;; TODO: disabled NeoEsp32RmtMethodIsr - esp32c3dev + ;esp32c3dev ; esp32s3dev_16MB_opi ;; TODO: disabled NeoEsp32RmtMethodIsr ; esp32s3dev_8MB_opi ;; TODO: disabled NeoEsp32RmtMethodIsr ;esp32s3_4M_qspi ;; TODO: disabled NeoEsp32RmtMethodIsr From 0f1055826b92add05cef8ecf389c584bc6bacfcb Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 13 Jun 2024 16:51:07 +0200 Subject: [PATCH 02/83] ESP32-C6 buildenv due to Arduino 3.0.1, a few updated libraries are required: * Tasmota Platform - official platfomio lacks arduino support for C6 * FastLED (latest + C6 build patches) * AsyncTCP (latest + C6 build patches) * AsyncWebServer (latest + C6 build patches) * NeoPixelBus (lastest) --- platformio.ini | 72 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 76af745bfb..8b3e37fad7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -161,10 +161,12 @@ upload_speed = 115200 # ------------------------------------------------------------------------------ lib_compat_mode = strict lib_deps = - fastled/FastLED @ 3.10.1 + ; fastled/FastLED @ 3.10.1 + https://github.com/netmindz/FastLED.git#ESP32-C6 ;; patched version needed for -C6 ; IRremoteESP8266 @ 2.8.2 makuna/NeoPixelBus @ 2.8.3 - https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.2 + ; https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.2 + https://github.com/softhack007/ESPAsyncWebServer.git#ESP32-C6 ;; patched version needed for -C6 marvinroger/AsyncMqttClient @ 0.9.0 # for I2C interface ;Wire @@ -342,6 +344,72 @@ lib_deps = board_build.partitions = ${esp32.default_partitions} ;; default partioning for 4MB Flash - can be overridden in build envs board_build.flash_mode = qio + +[esp32c6] +;; generic definitions for all ESP32-C6 boards +platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.06.10/platform-espressif32.zip +platform_packages = +;;platform_packages = +;; framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.1 +;; framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-arduino-libs-3.0.1.zip + +board = esp32-c6-devkitm-1 +build_flags = -g + -DARDUINO_ARCH_ESP32 + -DARDUINO_ARCH_ESP32C6 + -DCONFIG_IDF_TARGET_ESP32C6=1 + -D CONFIG_ASYNC_TCP_USE_WDT=0 + -DCO + -DARDUINO_USB_MODE=1 ;; this flag is mandatory for ESP32-C3 + ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: + ;; ARDUINO_USB_CDC_ON_BOOT +lib_deps = + ;;https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 + https://github.com/softhack007/AsyncTCP.git#ESP32-C6 ;; patched version needed for -C6 + makuna/NeoPixelBus @ 2.8.0 ;; latest version neeeded for -C6 + ${env.lib_deps} + + +[env:esp32c6dev_8MB] +;; ESP32-C6 "devkit C" with 8MB flash +extends = esp32c6 +platform = ${esp32c6.platform} +platform_packages = ${esp32c6.platform_packages} +framework = arduino +board = esp32-c6-devkitc-1 + +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} ${esp32c6.build_flags} -D WLED_RELEASE_NAME=ESP32-C6_8MB + -Wno-volatile -Wno-deprecated-declarations ;; silence compiler warnings + -Wno-cpp ;; silence '#pragma warning' messages + -D WLED_WATCHDOG_TIMEOUT=0 + ;; -DLOLIN_WIFI_FIX ; might be needed on "-C6 mini" + ;;-DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB + -DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip + -D WLED_DISABLE_INFRARED ;; library not not compatible with -C6 + -D WLED_DISABLE_ESPNOW ;; not sure if this will work + -D WLED_DISABLE_ALEXA ;; compile errors + -D WLED_DISABLE_WEBSOCKETS ;; not sure if this will work (hacks needed in asyncWebserver) +upload_speed = 460800 +lib_deps = ${esp32c6.lib_deps} +lib_ignore = + IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation + +board_build.partitions = ${esp32.large_partitions} +board_build.f_flash = 80000000L +board_build.flash_mode = qio +board_build.arduino.memory_type = qio_qspi +monitor_filters = esp32_exception_decoder + +[env:esp32c6dev_4MB] +;; ESP32-C6 "devkit M" with 4MB flash +extends = env:esp32c6dev_8MB +board = esp32-c6-devkitm-1 +board_build.partitions = ${esp32.default_partitions} +build_unflags = ${env:esp32c6dev_8MB.build_unflags} -D WLED_RELEASE_NAME=ESP32-C6_8MB +build_flags = ${env:esp32c6dev_8MB.build_flags} -D WLED_RELEASE_NAME=ESP32-C6_4MB + + [esp32s3] ;; generic definitions for all ESP32-S3 boards platform = ${esp32_idf_V5.platform} From cf195af7c8a6bf41f1c617d5936b3c626e1c0094 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 8 Nov 2025 13:54:39 +0000 Subject: [PATCH 03/83] build only esp32c6dev_4MB --- platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio.ini b/platformio.ini index 8b3e37fad7..82667b0087 100644 --- a/platformio.ini +++ b/platformio.ini @@ -29,6 +29,7 @@ default_envs = ; esp32s3dev_16MB_opi ;; TODO: disabled NeoEsp32RmtMethodIsr ; esp32s3dev_8MB_opi ;; TODO: disabled NeoEsp32RmtMethodIsr ;esp32s3_4M_qspi ;; TODO: disabled NeoEsp32RmtMethodIsr + esp32c6dev_4MB ; usermods src_dir = ./wled00 From db65e30ad5b711313b2780bf3978c87a1c318ba7 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 8 Nov 2025 14:02:47 +0000 Subject: [PATCH 04/83] use esp32_idf_V5.platform --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 82667b0087..cf6cd38f0a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -348,7 +348,7 @@ board_build.flash_mode = qio [esp32c6] ;; generic definitions for all ESP32-C6 boards -platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.06.10/platform-espressif32.zip +platform = ${esp32_idf_V5.platform} platform_packages = ;;platform_packages = ;; framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.1 From fa5aa586ecbc3951b1b3461d20d1d943e1cb378e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 13 Jun 2024 19:10:15 +0200 Subject: [PATCH 05/83] Update platformio.ini * more debug output * added my own fork of FastLED ( looks like more bugs to solve ....) --- platformio.ini | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index cf6cd38f0a..4fb68dd529 100644 --- a/platformio.ini +++ b/platformio.ini @@ -163,7 +163,7 @@ upload_speed = 115200 lib_compat_mode = strict lib_deps = ; fastled/FastLED @ 3.10.1 - https://github.com/netmindz/FastLED.git#ESP32-C6 ;; patched version needed for -C6 + https://github.com/softhack007/FastLED.git#ESP32-C6 ;; patched version needed for -C6 ; IRremoteESP8266 @ 2.8.2 makuna/NeoPixelBus @ 2.8.3 ; https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.2 @@ -380,9 +380,13 @@ framework = arduino board = esp32-c6-devkitc-1 build_unflags = ${common.build_unflags} + -D CORE_DEBUG_LEVEL=0 + -D NDEBUG build_flags = ${common.build_flags} ${esp32c6.build_flags} -D WLED_RELEASE_NAME=ESP32-C6_8MB -Wno-volatile -Wno-deprecated-declarations ;; silence compiler warnings -Wno-cpp ;; silence '#pragma warning' messages + -D DEBUG -g3 -ggdb + -D CORE_DEBUG_LEVEL=4 -D WLED_WATCHDOG_TIMEOUT=0 ;; -DLOLIN_WIFI_FIX ; might be needed on "-C6 mini" ;;-DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB From 1bc63cac6105180fa447d164c56f7e5d1cf8b52c Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 1 Dec 2025 01:37:57 +0100 Subject: [PATCH 06/83] use the same lib_deps as the "main V5" branch --- platformio.ini | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/platformio.ini b/platformio.ini index d88801caca..00d6b33fc7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -376,7 +376,7 @@ board_build.flash_mode = qio [esp32c6] ;; generic definitions for all ESP32-C6 boards platform = ${esp32_idf_V5.platform} -platform_packages = +platform_packages = ${esp32_idf_V5.platform_packages} ;;platform_packages = ;; framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.1 ;; framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-arduino-libs-3.0.1.zip @@ -391,11 +391,12 @@ build_flags = -g -DARDUINO_USB_MODE=1 ;; this flag is mandatory for ESP32-C3 ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: ;; ARDUINO_USB_CDC_ON_BOOT + ${esp32_idf_V5.build_flags} lib_deps = ;;https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 - https://github.com/softhack007/AsyncTCP.git#ESP32-C6 ;; patched version needed for -C6 - makuna/NeoPixelBus @ 2.8.0 ;; latest version neeeded for -C6 - ${env.lib_deps} + ; https://github.com/softhack007/AsyncTCP.git#ESP32-C6 ;; patched version needed for -C6 ;; softhack007 use default V5 libraries + ; makuna/NeoPixelBus @ 2.8.0 ;; latest version neeeded for -C6 ;; softhack007 use default V5 libraries + ${esp32_idf_V5.lib_deps} [env:esp32c6dev_8MB] From 6961059220365a763ffb8631f2017fe3acdee55a Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 1 Dec 2025 01:58:12 +0100 Subject: [PATCH 07/83] minor changes for consistency with other build envs --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 00d6b33fc7..16b1f2dd9c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -381,14 +381,14 @@ platform_packages = ${esp32_idf_V5.platform_packages} ;; framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.1 ;; framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-arduino-libs-3.0.1.zip -board = esp32-c6-devkitm-1 +;; board = esp32-c6-devkitm-1 ;; board must be defined in the lower-level [env:*] buildenvs for C6-based boards build_flags = -g -DARDUINO_ARCH_ESP32 -DARDUINO_ARCH_ESP32C6 -DCONFIG_IDF_TARGET_ESP32C6=1 -D CONFIG_ASYNC_TCP_USE_WDT=0 -DCO - -DARDUINO_USB_MODE=1 ;; this flag is mandatory for ESP32-C3 + -DARDUINO_USB_MODE=1 ;; this flag is - most likely - mandatory for ESP32-C6 ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: ;; ARDUINO_USB_CDC_ON_BOOT ${esp32_idf_V5.build_flags} From b2d659120e5ef3855c5acbe62d90a0e25cab8f39 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 1 Dec 2025 15:56:57 +0100 Subject: [PATCH 08/83] disable QuickEspNow - seems incompatible with -C6 also disabled some core debug flags --- platformio.ini | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/platformio.ini b/platformio.ini index f0b81ef6a9..747c5c7a3a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -408,13 +408,13 @@ framework = arduino board = esp32-c6-devkitc-1 build_unflags = ${common.build_unflags} - -D CORE_DEBUG_LEVEL=0 - -D NDEBUG + ;;-D CORE_DEBUG_LEVEL=0 + ;;-D NDEBUG build_flags = ${common.build_flags} ${esp32c6.build_flags} -D WLED_RELEASE_NAME=ESP32-C6_8MB -Wno-volatile -Wno-deprecated-declarations ;; silence compiler warnings -Wno-cpp ;; silence '#pragma warning' messages - -D DEBUG -g3 -ggdb - -D CORE_DEBUG_LEVEL=4 + ;;-D DEBUG -g3 -ggdb + ;;-D CORE_DEBUG_LEVEL=4 -D WLED_WATCHDOG_TIMEOUT=0 ;; -DLOLIN_WIFI_FIX ; might be needed on "-C6 mini" ;;-DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB @@ -423,10 +423,12 @@ build_flags = ${common.build_flags} ${esp32c6.build_flags} -D WLED_RELEASE_NAME= -D WLED_DISABLE_ESPNOW ;; not sure if this will work -D WLED_DISABLE_ALEXA ;; compile errors -D WLED_DISABLE_WEBSOCKETS ;; not sure if this will work (hacks needed in asyncWebserver) + -D WLED_DISABLE_ESPNOW ;; ToDO: temporarily disabled, until we find a solution for esp-now build errors with -C6 upload_speed = 460800 lib_deps = ${esp32c6.lib_deps} lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation + QuickEspNow ; ToDO: disabled until we find a compatible version board_build.partitions = ${esp32.large_partitions} board_build.f_flash = 80000000L From 62ca377060541dcc6539ce44cd6cfbe494c1a675 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 1 Dec 2025 16:29:51 +0100 Subject: [PATCH 09/83] remove special FASTLED_NO_FASTLED hack this was a temporary hack needed one year ago; FastLED should be compatible with -C6 now. --- platformio.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platformio.ini b/platformio.ini index 747c5c7a3a..a037f30ade 100644 --- a/platformio.ini +++ b/platformio.ini @@ -163,9 +163,9 @@ upload_speed = 115200 # ------------------------------------------------------------------------------ lib_compat_mode = strict lib_deps = - ; fastled/FastLED @ 3.10.1 - https://github.com/softhack007/FastLED.git#ESP32-C6 ;; patched version needed for -C6 -; IRremoteESP8266 @ 2.8.2 + fastled/FastLED @ 3.10.1 + ;; https://github.com/softhack007/FastLED.git#ESP32-C6 ;; patched version for -C6 + ; IRremoteESP8266 @ 2.8.2 https://github.com/netmindz/NeoPixelBus.git#2f05279a4a9f56875fb85482e6ec4e17078accc3 ;; CORE3 with log fix https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.2 marvinroger/AsyncMqttClient @ 0.9.0 From 70235450e8e175e025dbb9abaf984161961c64bd Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 1 Dec 2025 17:03:44 +0100 Subject: [PATCH 10/83] treat C6 similar to C3 trying to reduce compile errors in bus_wrapper.h ... plus some preparation for P4 support --- wled00/bus_wrapper.h | 24 ++++++++++++------------ wled00/const.h | 7 ++++--- wled00/wled.h | 10 +++++----- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index 0bc3cc4ec5..c1dbcef720 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -245,7 +245,7 @@ typedef NeoEsp32I2s0Apa106Method X1Apa106Method; typedef NeoEsp32I2s0Ws2805Method X1Ws2805Method; typedef NeoEsp32I2s0Tm1914Method X1Tm1914Method; -#elif !defined(CONFIG_IDF_TARGET_ESP32C3) +#elif !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) // regular ESP32 will use I2S1 typedef NeoEsp32I2s1Ws2812xMethod X1Ws2812xMethod; typedef NeoEsp32I2s1Sk6812Method X1Sk6812Method; @@ -461,7 +461,7 @@ 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 CONFIG_IDF_TARGET_ESP32C3 + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) 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; @@ -493,7 +493,7 @@ class PolyBus { static void* create(uint8_t busType, uint8_t* pins, uint16_t len, uint8_t channel) { // NOTE: "channel" is only used on ESP32 (and its variants) for RMT channel allocation - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) if (_useParallelI2S && (channel >= 8)) { // Parallel I2S channels are to be used first, so subtract 8 to get the RMT channel number channel -= 8; @@ -573,7 +573,7 @@ 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 CONFIG_IDF_TARGET_ESP32C3 + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) 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; @@ -672,7 +672,7 @@ 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 CONFIG_IDF_TARGET_ESP32C3 + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) 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; @@ -768,7 +768,7 @@ 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 CONFIG_IDF_TARGET_ESP32C3 + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) case I_32_I2_NEO_3: if (_useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; case I_32_I2_NEO_4: if (_useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; case I_32_I2_400_3: if (_useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; @@ -890,7 +890,7 @@ class PolyBus { case I_32_RN_TM1914_3: (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_RN_SM16825_5: (static_cast(busPtr))->SetPixelColor(pix, Rgbww80Color(col.R*257, col.G*257, col.B*257, cctWW*257, cctCW*257)); break; // I2S1 bus or paralell buses - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) case I_32_I2_NEO_3: if (_useParallelI2S) (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); else (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_I2_NEO_4: if (_useParallelI2S) (static_cast(busPtr))->SetPixelColor(pix, col); else (static_cast(busPtr))->SetPixelColor(pix, col); break; case I_32_I2_400_3: if (_useParallelI2S) (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); else (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; @@ -987,7 +987,7 @@ class PolyBus { case I_32_RN_TM1914_3: col = (static_cast(busPtr))->GetPixelColor(pix); break; case I_32_RN_SM16825_5: { Rgbww80Color c = (static_cast(busPtr))->GetPixelColor(pix); col = RGBW32(c.R/257,c.G/257,c.B/257,max(c.WW,c.CW)/257); } break; // will not return original W // I2S1 bus or paralell buses - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) case I_32_I2_NEO_3: col = (_useParallelI2S) ? (static_cast(busPtr))->GetPixelColor(pix) : (static_cast(busPtr))->GetPixelColor(pix); break; case I_32_I2_NEO_4: col = (_useParallelI2S) ? (static_cast(busPtr))->GetPixelColor(pix) : (static_cast(busPtr))->GetPixelColor(pix); break; case I_32_I2_400_3: col = (_useParallelI2S) ? (static_cast(busPtr))->GetPixelColor(pix) : (static_cast(busPtr))->GetPixelColor(pix); break; @@ -1102,7 +1102,7 @@ class PolyBus { case I_32_RN_TM1914_3: delete (static_cast(busPtr)); break; case I_32_RN_SM16825_5: delete (static_cast(busPtr)); break; // I2S1 bus or paralell buses - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) case I_32_I2_NEO_3: if (_useParallelI2S) delete (static_cast(busPtr)); else delete (static_cast(busPtr)); break; case I_32_I2_NEO_4: if (_useParallelI2S) delete (static_cast(busPtr)); else delete (static_cast(busPtr)); break; case I_32_I2_400_3: if (_useParallelI2S) delete (static_cast(busPtr)); else delete (static_cast(busPtr)); break; @@ -1199,7 +1199,7 @@ class PolyBus { case I_32_RN_TM1914_3: size = (static_cast(busPtr))->PixelsSize()*2; break; case I_32_RN_SM16825_5: size = (static_cast(busPtr))->PixelsSize()*2; break; // I2S1 bus or paralell buses (front + DMA; DMA = front * cadence, aligned to 4 bytes) - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) case I_32_I2_NEO_3: size = (_useParallelI2S) ? (static_cast(busPtr))->PixelsSize()*4 : (static_cast(busPtr))->PixelsSize()*4; break; case I_32_I2_NEO_4: size = (_useParallelI2S) ? (static_cast(busPtr))->PixelsSize()*4 : (static_cast(busPtr))->PixelsSize()*4; break; case I_32_I2_400_3: size = (_useParallelI2S) ? (static_cast(busPtr))->PixelsSize()*4 : (static_cast(busPtr))->PixelsSize()*4; break; @@ -1278,7 +1278,7 @@ class PolyBus { case I_32_RN_2805_5 : size = (size + 2*count)*2; break; // 5 channels case I_32_RN_SM16825_5: size = (size + 2*count)*2*2; break; // 16bit, 5 channels // I2S1 bus or paralell I2S1 buses (1x front, does not include DMA buffer which is front*cadence, a bit(?) more for LCD) - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) case I_32_I2_NEO_3 : // fallthrough case I_32_I2_400_3 : // fallthrough case I_32_I2_TM2_3 : // fallthrough @@ -1365,7 +1365,7 @@ class PolyBus { if (num > 4) return I_NONE; if (num > 3) offset = 1; // only one I2S0 (use last to allow Audioreactive) } - #elif defined(CONFIG_IDF_TARGET_ESP32C3) + #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) // On ESP32-C3 only the first 2 RMT channels are usable for transmitting if (num > 1) return I_NONE; //if (num > 1) offset = 1; // I2S not supported yet (only 1 I2S) diff --git a/wled00/const.h b/wled00/const.h index ac48838435..f7ac69b613 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -62,7 +62,8 @@ constexpr size_t FIXED_PALETTE_COUNT = DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_C #include "driver/ledc.h" // needed for analog/LEDC channel counts #endif #define WLED_MAX_ANALOG_CHANNELS (LEDC_CHANNEL_MAX*LEDC_SPEED_MODE_MAX) - #if defined(CONFIG_IDF_TARGET_ESP32C3) // 2 RMT, 6 LEDC, only has 1 I2S but NPB does not support it ATM + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + // 2 RMT, 6 LEDC, only has 1 I2S but NPB does not support it ATM #define WLED_MAX_DIGITAL_CHANNELS 2 //#define WLED_MAX_ANALOG_CHANNELS 6 #define WLED_MIN_VIRTUAL_BUSSES 4 // no longer used for bus creation but used to distinguish S2/S3 in UI @@ -472,7 +473,7 @@ static_assert(WLED_MAX_BUSSES <= 32, "WLED_MAX_BUSSES exceeds hard limit"); #define MAX_LEDS 1536 //can't rely on memory limit to limit this to 1536 LEDs #elif defined(CONFIG_IDF_TARGET_ESP32S2) #define MAX_LEDS 2048 //due to memory constraints S2 - #elif defined(CONFIG_IDF_TARGET_ESP32C3) + #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) #define MAX_LEDS 4096 #else #define MAX_LEDS 16384 @@ -485,7 +486,7 @@ static_assert(WLED_MAX_BUSSES <= 32, "WLED_MAX_BUSSES exceeds hard limit"); #else #if defined(ARDUINO_ARCH_ESP32S2) #define MAX_LED_MEMORY 16384 - #elif defined(ARDUINO_ARCH_ESP32C3) + #elif defined(ARDUINO_ARCH_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) #define MAX_LED_MEMORY 32768 #else #define MAX_LED_MEMORY 65536 diff --git a/wled00/wled.h b/wled00/wled.h index 79c75c10a4..9046a36557 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -154,7 +154,7 @@ #endif #ifdef WLED_ENABLE_DMX - #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) + #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) #include "src/dependencies/dmx/ESPDMX.h" #else //ESP32 #include "src/dependencies/dmx/SparkFunDMX.h" @@ -327,7 +327,7 @@ WLED_GLOBAL bool rlyOpenDrain _INIT(RLYODRAIN); #define IRTYPE 0 #endif -#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || (defined(RX) && defined(TX)) +#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32S2) || (defined(RX) && defined(TX)) // use RX/TX as set by the framework - these boards do _not_ have RX=3 and TX=1 constexpr uint8_t hardwareRX = RX; constexpr uint8_t hardwareTX = TX; @@ -388,7 +388,7 @@ WLED_GLOBAL bool noWifiSleep _INIT(false); WLED_GLOBAL bool force802_3g _INIT(false); #endif // WLED_SAVE_RAM #ifdef ARDUINO_ARCH_ESP32 - #if defined(LOLIN_WIFI_FIX) && (defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)) + #if defined(LOLIN_WIFI_FIX) && (defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)) WLED_GLOBAL uint8_t txPower _INIT(WIFI_POWER_8_5dBm); #else WLED_GLOBAL uint8_t txPower _INIT(WIFI_POWER_19_5dBm); @@ -415,7 +415,7 @@ WLED_GLOBAL byte bootPreset _INIT(0); // save preset to load WLED_GLOBAL bool useGlobalLedBuffer _INIT(false); // double buffering disabled on ESP8266 #else WLED_GLOBAL bool useGlobalLedBuffer _INIT(true); // double buffering enabled on ESP32 - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) WLED_GLOBAL bool useParallelI2S _INIT(false); // parallel I2S for ESP32 #endif #endif @@ -469,7 +469,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 - #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) + #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) WLED_GLOBAL DMXESPSerial dmx; #else //ESP32 WLED_GLOBAL SparkFunDMX dmx; From 1de36ca0da883493d521eb908a4715328b5ac5e4 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 1 Dec 2025 17:15:04 +0100 Subject: [PATCH 11/83] more "C6 is like C3" adjustments --- wled00/FX_fcn.cpp | 4 ++-- wled00/set.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index f2a474a486..47ef23cd40 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1161,7 +1161,7 @@ void WS2812FX::finalizeInit() { BusManager::removeAll(); unsigned digitalCount = 0; - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) // 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; unsigned busType = 0; @@ -1191,7 +1191,7 @@ void WS2812FX::finalizeInit() { unsigned memB = bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount++ : 0); // does not include DMA/RMT buffer mem += memB; // estimate maximum I2S memory usage (only relevant for digital non-2pin busses) - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(ESP8266) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) && !defined(ESP8266) #if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S3) const bool usesI2S = ((useParallelI2S && digitalCount <= 8) || (!useParallelI2S && digitalCount == 1)); #elif defined(CONFIG_IDF_TARGET_ESP32S2) diff --git a/wled00/set.cpp b/wled00/set.cpp index 087e9b39f2..b1831cf9e7 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -155,7 +155,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) Bus::setCCTBlend(cctBlending); Bus::setGlobalAWMode(request->arg(F("AW")).toInt()); strip.setTargetFps(request->arg(F("FR")).toInt()); - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) useParallelI2S = request->hasArg(F("PR")); #endif From 2df4c58de89950d33d8fe15d11fd44d83081612b Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 1 Dec 2025 17:22:16 +0100 Subject: [PATCH 12/83] disable touch button code on C6 similar to C3 --- wled00/button.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/button.cpp b/wled00/button.cpp index 8ab2363acb..651f12cf18 100644 --- a/wled00/button.cpp +++ b/wled00/button.cpp @@ -109,7 +109,7 @@ bool isButtonPressed(uint8_t b) break; case BTN_TYPE_TOUCH: case BTN_TYPE_TOUCH_SWITCH: - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) #ifdef SOC_TOUCH_VERSION_2 //ESP32 S2 and S3 provide a function to check touch state (state is updated in interrupt) if (touchInterruptGetLastStatus(pin)) return true; #else From 3f441f0605684dd4b226f46d704ab7fda5ea1083 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 1 Dec 2025 17:31:41 +0100 Subject: [PATCH 13/83] guess what ... more "C6 is like C3" ifdefs needed --- wled00/cfg.cpp | 4 ++-- wled00/json.cpp | 2 +- wled00/util.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 47ba152c96..2bc3fe4503 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -165,7 +165,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { uint8_t cctBlending = hw_led[F("cb")] | Bus::getCCTBlend(); Bus::setCCTBlend(cctBlending); strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) CJSON(useParallelI2S, hw_led[F("prl")]); #endif @@ -933,7 +933,7 @@ void serializeConfig(JsonObject root) { hw_led[F("cb")] = Bus::getCCTBlend(); hw_led["fps"] = strip.getTargetFps(); hw_led[F("rgbwm")] = Bus::getGlobalAWMode(); // global auto white mode override - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) hw_led[F("prl")] = BusManager::hasParallelOutput(); #endif diff --git a/wled00/json.cpp b/wled00/json.cpp index 35fde73c69..22ebcf7b03 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -811,7 +811,7 @@ void serializeInfo(JsonObject root) wifi_info[F("txPower")] = (int) WiFi.getTxPower(); wifi_info[F("sleep")] = (bool) WiFi.getSleep(); #endif - #if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) + #if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) root[F("arch")] = "esp32"; #else root[F("arch")] = ESP.getChipModel(); diff --git a/wled00/util.cpp b/wled00/util.cpp index 391e2873fb..7165006dda 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -633,7 +633,7 @@ int32_t hw_random(int32_t lowerlimit, int32_t upperlimit) { // PSRAM compile time checks to provide info for misconfigured env #if defined(BOARD_HAS_PSRAM) - #if defined(IDF_TARGET_ESP32C3) || defined(ESP8266) + #if defined(IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(ESP8266) #error "ESP32-C3 and ESP8266 with PSRAM is not supported, please remove BOARD_HAS_PSRAM definition" #else #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) // PSRAM fix only needed for classic esp32 @@ -694,7 +694,7 @@ static void *validateFreeHeap(void *buffer) { void *d_malloc(size_t size) { void *buffer; - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) // the newer ESP32 variants have byte-accessible fast RTC memory that can be used as heap, access speed is on-par with DRAM // the system does prefer normal DRAM until full, since free RTC memory is ~7.5k only, its below the minimum heap threshold and needs to be allocated explicitly // use RTC RAM for small allocations to improve fragmentation or if DRAM is running low From c73935dd369ed0e25af9ecc041e6000d29bc346a Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 1 Dec 2025 17:36:33 +0100 Subject: [PATCH 14/83] small fix missing || --- wled00/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/util.cpp b/wled00/util.cpp index 7165006dda..8b592050b7 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -694,7 +694,7 @@ static void *validateFreeHeap(void *buffer) { void *d_malloc(size_t size) { void *buffer; - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) // the newer ESP32 variants have byte-accessible fast RTC memory that can be used as heap, access speed is on-par with DRAM // the system does prefer normal DRAM until full, since free RTC memory is ~7.5k only, its below the minimum heap threshold and needs to be allocated explicitly // use RTC RAM for small allocations to improve fragmentation or if DRAM is running low From c096c5bb8f9e84f3558b47d6894bef0bc60091ef Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 1 Dec 2025 17:53:04 +0100 Subject: [PATCH 15/83] fix for old-style WLED_RELEASE_NAME --- platformio.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platformio.ini b/platformio.ini index a037f30ade..4e44b1e814 100644 --- a/platformio.ini +++ b/platformio.ini @@ -410,7 +410,7 @@ board = esp32-c6-devkitc-1 build_unflags = ${common.build_unflags} ;;-D CORE_DEBUG_LEVEL=0 ;;-D NDEBUG -build_flags = ${common.build_flags} ${esp32c6.build_flags} -D WLED_RELEASE_NAME=ESP32-C6_8MB +build_flags = ${common.build_flags} ${esp32c6.build_flags} -D WLED_RELEASE_NAME=\"ESP32-C6_8MB\" -Wno-volatile -Wno-deprecated-declarations ;; silence compiler warnings -Wno-cpp ;; silence '#pragma warning' messages ;;-D DEBUG -g3 -ggdb @@ -441,8 +441,8 @@ monitor_filters = esp32_exception_decoder extends = env:esp32c6dev_8MB board = esp32-c6-devkitm-1 board_build.partitions = ${esp32.default_partitions} -build_unflags = ${env:esp32c6dev_8MB.build_unflags} -D WLED_RELEASE_NAME=ESP32-C6_8MB -build_flags = ${env:esp32c6dev_8MB.build_flags} -D WLED_RELEASE_NAME=ESP32-C6_4MB +build_unflags = ${env:esp32c6dev_8MB.build_unflags} -D WLED_RELEASE_NAME=\"ESP32-C6_8MB\" +build_flags = ${env:esp32c6dev_8MB.build_flags} -D WLED_RELEASE_NAME=\"ESP32-C6_4MB\" [esp32s3] From 9f12301128850455320716f3abd980097fb63bab Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 1 Dec 2025 23:59:50 +0100 Subject: [PATCH 16/83] esp32c6 inherits build_unflags and lib_ignore from V5 buildenv --- platformio.ini | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 1b3aca518b..70e88defe5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -389,6 +389,7 @@ platform_packages = ${esp32_idf_V5.platform_packages} ;; framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-arduino-libs-3.0.1.zip ;; board = esp32-c6-devkitm-1 ;; board must be defined in the lower-level [env:*] buildenvs for C6-based boards +build_unflags = ${esp32_idf_V5.build_unflags} build_flags = -g -DARDUINO_ARCH_ESP32 -DARDUINO_ARCH_ESP32C6 @@ -404,6 +405,7 @@ lib_deps = ; https://github.com/softhack007/AsyncTCP.git#ESP32-C6 ;; patched version needed for -C6 ;; softhack007 use default V5 libraries ; makuna/NeoPixelBus @ 2.8.0 ;; latest version neeeded for -C6 ;; softhack007 use default V5 libraries ${esp32_idf_V5.lib_deps} +lib_ignore = ${esp32_idf_V5.lib_ignore} [env:esp32c6dev_8MB] @@ -414,7 +416,7 @@ platform_packages = ${esp32c6.platform_packages} framework = arduino board = esp32-c6-devkitc-1 -build_unflags = ${common.build_unflags} +build_unflags = ${esp32c6.build_unflags} ;;-D CORE_DEBUG_LEVEL=0 ;;-D NDEBUG build_flags = ${common.build_flags} ${esp32c6.build_flags} -D WLED_RELEASE_NAME=\"ESP32-C6_8MB\" @@ -433,7 +435,7 @@ build_flags = ${common.build_flags} ${esp32c6.build_flags} -D WLED_RELEASE_NAME= -D WLED_DISABLE_ESPNOW ;; ToDO: temporarily disabled, until we find a solution for esp-now build errors with -C6 upload_speed = 460800 lib_deps = ${esp32c6.lib_deps} -lib_ignore = +lib_ignore = ${esp32c6.lib_ignore} IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation QuickEspNow ; ToDO: disabled until we find a compatible version From f88fd073a3d7a13e8004b786f910911c7e43c831 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 2 Dec 2025 00:00:31 +0100 Subject: [PATCH 17/83] temporary workaround for #5145 --- pio-scripts/set_metadata.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pio-scripts/set_metadata.py b/pio-scripts/set_metadata.py index 7c8c223038..f7e7aa1a02 100644 --- a/pio-scripts/set_metadata.py +++ b/pio-scripts/set_metadata.py @@ -100,15 +100,16 @@ def add_wled_metadata_flags(env, node): if not has_def(cdefs, "WLED_REPO"): repo = get_github_repo() if repo: + print(f"repo = {repo}") cdefs.append(("WLED_REPO", f"\\\"{repo}\\\"")) cdefs.append(("WLED_VERSION", WLED_VERSION)) - # This transforms the node in to a Builder; it cannot be modified again - return env.Object( - node, - CPPDEFINES=cdefs - ) + # Return the node unmodified - middleware should not create new build targets + print(f"version = {WLED_VERSION}") + # Instead, modify the environment's CPPDEFINES before the file is compiled + env["CPPDEFINES"] = cdefs + return node env.AddBuildMiddleware( add_wled_metadata_flags, From d3e92f26c05eea238d503bd1fe3e6d067b82b602 Mon Sep 17 00:00:00 2001 From: Karan Vijayakumar Date: Thu, 27 Nov 2025 02:39:07 +0900 Subject: [PATCH 18/83] Fix ESP32-C6 runtime crash and improve compatibility - Fix IPAddress comparison with 0U causing null pointer dereference in initConnection() - Add bounds checking for selectedWiFi index before array access - Add ESP32-C6 conditional for touch sensor exclusion (C6 has no capacitive touch) - Add deferResponse() wrapper for C6's patched ESPAsyncWebServer - Add early return in esp32RMTInvertIdle() for C6 (no RMT support) - Add ESP32-C6 BitBang bus creation in bus_wrapper.h - Update platformio.ini with proper C6 build flags and dependencies - Use patched FastLED, AsyncTCP, and ESPAsyncWebServer forks for C6 support --- .vscode/extensions.json | 3 +-- wled00/bus_manager.cpp | 5 +++++ wled00/fcn_declare.h | 11 +++++++++++ wled00/json.cpp | 2 +- wled00/network.cpp | 4 ++-- wled00/set.cpp | 2 +- wled00/wled.h | 5 +++++ wled00/wled_server.cpp | 2 +- 8 files changed, 27 insertions(+), 7 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 080e70d08b..8057bc70a7 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,6 @@ { - // See http://go.microsoft.com/fwlink/?LinkId=827846 - // for the documentation about the extensions.json format "recommendations": [ + "pioarduino.pioarduino-ide", "platformio.platformio-ide" ], "unwantedRecommendations": [ diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 60925e1495..e2e28cebc0 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -1242,6 +1242,10 @@ void BusManager::removeAll() { // If enabled, RMT idle level is set to HIGH when off // to prevent leakage current when using an N-channel MOSFET to toggle LED power void BusManager::esp32RMTInvertIdle() { +#if defined(CONFIG_IDF_TARGET_ESP32C6) + // ESP32-C6 uses BitBang method, not RMT - nothing to do here + return; +#else bool idle_out; unsigned rmt = 0; unsigned u = 0; @@ -1272,6 +1276,7 @@ void BusManager::esp32RMTInvertIdle() { rmt_set_idle_level(ch, idle_out, lvl); u++; } +#endif } #endif diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index d950b16655..5bea2b5c36 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -553,6 +553,17 @@ void serveJsonError(AsyncWebServerRequest* request, uint16_t code, uint16_t erro void serveSettings(AsyncWebServerRequest* request, bool post = false); void serveSettingsJS(AsyncWebServerRequest* request); +// ESP32-C6 compatibility: deferResponse not available in patched ESPAsyncWebServer fork +// Use this inline function which falls back to sending a 503 error +inline void deferResponse(AsyncWebServerRequest* request) { +#if defined(CONFIG_IDF_TARGET_ESP32C6) + // deferResponse not available, send 503 Service Unavailable instead + request->send(503, F("text/plain"), F("Server busy, try again")); +#else + request->deferResponse(); +#endif +} + //ws.cpp void handleWs(); void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len); diff --git a/wled00/json.cpp b/wled00/json.cpp index 22ebcf7b03..76de82513e 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -1135,7 +1135,7 @@ void serveJson(AsyncWebServerRequest* request) } if (!requestJSONBufferLock(17)) { - request->deferResponse(); + deferResponse(request); return; } // releaseJSONBufferLock() will be called when "response" is destroyed (from AsyncWebServer) diff --git a/wled00/network.cpp b/wled00/network.cpp index 174df1c631..60a6162b5b 100644 --- a/wled00/network.cpp +++ b/wled00/network.cpp @@ -296,14 +296,14 @@ int findWiFi(bool doScan) { } else if (status >= 0) { // status contains number of found networks (including duplicate SSIDs with different BSSID) DEBUG_PRINTF_P(PSTR("WiFi: Found %d SSIDs. @ %lus\n"), status, millis()/1000); int rssi = -9999; - int selected = selectedWiFi; + int selected = (selectedWiFi < multiWiFi.size()) ? selectedWiFi : 0; // ensure valid starting index for (int o = 0; o < status; o++) { DEBUG_PRINTF_P(PSTR(" SSID: %s (BSSID: %s) RSSI: %ddB\n"), WiFi.SSID(o).c_str(), WiFi.BSSIDstr(o).c_str(), WiFi.RSSI(o)); for (unsigned n = 0; n < multiWiFi.size(); n++) if (!strcmp(WiFi.SSID(o).c_str(), multiWiFi[n].clientSSID)) { bool foundBSSID = memcmp(multiWiFi[n].bssid, WiFi.BSSID(o), 6) == 0; // find the WiFi with the strongest signal (but keep priority of entry if signal difference is not big) - if (foundBSSID || (n < selected && WiFi.RSSI(o) > rssi-10) || WiFi.RSSI(o) > rssi) { + if (foundBSSID || (n < (unsigned)selected && WiFi.RSSI(o) > rssi-10) || WiFi.RSSI(o) > rssi) { rssi = foundBSSID ? 0 : WiFi.RSSI(o); // RSSI is only ever negative selected = n; } diff --git a/wled00/set.cpp b/wled00/set.cpp index b1831cf9e7..bf02e6de3c 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -655,7 +655,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) if (subPage == SUBPAGE_UM) { if (!requestJSONBufferLock(5)) { - request->deferResponse(); + deferResponse(request); return; } diff --git a/wled00/wled.h b/wled00/wled.h index 9046a36557..eec373d3a9 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -921,7 +921,12 @@ WLED_GLOBAL bool ledStatusState _INIT(false); // the current LED state #endif // server library objects +#if defined(CONFIG_IDF_TARGET_ESP32C6) +// ESP32-C6 uses patched ESPAsyncWebServer fork with simpler constructor +WLED_GLOBAL AsyncWebServer server _INIT_N(((80))); +#else WLED_GLOBAL AsyncWebServer server _INIT_N(((80, {0, WLED_REQUEST_MAX_QUEUE, WLED_REQUEST_MIN_HEAP, WLED_REQUEST_HEAP_USAGE}))); +#endif #ifdef WLED_ENABLE_WEBSOCKETS WLED_GLOBAL AsyncWebSocket ws _INIT_N((("/ws"))); #endif diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index 7a455453cd..fbcebef9c5 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -393,7 +393,7 @@ void initServer() bool isConfig = false; if (!requestJSONBufferLock(14)) { - request->deferResponse(); + deferResponse(request); return; } From ec44fd167a74a42bfab767c1c42a952b00bb9727 Mon Sep 17 00:00:00 2001 From: Karan Vijayakumar Date: Thu, 27 Nov 2025 03:10:39 +0900 Subject: [PATCH 19/83] Add ESP32-C6 pin validation for strapping and USB-JTAG pins --- wled00/pin_manager.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index 709263e1a3..729e845039 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -232,6 +232,13 @@ bool PinManager::isPinOk(byte gpio, bool output) if (gpio > 21 && gpio < 33) return false; // 22 to 32: not connected + SPI FLASH // JTAG: GPIO39-42 are usually used for inline debugging // GPIO46 is input only and pulled down + #elif defined(CONFIG_IDF_TARGET_ESP32C6) + // strapping pins: 8, 9, 15 + // GPIO 0-23 directly usable, 24-30 are for SPI flash + if (gpio > 23 && gpio < 31) return false; // 24-30 SPI FLASH + #if ARDUINO_USB_CDC_ON_BOOT == 1 || ARDUINO_USB_DFU_ON_BOOT == 1 + if (gpio == 12 || gpio == 13) return false; // 12-13 USB-JTAG + #endif #else if ((strncmp_P(PSTR("ESP32-U4WDH"), ESP.getChipModel(), 11) == 0) || // this is the correct identifier, but.... From c92abb8dfcfc957d868393b0c8d8fe2891ffde8e Mon Sep 17 00:00:00 2001 From: Karan Vijayakumar Date: Sat, 29 Nov 2025 21:09:08 +0900 Subject: [PATCH 20/83] Address PR comments: cleanup and safety improvements - Revert VSCode extension changes - Remove unused QuickDebug dependency - Revert GifDecoder hash to short form - Harden selectedWiFi index calculation in network.cpp --- wled00/network.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/network.cpp b/wled00/network.cpp index 60a6162b5b..4602faedcc 100644 --- a/wled00/network.cpp +++ b/wled00/network.cpp @@ -296,14 +296,14 @@ int findWiFi(bool doScan) { } else if (status >= 0) { // status contains number of found networks (including duplicate SSIDs with different BSSID) DEBUG_PRINTF_P(PSTR("WiFi: Found %d SSIDs. @ %lus\n"), status, millis()/1000); int rssi = -9999; - int selected = (selectedWiFi < multiWiFi.size()) ? selectedWiFi : 0; // ensure valid starting index + size_t selected = (static_cast(selectedWiFi) < multiWiFi.size()) ? static_cast(selectedWiFi) : 0; // ensure valid starting index for (int o = 0; o < status; o++) { DEBUG_PRINTF_P(PSTR(" SSID: %s (BSSID: %s) RSSI: %ddB\n"), WiFi.SSID(o).c_str(), WiFi.BSSIDstr(o).c_str(), WiFi.RSSI(o)); for (unsigned n = 0; n < multiWiFi.size(); n++) if (!strcmp(WiFi.SSID(o).c_str(), multiWiFi[n].clientSSID)) { bool foundBSSID = memcmp(multiWiFi[n].bssid, WiFi.BSSID(o), 6) == 0; // find the WiFi with the strongest signal (but keep priority of entry if signal difference is not big) - if (foundBSSID || (n < (unsigned)selected && WiFi.RSSI(o) > rssi-10) || WiFi.RSSI(o) > rssi) { + if (foundBSSID || (n < selected && WiFi.RSSI(o) > rssi-10) || WiFi.RSSI(o) > rssi) { rssi = foundBSSID ? 0 : WiFi.RSSI(o); // RSSI is only ever negative selected = n; } From e4d6848d1b3b5776d2610d6c12b23911d1a05335 Mon Sep 17 00:00:00 2001 From: Karan Vijayakumar Date: Sat, 29 Nov 2025 21:10:41 +0900 Subject: [PATCH 21/83] Revert .vscode/extensions.json --- .vscode/extensions.json | 1 - 1 file changed, 1 deletion(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 8057bc70a7..bca82dcaae 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,6 +1,5 @@ { "recommendations": [ - "pioarduino.pioarduino-ide", "platformio.platformio-ide" ], "unwantedRecommendations": [ From d2c13135b60951b7ec131ac05bda587fdc939604 Mon Sep 17 00:00:00 2001 From: Karan Vijayakumar Date: Sat, 29 Nov 2025 21:18:45 +0900 Subject: [PATCH 22/83] Fully revert .vscode/extensions.json to base branch --- .vscode/extensions.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index bca82dcaae..080e70d08b 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,4 +1,6 @@ { + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format "recommendations": [ "platformio.platformio-ide" ], From 4ebbd866c497512453eff74e0e68a33a47c38523 Mon Sep 17 00:00:00 2001 From: Karan Vijayakumar Date: Sat, 29 Nov 2025 21:28:31 +0900 Subject: [PATCH 23/83] Use Aircoookie/ESPAsyncWebServer v2.4.2 instead of softhack007 fork - Upgrade to newer ESPAsyncWebServer that has deferResponse() and queue features - Remove deferResponse() wrapper function from fcn_declare.h - Remove AsyncWebServer constructor conditional from wled.h - Revert json.cpp, set.cpp, wled_server.cpp to use native deferResponse() This addresses @willmmiles feedback to use the proper library instead of workarounds. --- wled00/fcn_declare.h | 11 ----------- wled00/json.cpp | 2 +- wled00/set.cpp | 2 +- wled00/wled.h | 5 ----- wled00/wled_server.cpp | 2 +- 5 files changed, 3 insertions(+), 19 deletions(-) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 5bea2b5c36..d950b16655 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -553,17 +553,6 @@ void serveJsonError(AsyncWebServerRequest* request, uint16_t code, uint16_t erro void serveSettings(AsyncWebServerRequest* request, bool post = false); void serveSettingsJS(AsyncWebServerRequest* request); -// ESP32-C6 compatibility: deferResponse not available in patched ESPAsyncWebServer fork -// Use this inline function which falls back to sending a 503 error -inline void deferResponse(AsyncWebServerRequest* request) { -#if defined(CONFIG_IDF_TARGET_ESP32C6) - // deferResponse not available, send 503 Service Unavailable instead - request->send(503, F("text/plain"), F("Server busy, try again")); -#else - request->deferResponse(); -#endif -} - //ws.cpp void handleWs(); void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len); diff --git a/wled00/json.cpp b/wled00/json.cpp index 76de82513e..22ebcf7b03 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -1135,7 +1135,7 @@ void serveJson(AsyncWebServerRequest* request) } if (!requestJSONBufferLock(17)) { - deferResponse(request); + request->deferResponse(); return; } // releaseJSONBufferLock() will be called when "response" is destroyed (from AsyncWebServer) diff --git a/wled00/set.cpp b/wled00/set.cpp index bf02e6de3c..b1831cf9e7 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -655,7 +655,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) if (subPage == SUBPAGE_UM) { if (!requestJSONBufferLock(5)) { - deferResponse(request); + request->deferResponse(); return; } diff --git a/wled00/wled.h b/wled00/wled.h index eec373d3a9..9046a36557 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -921,12 +921,7 @@ WLED_GLOBAL bool ledStatusState _INIT(false); // the current LED state #endif // server library objects -#if defined(CONFIG_IDF_TARGET_ESP32C6) -// ESP32-C6 uses patched ESPAsyncWebServer fork with simpler constructor -WLED_GLOBAL AsyncWebServer server _INIT_N(((80))); -#else WLED_GLOBAL AsyncWebServer server _INIT_N(((80, {0, WLED_REQUEST_MAX_QUEUE, WLED_REQUEST_MIN_HEAP, WLED_REQUEST_HEAP_USAGE}))); -#endif #ifdef WLED_ENABLE_WEBSOCKETS WLED_GLOBAL AsyncWebSocket ws _INIT_N((("/ws"))); #endif diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index fbcebef9c5..7a455453cd 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -393,7 +393,7 @@ void initServer() bool isConfig = false; if (!requestJSONBufferLock(14)) { - deferResponse(request); + request->deferResponse(); return; } From cf09c0dd1ed72d90121a7f9598f3aba0c683bb10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20M=C3=B6hle?= <91616163+softhack007@users.noreply.github.com> Date: Sat, 7 Feb 2026 01:32:05 +0100 Subject: [PATCH 24/83] Comment out '#pragma warning' suppression flag Comment out the warning suppression for '#pragma warning' messages. --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 70e88defe5..aa542a3c34 100644 --- a/platformio.ini +++ b/platformio.ini @@ -421,7 +421,7 @@ build_unflags = ${esp32c6.build_unflags} ;;-D NDEBUG build_flags = ${common.build_flags} ${esp32c6.build_flags} -D WLED_RELEASE_NAME=\"ESP32-C6_8MB\" -Wno-volatile -Wno-deprecated-declarations ;; silence compiler warnings - -Wno-cpp ;; silence '#pragma warning' messages + ;; -Wno-cpp ;; silence '#pragma warning' messages ;;-D DEBUG -g3 -ggdb ;;-D CORE_DEBUG_LEVEL=4 -D WLED_WATCHDOG_TIMEOUT=0 From 01b1c5165322cec4327bbfd34e2d4c9a5e001b30 Mon Sep 17 00:00:00 2001 From: Jonny Davey Date: Sat, 7 Feb 2026 13:37:50 +0000 Subject: [PATCH 25/83] Add experimental ESP32-C5 support with WiFi 6 dual-band ESP32-C5 is a RISC-V based SoC with WiFi 6 (2.4GHz + 5GHz) support. Treats C5 similarly to C3 for hardware capabilities (2 RMT channels, no parallel I2S for LEDs, similar GPIO restrictions). Changes across 25 files: - Add CONFIG_IDF_TARGET_ESP32C5 conditionals alongside C3/C6 checks - Add [esp32c5] and [env:esp32c5dev] build environments in platformio.ini - Uses pioarduino platform (Tasmota framework lacks C5 Arduino libs) - Exclude esp_dmx library (doesn't support C5 UART registers yet) - Fix LEDC register access for IDF 5.5.0 (duty_init vs duty) - Guard mbedtls_sha1_shim for IDF 5.5.0 (SHA1 built-in) - Add C5 chip identification (ID: 0x0017) in OTA and web UI Known limitations: - RMT LED output shows flush timeouts (needs NeoPixelBus C5 support) - WiFi AP confirmed working on hardware - esp_dmx/DMX input disabled - Experimental: requires pioarduino community platform Co-Authored-By: Claude Opus 4.6 --- platformio.ini | 51 +++++++++++++++++++ usermods/audioreactive/audio_reactive.cpp | 30 ++++++------ wled00/FX.h | 8 +-- wled00/FX_fcn.cpp | 10 ++-- wled00/FXparticleSystem.cpp | 14 +++--- wled00/NodeStruct.h | 2 + wled00/bus_manager.cpp | 14 ++++-- wled00/bus_wrapper.h | 26 +++++----- wled00/button.cpp | 2 +- wled00/cfg.cpp | 4 +- wled00/const.h | 8 +-- wled00/data/index.js | 3 ++ wled00/dmx_output.cpp | 2 +- wled00/improv.cpp | 2 +- wled00/json.cpp | 6 ++- wled00/mbedtls_sha1_shim.cpp | 3 +- wled00/ota_update.cpp | 7 +++ wled00/pin_manager.cpp | 7 +++ wled00/set.cpp | 2 +- wled00/src/dependencies/dmx/ESPDMX.cpp | 2 +- wled00/src/dependencies/dmx/SparkFunDMX.cpp | 2 +- wled00/udp.cpp | 4 ++ wled00/util.cpp | 6 +-- wled00/wled.cpp | 54 ++++++++++++++++++++- wled00/wled.h | 10 ++-- 25 files changed, 206 insertions(+), 73 deletions(-) diff --git a/platformio.ini b/platformio.ini index aa542a3c34..1f80fb2a5f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -454,6 +454,57 @@ build_unflags = ${env:esp32c6dev_8MB.build_unflags} -D WLED_RELEASE_NAME=\"ESP32 build_flags = ${env:esp32c6dev_8MB.build_flags} -D WLED_RELEASE_NAME=\"ESP32-C6_4MB\" +[esp32c5] +;; generic definitions for all ESP32-C5 boards +;; NOTE: ESP32-C5 requires pioarduino platform (Tasmota framework doesn't include C5 Arduino libs yet) +platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip +platform_packages = +build_unflags = ${esp32_idf_V5.build_unflags} + -D WLED_ENABLE_DMX_INPUT ;; esp_dmx library doesn't support C5 UART registers yet +build_flags = -g + -Wshadow=compatible-local + -DARDUINO_ARCH_ESP32 + -DARDUINO_ARCH_ESP32C5 + -DCONFIG_IDF_TARGET_ESP32C5=1 + -D CONFIG_ASYNC_TCP_USE_WDT=0 + -DCO + -DARDUINO_USB_MODE=1 + ${esp32_idf_V5.build_flags} +lib_deps = + ${esp32_idf_V5.lib_deps} +lib_ignore = ${esp32_idf_V5.lib_ignore} + esp_dmx ;; esp_dmx library doesn't support C5 UART registers yet + +[env:esp32c5dev] +;; ESP32-C5 "devkit C" with 4MB flash - EXPERIMENTAL +extends = esp32c5 +platform = ${esp32c5.platform} +platform_packages = ${esp32c5.platform_packages} +framework = arduino +board = esp32-c5-devkitc-1 + +build_unflags = ${esp32c5.build_unflags} +build_flags = ${common.build_flags} ${esp32c5.build_flags} -D WLED_RELEASE_NAME=\"ESP32-C5\" + -Wno-volatile -Wno-deprecated-declarations + -D WLED_WATCHDOG_TIMEOUT=0 + -DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip + -D WLED_DISABLE_INFRARED ;; library not compatible with -C5 + -D WLED_DISABLE_ESPNOW ;; not yet tested + -D WLED_DISABLE_ALEXA ;; compile errors + -D WLED_DISABLE_WEBSOCKETS ;; not yet tested +upload_speed = 460800 +lib_deps = ${esp32c5.lib_deps} +lib_ignore = ${esp32c5.lib_ignore} + IRremoteESP8266 + QuickEspNow + +board_build.partitions = ${esp32.big_partitions} +board_build.f_flash = 80000000L +board_build.flash_mode = qio +board_build.arduino.memory_type = qio_qspi +monitor_filters = esp32_exception_decoder + + [esp32s3] ;; generic definitions for all ESP32-S3 boards platform = ${esp32_idf_V5.platform} diff --git a/usermods/audioreactive/audio_reactive.cpp b/usermods/audioreactive/audio_reactive.cpp index 1d1825fdf1..54f8a61b9e 100644 --- a/usermods/audioreactive/audio_reactive.cpp +++ b/usermods/audioreactive/audio_reactive.cpp @@ -672,7 +672,7 @@ class AudioReactive : public Usermod { static const char _dynamics[]; static const char _frequency[]; static const char _inputLvl[]; -#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) +#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32S3) static const char _analogmic[]; #endif static const char _digitalmic[]; @@ -1164,7 +1164,7 @@ class AudioReactive : public Usermod { // Reset I2S peripheral for good measure i2s_driver_uninstall(I2S_NUM_0); // E (696) I2S: i2s_driver_uninstall(2006): I2S port 0 has not installed - #if !defined(CONFIG_IDF_TARGET_ESP32C3) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) delay(100); periph_module_reset(PERIPH_I2S0_MODULE); // not possible on -C3 #endif @@ -1172,15 +1172,15 @@ class AudioReactive : public Usermod { useBandPassFilter = false; - #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) + #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) if ((i2sckPin == I2S_PIN_NO_CHANGE) && (i2ssdPin >= 0) && (i2swsPin >= 0) && ((dmType == 1) || (dmType == 4)) ) dmType = 5; // dummy user support: SCK == -1 --means--> PDM microphone #endif switch (dmType) { - #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) + #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S3) // stub cases for not-yet-supported I2S modes on other ESP32 chips case 0: //ADC analog - #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) + #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) case 5: //PDM Microphone #endif #endif @@ -1208,7 +1208,7 @@ class AudioReactive : public Usermod { delay(100); if (audioSource) audioSource->initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin); break; - #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) + #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) case 5: DEBUGSR_PRINT(F("AR: I2S PDM Microphone - ")); DEBUGSR_PRINTLN(F(I2S_PDM_MIC_CHANNEL_TEXT)); audioSource = new I2SSource(SAMPLE_RATE, BLOCK_SIZE, 1.0f/4.0f); @@ -1224,7 +1224,7 @@ class AudioReactive : public Usermod { if (audioSource) audioSource->initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin); break; - #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) + #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32S3) // ADC over I2S is only possible on "classic" ESP32 case 0: DEBUGSR_PRINTLN(F("AR: Analog Microphone (left channel only).")); @@ -1801,7 +1801,7 @@ class AudioReactive : public Usermod { top[FPSTR(_addPalettes)] = addPalettes; #ifdef ARDUINO_ARCH_ESP32 - #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) + #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32S3) JsonObject amic = top.createNestedObject(FPSTR(_analogmic)); amic["pin"] = audioPin; #endif @@ -1860,16 +1860,16 @@ class AudioReactive : public Usermod { configComplete &= getJsonValue(top[FPSTR(_addPalettes)], addPalettes); #ifdef ARDUINO_ARCH_ESP32 - #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) + #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32S3) configComplete &= getJsonValue(top[FPSTR(_analogmic)]["pin"], audioPin); #else audioPin = -1; // MCU does not support analog mic #endif configComplete &= getJsonValue(top[FPSTR(_digitalmic)]["type"], dmType); - #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) + #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S3) if (dmType == 0) dmType = SR_DMTYPE; // MCU does not support analog - #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) + #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) if (dmType == 5) dmType = SR_DMTYPE; // MCU does not support PDM #endif #endif @@ -1907,14 +1907,14 @@ class AudioReactive : public Usermod { #ifdef ARDUINO_ARCH_ESP32 uiScript.print(F("uxp=ux+':digitalmic:pin[]';")); // uxp = shortcut for AudioReactive:digitalmic:pin[] uiScript.print(F("dd=addDropdown(ux,'digitalmic:type');")); - #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) + #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32S3) uiScript.print(F("addOption(dd,'Generic Analog',0);")); #endif uiScript.print(F("addOption(dd,'Generic I2S',1);")); uiScript.print(F("addOption(dd,'ES7243',2);")); uiScript.print(F("addOption(dd,'SPH0654',3);")); uiScript.print(F("addOption(dd,'Generic I2S with Mclk',4);")); - #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) + #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) uiScript.print(F("addOption(dd,'Generic I2S PDM',5);")); #endif uiScript.print(F("addOption(dd,'ES8388',6);")); @@ -1950,7 +1950,7 @@ class AudioReactive : public Usermod { uiScript.print(F("addInfo(uxp,0,'sd/data/dout','I2S SD');")); uiScript.print(F("addInfo(uxp,1,'ws/clk/lrck','I2S WS');")); uiScript.print(F("addInfo(uxp,2,'sck/bclk','I2S SCK');")); - #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) + #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32S3) uiScript.print(F("addInfo(uxp,3,'only use -1, 0, 1 or 3','I2S MCLK');")); #else uiScript.print(F("addInfo(uxp,3,'master clock','I2S MCLK');")); @@ -2073,7 +2073,7 @@ const char AudioReactive::_config[] PROGMEM = "config"; const char AudioReactive::_dynamics[] PROGMEM = "dynamics"; const char AudioReactive::_frequency[] PROGMEM = "frequency"; const char AudioReactive::_inputLvl[] PROGMEM = "inputLevel"; -#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) +#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32S3) const char AudioReactive::_analogmic[] PROGMEM = "analogmic"; #endif const char AudioReactive::_digitalmic[] PROGMEM = "digitalmic"; diff --git a/wled00/FX.h b/wled00/FX.h index 250df2646d..196a72346d 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -70,10 +70,10 @@ extern byte realtimeMode; // used in getMappedPixelIndex() #define WLED_FPS 42 #define FRAMETIME_FIXED (1000/WLED_FPS) #define FRAMETIME strip.getFrameTime() -#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) - #define MIN_FRAME_DELAY 2 // minimum wait between repaints, to keep other functions like WiFi alive -#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) - #define MIN_FRAME_DELAY 3 // S2/C3 are slower than normal esp32, and only have one core +#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32S2) + #define MIN_FRAME_DELAY 2 // minimum wait between repaints, to keep other functions like WiFi alive +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) + #define MIN_FRAME_DELAY 3 // S2/C3/C5 are slower than normal esp32, and only have one core #else #define MIN_FRAME_DELAY 8 // 8266 legacy MIN_SHOW_DELAY #endif diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 47ef23cd40..21d15cd58b 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1161,7 +1161,7 @@ void WS2812FX::finalizeInit() { BusManager::removeAll(); unsigned digitalCount = 0; - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) // 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; unsigned busType = 0; @@ -1191,7 +1191,7 @@ void WS2812FX::finalizeInit() { unsigned memB = bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount++ : 0); // does not include DMA/RMT buffer mem += memB; // estimate maximum I2S memory usage (only relevant for digital non-2pin busses) - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) && !defined(ESP8266) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) && !defined(ESP8266) #if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S3) const bool usesI2S = ((useParallelI2S && digitalCount <= 8) || (!useParallelI2S && digitalCount == 1)); #elif defined(CONFIG_IDF_TARGET_ESP32S2) @@ -1339,8 +1339,8 @@ static uint8_t _add (uint8_t a, uint8_t b) { unsigned t = a + b; return t static uint8_t _subtract (uint8_t a, uint8_t b) { return b > a ? (b - a) : 0; } static uint8_t _difference(uint8_t a, uint8_t b) { return b > a ? (b - a) : (a - b); } static uint8_t _average (uint8_t a, uint8_t b) { return (a + b) >> 1; } -#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) -static uint8_t _multiply (uint8_t a, uint8_t b) { return ((a * b) + 255) >> 8; } // faster than division on C3 but slightly less accurate +#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) +static uint8_t _multiply (uint8_t a, uint8_t b) { return ((a * b) + 255) >> 8; } // faster than division on C3/C5 but slightly less accurate #else static uint8_t _multiply (uint8_t a, uint8_t b) { return (a * b) / 255; } // origianl uses a & b in range [0,1] #endif @@ -1350,7 +1350,7 @@ static uint8_t _darken (uint8_t a, uint8_t b) { return a < b ? a : b; } static uint8_t _screen (uint8_t a, uint8_t b) { return 255 - _multiply(~a,~b); } // 255 - (255-a)*(255-b)/255 static uint8_t _overlay (uint8_t a, uint8_t b) { return b < 128 ? 2 * _multiply(a,b) : (255 - 2 * _multiply(~a,~b)); } static uint8_t _hardlight (uint8_t a, uint8_t b) { return a < 128 ? 2 * _multiply(a,b) : (255 - 2 * _multiply(~a,~b)); } -#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) +#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) static uint8_t _softlight (uint8_t a, uint8_t b) { return (((b * b * (255 - 2 * a))) + ((2 * a * b + 256) << 8)) >> 16; } // Pegtop's formula (1 - 2a)b^2 #else static uint8_t _softlight (uint8_t a, uint8_t b) { return (b * b * (255 - 2 * a) + 255 * 2 * a * b) / (255 * 255); } // Pegtop's formula (1 - 2a)b^2 + 2ab diff --git a/wled00/FXparticleSystem.cpp b/wled00/FXparticleSystem.cpp index 1a1ed08850..f64ba1e5cc 100644 --- a/wled00/FXparticleSystem.cpp +++ b/wled00/FXparticleSystem.cpp @@ -493,7 +493,7 @@ void ParticleSystem2D::applyGravity(PSparticle &part) { // note: a coefficient smaller than 0 will speed them up (this is a feature, not a bug), coefficient larger than 255 inverts the speed, so don't do that void ParticleSystem2D::applyFriction(PSparticle &part, const int32_t coefficient) { // note: not checking if particle is dead can be done by caller (or can be omitted) - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) int32_t friction = 256 - coefficient; part.vx = ((int32_t)part.vx * friction + (((int32_t)part.vx >> 31) & 0xFF)) >> 8; // note: (v>>31) & 0xFF)) extracts the sign and adds 255 if negative for correct rounding using shifts part.vy = ((int32_t)part.vy * friction + (((int32_t)part.vy >> 31) & 0xFF)) >> 8; @@ -507,7 +507,7 @@ void ParticleSystem2D::applyFriction(PSparticle &part, const int32_t coefficient // apply friction to all particles // note: not checking if particle is dead is faster as most are usually alive and if few are alive, rendering is fast anyways void ParticleSystem2D::applyFriction(const int32_t coefficient) { - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) int32_t friction = 256 - coefficient; for (uint32_t i = 0; i < usedParticles; i++) { particles[i].vx = ((int32_t)particles[i].vx * friction + (((int32_t)particles[i].vx >> 31) & 0xFF)) >> 8; // note: (v>>31) & 0xFF)) extracts the sign and adds 255 if negative for correct rounding using shifts @@ -891,7 +891,7 @@ void WLED_O2_ATTR ParticleSystem2D::collideParticles(PSparticle &particle1, PSpa int32_t surfacehardness = 1 + max(collisionHardness, (int32_t)PS_P_MINSURFACEHARDNESS); // if particles are soft, the impulse must stay above a limit or collisions slip through at higher speeds, 170 seems to be a good value int32_t impulse = (((((-dotProduct) << 15) / distanceSquared) * surfacehardness) >> 8); // note: inverting before bitshift corrects for asymmetry in right-shifts (is slightly faster) - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) int32_t ximpulse = (impulse * dx + ((dx >> 31) & 32767)) >> 15; // note: extracting sign bit and adding rounding value to correct for asymmetry in right shifts int32_t yimpulse = (impulse * dy + ((dy >> 31) & 32767)) >> 15; #else @@ -906,7 +906,7 @@ void WLED_O2_ATTR ParticleSystem2D::collideParticles(PSparticle &particle1, PSpa if (collisionHardness < PS_P_MINSURFACEHARDNESS && (SEGMENT.call & 0x07) == 0) { // if particles are soft, they become 'sticky' i.e. apply some friction (they do pile more nicely and stop sloshing around) const uint32_t coeff = collisionHardness + (255 - PS_P_MINSURFACEHARDNESS); // Note: could call applyFriction, but this is faster and speed is key here - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) particle1.vx = ((int32_t)particle1.vx * coeff + (((int32_t)particle1.vx >> 31) & 0xFF)) >> 8; // note: (v>>31) & 0xFF)) extracts the sign and adds 255 if negative for correct rounding using shifts particle1.vy = ((int32_t)particle1.vy * coeff + (((int32_t)particle1.vy >> 31) & 0xFF)) >> 8; particle2.vx = ((int32_t)particle2.vx * coeff + (((int32_t)particle2.vx >> 31) & 0xFF)) >> 8; @@ -1398,7 +1398,7 @@ void ParticleSystem1D::applyGravity(PSparticle1D &part, PSparticleFlags1D &partF // slow down particle by friction, the higher the speed, the higher the friction. a high friction coefficient slows them more (255 means instant stop) // note: a coefficient smaller than 0 will speed them up (this is a feature, not a bug), coefficient larger than 255 inverts the speed, so don't do that void ParticleSystem1D::applyFriction(int32_t coefficient) { - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) int32_t friction = 256 - coefficient; for (uint32_t i = 0; i < usedParticles; i++) { if (particles[i].ttl) @@ -1652,7 +1652,7 @@ void WLED_O2_ATTR ParticleSystem1D::collideParticles(PSparticle1D &particle1, co if (dotProduct < 0) { // particles are moving towards each other uint32_t surfacehardness = max(collisionHardness, (int32_t)PS_P_MINSURFACEHARDNESS_1D); // if particles are soft, the impulse must stay above a limit or collisions slip through // Calculate new velocities after collision note: not using dot product like in 2D as impulse is purely speed depnedent - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) int32_t impulse = ((dv * surfacehardness) + ((dv >> 31) & 0xFF)) >> 8; // note: (v>>31) & 0xFF)) extracts the sign and adds 255 if negative for correct rounding using shifts #else // division is faster on ESP32, S2 and S3 int32_t impulse = (dv * surfacehardness) / 255; @@ -1668,7 +1668,7 @@ void WLED_O2_ATTR ParticleSystem1D::collideParticles(PSparticle1D &particle1, co if (collisionHardness < PS_P_MINSURFACEHARDNESS_1D && (SEGMENT.call & 0x07) == 0) { // if particles are soft, they become 'sticky' i.e. apply some friction const uint32_t coeff = collisionHardness + (250 - PS_P_MINSURFACEHARDNESS_1D); - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) particle1.vx = ((int32_t)particle1.vx * coeff + (((int32_t)particle1.vx >> 31) & 0xFF)) >> 8; // note: (v>>31) & 0xFF)) extracts the sign and adds 255 if negative for correct rounding using shifts particle2.vx = ((int32_t)particle2.vx * coeff + (((int32_t)particle2.vx >> 31) & 0xFF)) >> 8; #else // division is faster on ESP32, S2 and S3 diff --git a/wled00/NodeStruct.h b/wled00/NodeStruct.h index 34f73ab418..f436a6519e 100644 --- a/wled00/NodeStruct.h +++ b/wled00/NodeStruct.h @@ -14,6 +14,8 @@ #define NODE_TYPE_ID_ESP32S2 33 // etc #define NODE_TYPE_ID_ESP32S3 34 #define NODE_TYPE_ID_ESP32C3 35 +#define NODE_TYPE_ID_ESP32C6 36 +#define NODE_TYPE_ID_ESP32C5 41 /*********************************************************************************************\ * NodeStruct diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index e2e28cebc0..abd50111e6 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -9,7 +9,7 @@ #include "src/dependencies/network/Network.h" // for isConnected() (& WiFi) #include "driver/ledc.h" #include "soc/ledc_struct.h" - #if !(defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)) + #if !(defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)) #define LEDC_MUTEX_LOCK() do {} while (xSemaphoreTake(_ledc_sys_lock, portMAX_DELAY) != pdPASS) #define LEDC_MUTEX_UNLOCK() xSemaphoreGive(_ledc_sys_lock) extern SemaphoreHandle_t _ledc_sys_lock; @@ -593,7 +593,11 @@ void BusPwm::show() { unsigned ch = channel%8; // group channel // directly write to LEDC struct as there is no HAL exposed function for dithering // duty has 20 bit resolution with 4 fractional bits (24 bits in total) + #if defined(CONFIG_IDF_TARGET_ESP32C5) + LEDC.channel_group[gr].channel[ch].duty_init.duty = duty << ((!dithering)*4); // C5 LEDC struct uses duty_init + #else LEDC.channel_group[gr].channel[ch].duty.duty = duty << ((!dithering)*4); // lowest 4 bits are used for dithering, shift by 4 bits if not using dithering + #endif LEDC.channel_group[gr].channel[ch].hpoint.hpoint = hPoint >> bitShift; // hPoint is at _depth resolution (needs shifting if dithering) ledc_update_duty((ledc_mode_t)gr, (ledc_channel_t)ch); #endif @@ -1140,12 +1144,12 @@ size_t BusManager::memUsage() { // front buffers are always allocated per bus unsigned size = 0; unsigned maxI2S = 0; - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(ESP8266) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(ESP8266) unsigned digitalCount = 0; #endif for (const auto &bus : busses) { size += bus->getBusSize(); - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(ESP8266) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(ESP8266) if (bus->isDigital() && !bus->is2Pin()) { digitalCount++; if ((PolyBus::isParallelI2S1Output() && digitalCount <= 8) || (!PolyBus::isParallelI2S1Output() && digitalCount == 1)) { @@ -1242,8 +1246,8 @@ void BusManager::removeAll() { // If enabled, RMT idle level is set to HIGH when off // to prevent leakage current when using an N-channel MOSFET to toggle LED power void BusManager::esp32RMTInvertIdle() { -#if defined(CONFIG_IDF_TARGET_ESP32C6) - // ESP32-C6 uses BitBang method, not RMT - nothing to do here +#if defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) + // ESP32-C5/C6 use shared RMT method - idle level inversion not supported return; #else bool idle_out; diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index 43bc0e2ed7..6beab153bf 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -248,7 +248,7 @@ typedef NeoEsp32I2s0Apa106Method X1Apa106Method; typedef NeoEsp32I2s0Ws2805Method X1Ws2805Method; typedef NeoEsp32I2s0Tm1914Method X1Tm1914Method; -#elif !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) +#elif !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) // regular ESP32 will use I2S1 typedef NeoEsp32I2s1Ws2812xMethod X1Ws2812xMethod; typedef NeoEsp32I2s1Sk6812Method X1Sk6812Method; @@ -464,7 +464,7 @@ 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 - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) 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; @@ -496,7 +496,7 @@ class PolyBus { static void* create(uint8_t busType, uint8_t* pins, uint16_t len, uint8_t channel) { // NOTE: "channel" is only used on ESP32 (and its variants) for RMT channel allocation - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) if (_useParallelI2S && (channel >= 8)) { // Parallel I2S channels are to be used first, so subtract 8 to get the RMT channel number channel -= 8; @@ -576,7 +576,7 @@ 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 - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) 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; @@ -675,7 +675,7 @@ 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 - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) 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; @@ -771,7 +771,7 @@ 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 - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) case I_32_I2_NEO_3: if (_useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; case I_32_I2_NEO_4: if (_useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; case I_32_I2_400_3: if (_useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; @@ -893,7 +893,7 @@ class PolyBus { case I_32_RN_TM1914_3: (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_RN_SM16825_5: (static_cast(busPtr))->SetPixelColor(pix, Rgbww80Color(col.R*257, col.G*257, col.B*257, cctWW*257, cctCW*257)); break; // I2S1 bus or paralell buses - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) case I_32_I2_NEO_3: if (_useParallelI2S) (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); else (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_I2_NEO_4: if (_useParallelI2S) (static_cast(busPtr))->SetPixelColor(pix, col); else (static_cast(busPtr))->SetPixelColor(pix, col); break; case I_32_I2_400_3: if (_useParallelI2S) (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); else (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; @@ -990,7 +990,7 @@ class PolyBus { case I_32_RN_TM1914_3: col = (static_cast(busPtr))->GetPixelColor(pix); break; case I_32_RN_SM16825_5: { Rgbww80Color c = (static_cast(busPtr))->GetPixelColor(pix); col = RGBW32(c.R/257,c.G/257,c.B/257,max(c.WW,c.CW)/257); } break; // will not return original W // I2S1 bus or paralell buses - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) case I_32_I2_NEO_3: col = (_useParallelI2S) ? (static_cast(busPtr))->GetPixelColor(pix) : (static_cast(busPtr))->GetPixelColor(pix); break; case I_32_I2_NEO_4: col = (_useParallelI2S) ? (static_cast(busPtr))->GetPixelColor(pix) : (static_cast(busPtr))->GetPixelColor(pix); break; case I_32_I2_400_3: col = (_useParallelI2S) ? (static_cast(busPtr))->GetPixelColor(pix) : (static_cast(busPtr))->GetPixelColor(pix); break; @@ -1105,7 +1105,7 @@ class PolyBus { case I_32_RN_TM1914_3: delete (static_cast(busPtr)); break; case I_32_RN_SM16825_5: delete (static_cast(busPtr)); break; // I2S1 bus or paralell buses - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) case I_32_I2_NEO_3: if (_useParallelI2S) delete (static_cast(busPtr)); else delete (static_cast(busPtr)); break; case I_32_I2_NEO_4: if (_useParallelI2S) delete (static_cast(busPtr)); else delete (static_cast(busPtr)); break; case I_32_I2_400_3: if (_useParallelI2S) delete (static_cast(busPtr)); else delete (static_cast(busPtr)); break; @@ -1202,7 +1202,7 @@ class PolyBus { case I_32_RN_TM1914_3: size = (static_cast(busPtr))->PixelsSize()*2; break; case I_32_RN_SM16825_5: size = (static_cast(busPtr))->PixelsSize()*2; break; // I2S1 bus or paralell buses (front + DMA; DMA = front * cadence, aligned to 4 bytes) - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) case I_32_I2_NEO_3: size = (_useParallelI2S) ? (static_cast(busPtr))->PixelsSize()*4 : (static_cast(busPtr))->PixelsSize()*4; break; case I_32_I2_NEO_4: size = (_useParallelI2S) ? (static_cast(busPtr))->PixelsSize()*4 : (static_cast(busPtr))->PixelsSize()*4; break; case I_32_I2_400_3: size = (_useParallelI2S) ? (static_cast(busPtr))->PixelsSize()*4 : (static_cast(busPtr))->PixelsSize()*4; break; @@ -1281,7 +1281,7 @@ class PolyBus { case I_32_RN_2805_5 : size = (size + 2*count)*2; break; // 5 channels case I_32_RN_SM16825_5: size = (size + 2*count)*2*2; break; // 16bit, 5 channels // I2S1 bus or paralell I2S1 buses (1x front, does not include DMA buffer which is front*cadence, a bit(?) more for LCD) - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) case I_32_I2_NEO_3 : // fallthrough case I_32_I2_400_3 : // fallthrough case I_32_I2_TM2_3 : // fallthrough @@ -1368,8 +1368,8 @@ class PolyBus { if (num > 4) return I_NONE; if (num > 3) offset = 1; // only one I2S0 (use last to allow Audioreactive) } - #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) - // On ESP32-C3 only the first 2 RMT channels are usable for transmitting + #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) + // On ESP32-C3/C5/C6 only the first 2 RMT channels are usable for transmitting if (num > 1) return I_NONE; //if (num > 1) offset = 1; // I2S not supported yet (only 1 I2S) #elif defined(CONFIG_IDF_TARGET_ESP32S3) diff --git a/wled00/button.cpp b/wled00/button.cpp index 651f12cf18..f1a29ecb72 100644 --- a/wled00/button.cpp +++ b/wled00/button.cpp @@ -109,7 +109,7 @@ bool isButtonPressed(uint8_t b) break; case BTN_TYPE_TOUCH: case BTN_TYPE_TOUCH_SWITCH: - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) #ifdef SOC_TOUCH_VERSION_2 //ESP32 S2 and S3 provide a function to check touch state (state is updated in interrupt) if (touchInterruptGetLastStatus(pin)) return true; #else diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 2bc3fe4503..bcab0af736 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -165,7 +165,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { uint8_t cctBlending = hw_led[F("cb")] | Bus::getCCTBlend(); Bus::setCCTBlend(cctBlending); strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) CJSON(useParallelI2S, hw_led[F("prl")]); #endif @@ -933,7 +933,7 @@ void serializeConfig(JsonObject root) { hw_led[F("cb")] = Bus::getCCTBlend(); hw_led["fps"] = strip.getTargetFps(); hw_led[F("rgbwm")] = Bus::getGlobalAWMode(); // global auto white mode override - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) hw_led[F("prl")] = BusManager::hasParallelOutput(); #endif diff --git a/wled00/const.h b/wled00/const.h index ce03f9d856..d5078e8678 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -66,7 +66,7 @@ constexpr size_t FIXED_PALETTE_COUNT = DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_C constexpr size_t WLED_MAX_ANALOG_CHANNELS = static_cast(LEDC_CHANNEL_MAX) * static_cast(LEDC_SPEED_MODE_MAX); - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) // 2 RMT, 6 LEDC, only has 1 I2S but NPB does not support it ATM #define WLED_MAX_DIGITAL_CHANNELS 2 //#define WLED_MAX_ANALOG_CHANNELS 6 @@ -477,7 +477,7 @@ static_assert(WLED_MAX_BUSSES <= 32, "WLED_MAX_BUSSES exceeds hard limit"); #define MAX_LEDS 1536 //can't rely on memory limit to limit this to 1536 LEDs #elif defined(CONFIG_IDF_TARGET_ESP32S2) #define MAX_LEDS 2048 //due to memory constraints S2 - #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) #define MAX_LEDS 4096 #else #define MAX_LEDS 16384 @@ -490,7 +490,7 @@ static_assert(WLED_MAX_BUSSES <= 32, "WLED_MAX_BUSSES exceeds hard limit"); #else #if defined(ARDUINO_ARCH_ESP32S2) #define MAX_LED_MEMORY 16384 - #elif defined(ARDUINO_ARCH_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) #define MAX_LED_MEMORY 32768 #else #define MAX_LED_MEMORY 65536 @@ -606,7 +606,7 @@ static_assert(WLED_MAX_BUSSES <= 32, "WLED_MAX_BUSSES exceeds hard limit"); #endif // Defaults pins, type and counts to configure LED output -#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) +#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) #ifdef WLED_ENABLE_DMX #define DEFAULT_LED_PIN 1 #warning "Compiling with DMX. The default LED pin has been changed to pin 1." diff --git a/wled00/data/index.js b/wled00/data/index.js index 84b256183c..478f970ce2 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -735,6 +735,7 @@ ${urows===""?'':'
"):''} ${inforow("Build",i.vid)} ${inforow("Signal strength",i.wifi.signal +"% ("+ i.wifi.rssi, " dBm)")} +${i.wifi.band?inforow("WiFi band",i.wifi.band + " (Ch " + i.wifi.channel + ")"):""} ${inforow("Uptime",getRuntimeStr(i.uptime))} ${inforow("Time",i.time)} ${inforow("Free heap",(i.freeheap/1024).toFixed(1)," kB")} @@ -1096,6 +1097,8 @@ function btype(b) case 34: return "ESP32-S3"; case 5: case 35: return "ESP32-C3"; + case 36: return "ESP32-C6"; + case 41: return "ESP32-C5"; case 1: case 82: return "ESP8266"; } diff --git a/wled00/dmx_output.cpp b/wled00/dmx_output.cpp index eace2145e6..f7b87cb048 100644 --- a/wled00/dmx_output.cpp +++ b/wled00/dmx_output.cpp @@ -69,7 +69,7 @@ void handleDMXOutput() } void initDMXOutput() { - #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) + #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S2) dmx.init(512); // initialize with bus length #else dmx.initWrite(512); // initialize with bus length diff --git a/wled00/improv.cpp b/wled00/improv.cpp index 1eb83627db..d94cf35381 100644 --- a/wled00/improv.cpp +++ b/wled00/improv.cpp @@ -10,7 +10,7 @@ #define DIMPROV_PRINTF(x...) #endif -#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) +#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S3) #undef WLED_DISABLE_IMPROV_WIFISCAN #define WLED_DISABLE_IMPROV_WIFISCAN #endif diff --git a/wled00/json.cpp b/wled00/json.cpp index 22ebcf7b03..60c9c3a036 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -796,7 +796,9 @@ void serializeInfo(JsonObject root) int qrssi = WiFi.RSSI(); wifi_info[F("rssi")] = qrssi; wifi_info[F("signal")] = getSignalQuality(qrssi); - wifi_info[F("channel")] = WiFi.channel(); + int wifiChannel = WiFi.channel(); + wifi_info[F("channel")] = wifiChannel; + wifi_info[F("band")] = (wifiChannel >= 36) ? F("5GHz") : F("2.4GHz"); wifi_info[F("ap")] = apActive; JsonObject fs_info = root.createNestedObject("fs"); @@ -811,7 +813,7 @@ void serializeInfo(JsonObject root) wifi_info[F("txPower")] = (int) WiFi.getTxPower(); wifi_info[F("sleep")] = (bool) WiFi.getSleep(); #endif - #if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) root[F("arch")] = "esp32"; #else root[F("arch")] = ESP.getChipModel(); diff --git a/wled00/mbedtls_sha1_shim.cpp b/wled00/mbedtls_sha1_shim.cpp index 8561afcfc3..a009553bee 100644 --- a/wled00/mbedtls_sha1_shim.cpp +++ b/wled00/mbedtls_sha1_shim.cpp @@ -1,6 +1,7 @@ #include "wled.h" #ifdef ESP32 -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) +// ESP32-C5 on pioarduino uses IDF 5.5+ which has SHA1 built-in, skip shim +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0) #include "mbedtls/sha1.h" #include "SHA1Builder.h" diff --git a/wled00/ota_update.cpp b/wled00/ota_update.cpp index 2f758b2c79..e91e5a98c0 100644 --- a/wled00/ota_update.cpp +++ b/wled00/ota_update.cpp @@ -435,6 +435,13 @@ bool verifyBootloaderImage(const uint8_t* &buffer, size_t &len, String* bootload } *bootloaderErrorMsg = "ESP32-S3 update not supported yet"; return false; + #elif defined(CONFIG_IDF_TARGET_ESP32C5) + if (chipId != 0x0017) { + *bootloaderErrorMsg = "Chip ID mismatch - expected ESP32-C5 (0x0017), got 0x" + String(chipId, HEX); + return false; + } + *bootloaderErrorMsg = "ESP32-C5 update not supported yet"; + return false; #elif defined(CONFIG_IDF_TARGET_ESP32C6) if (chipId != 0x000D) { *bootloaderErrorMsg = "Chip ID mismatch - expected ESP32-C6 (0x000D), got 0x" + String(chipId, HEX); diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index 729e845039..cf7d492527 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -232,6 +232,13 @@ bool PinManager::isPinOk(byte gpio, bool output) if (gpio > 21 && gpio < 33) return false; // 22 to 32: not connected + SPI FLASH // JTAG: GPIO39-42 are usually used for inline debugging // GPIO46 is input only and pulled down + #elif defined(CONFIG_IDF_TARGET_ESP32C5) + // strapping pins: 2, 7, 27, 28 + // GPIO 0-15 directly usable, 16-22 are for SPI flash + if (gpio > 15 && gpio < 23) return false; // 16-22 SPI FLASH + #if ARDUINO_USB_CDC_ON_BOOT == 1 || ARDUINO_USB_DFU_ON_BOOT == 1 + if (gpio == 13 || gpio == 14) return false; // 13-14 USB-JTAG + #endif #elif defined(CONFIG_IDF_TARGET_ESP32C6) // strapping pins: 8, 9, 15 // GPIO 0-23 directly usable, 24-30 are for SPI flash diff --git a/wled00/set.cpp b/wled00/set.cpp index b1831cf9e7..45107492f0 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -155,7 +155,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) Bus::setCCTBlend(cctBlending); Bus::setGlobalAWMode(request->arg(F("AW")).toInt()); strip.setTargetFps(request->arg(F("FR")).toInt()); - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) useParallelI2S = request->hasArg(F("PR")); #endif diff --git a/wled00/src/dependencies/dmx/ESPDMX.cpp b/wled00/src/dependencies/dmx/ESPDMX.cpp index a80cad71c8..b1a613375a 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(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S2) #include diff --git a/wled00/src/dependencies/dmx/SparkFunDMX.cpp b/wled00/src/dependencies/dmx/SparkFunDMX.cpp index 064b9ff620..a180869b80 100644 --- a/wled00/src/dependencies/dmx/SparkFunDMX.cpp +++ b/wled00/src/dependencies/dmx/SparkFunDMX.cpp @@ -17,7 +17,7 @@ Distributed as-is; no warranty is given. #if defined(ARDUINO_ARCH_ESP32) #include -#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) +#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32S2) #include "SparkFunDMX.h" #include diff --git a/wled00/udp.cpp b/wled00/udp.cpp index c1e4951b42..477acf2da1 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -722,6 +722,10 @@ void sendSysInfoUDP() memcpy((byte *)data + 6, serverDescription, 32); #ifdef ESP8266 data[38] = NODE_TYPE_ID_ESP8266; + #elif defined(CONFIG_IDF_TARGET_ESP32C5) + data[38] = NODE_TYPE_ID_ESP32C5; + #elif defined(CONFIG_IDF_TARGET_ESP32C6) + data[38] = NODE_TYPE_ID_ESP32C6; #elif defined(CONFIG_IDF_TARGET_ESP32C3) data[38] = NODE_TYPE_ID_ESP32C3; #elif defined(CONFIG_IDF_TARGET_ESP32S3) diff --git a/wled00/util.cpp b/wled00/util.cpp index a391d536b8..2237512457 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -633,8 +633,8 @@ int32_t hw_random(int32_t lowerlimit, int32_t upperlimit) { // PSRAM compile time checks to provide info for misconfigured env #if defined(BOARD_HAS_PSRAM) - #if defined(IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(ESP8266) - #error "ESP32-C3 and ESP8266 with PSRAM is not supported, please remove BOARD_HAS_PSRAM definition" + #if defined(IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(ESP8266) + #error "ESP32-C3/C5 and ESP8266 with PSRAM is not supported, please remove BOARD_HAS_PSRAM definition" #else #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) // PSRAM fix only needed for classic esp32 // BOARD_HAS_PSRAM also means that compiler flag "-mfix-esp32-psram-cache-issue" has to be used for old "rev.1" esp32 @@ -694,7 +694,7 @@ static void *validateFreeHeap(void *buffer) { void *d_malloc(size_t size) { void *buffer; - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) // the newer ESP32 variants have byte-accessible fast RTC memory that can be used as heap, access speed is on-par with DRAM // the system does prefer normal DRAM until full, since free RTC memory is ~7.5k only, its below the minimum heap threshold and needs to be allocated explicitly // use RTC RAM for small allocations to improve fragmentation or if DRAM is running low diff --git a/wled00/wled.cpp b/wled00/wled.cpp index d41c75465e..c27b0e75a8 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -351,7 +351,7 @@ void WLED::setup() Serial.setTimeout(50); // this causes troubles on new MCUs that have a "virtual" USB Serial (HWCDC) #else #endif - #if defined(WLED_DEBUG) && defined(ARDUINO_ARCH_ESP32) && (defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || ARDUINO_USB_CDC_ON_BOOT) + #if defined(WLED_DEBUG) && defined(ARDUINO_ARCH_ESP32) && (defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || ARDUINO_USB_CDC_ON_BOOT) delay(2500); // allow CDC USB serial to initialise #endif #if !defined(WLED_DEBUG) && defined(ARDUINO_ARCH_ESP32) && !defined(WLED_DEBUG_HOST) && ARDUINO_USB_CDC_ON_BOOT @@ -696,7 +696,56 @@ if (multiWiFi.empty()) { // guard: handle empty WiFi list // convert the "serverDescription" into a valid DNS hostname (alphanumeric) char hostname[25]; prepareHostname(hostname); +#if defined(CONFIG_IDF_TARGET_ESP32C5) + // ESP32-C5: Prefer 5GHz WiFi 6 for better performance + DEBUG_PRINTF_P(PSTR("ESP32-C5: Trying 5GHz for SSID: %s\n"), multiWiFi[selectedWiFi].clientSSID); + + WiFi.disconnect(true); + WiFi.mode(WIFI_STA); + + // Set country code to enable all 5GHz channels + wifi_country_t country = { + .cc = "US", + .schan = 1, + .nchan = 14, + .max_tx_power = 80, + .policy = WIFI_COUNTRY_POLICY_MANUAL + }; + esp_wifi_set_country(&country); + WiFi.setBandMode(WIFI_BAND_MODE_5G_ONLY); + DEBUG_PRINTLN(F("ESP32-C5: Band mode set to 5GHz ONLY")); + + wifi_config_t wifi_config = {}; + strncpy((char*)wifi_config.sta.ssid, multiWiFi[selectedWiFi].clientSSID, sizeof(wifi_config.sta.ssid) - 1); + strncpy((char*)wifi_config.sta.password, multiWiFi[selectedWiFi].clientPass, sizeof(wifi_config.sta.password) - 1); + wifi_config.sta.scan_method = WIFI_ALL_CHANNEL_SCAN; + wifi_config.sta.sort_method = WIFI_CONNECT_AP_BY_SIGNAL; + wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; + esp_wifi_set_config(WIFI_IF_STA, &wifi_config); + esp_wifi_connect(); + + // Wait up to 20 seconds for 5GHz connection + DEBUG_PRINTLN(F("ESP32-C5: Waiting for 5GHz connection (20s timeout)...")); + unsigned long c5start = millis(); + while (WiFi.status() != WL_CONNECTED && millis() - c5start < 20000) { + delay(250); + if ((millis() - c5start) % 3000 < 250) { + DEBUG_PRINTF_P(PSTR(" ...%lus, status=%d\n"), (millis() - c5start) / 1000, WiFi.status()); + } + } + + if (WiFi.status() != WL_CONNECTED) { + DEBUG_PRINTLN(F("ESP32-C5: 5GHz failed, falling back to AUTO mode")); + esp_wifi_disconnect(); + WiFi.setBandMode(WIFI_BAND_MODE_AUTO); + esp_wifi_set_config(WIFI_IF_STA, &wifi_config); + esp_wifi_connect(); + } else { + DEBUG_PRINTF_P(PSTR("ESP32-C5: Connected on 5GHz, channel: %d\n"), WiFi.channel()); + } +#else WiFi.begin(multiWiFi[selectedWiFi].clientSSID, multiWiFi[selectedWiFi].clientPass); // no harm if called multiple times +#endif #ifdef ARDUINO_ARCH_ESP32 WiFi.setTxPower(wifi_power_t(txPower)); @@ -873,6 +922,9 @@ void WLED::handleConnection() DEBUG_PRINTLN(); DEBUG_PRINT(F("Connected! IP address: ")); DEBUG_PRINTLN(WLEDNetwork.localIP()); + #if defined(CONFIG_IDF_TARGET_ESP32C5) + { int32_t ch = WiFi.channel(); DEBUG_PRINTF_P(PSTR("WiFi channel: %d (%s)\n"), ch, (ch >= 36) ? "5GHz" : "2.4GHz"); } + #endif if (improvActive) { if (improvError == 3) sendImprovStateResponse(0x00, true); sendImprovStateResponse(0x04); diff --git a/wled00/wled.h b/wled00/wled.h index 9046a36557..02002d9fe8 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -154,7 +154,7 @@ #endif #ifdef WLED_ENABLE_DMX - #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) + #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) #include "src/dependencies/dmx/ESPDMX.h" #else //ESP32 #include "src/dependencies/dmx/SparkFunDMX.h" @@ -327,7 +327,7 @@ WLED_GLOBAL bool rlyOpenDrain _INIT(RLYODRAIN); #define IRTYPE 0 #endif -#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32S2) || (defined(RX) && defined(TX)) +#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32S2) || (defined(RX) && defined(TX)) // use RX/TX as set by the framework - these boards do _not_ have RX=3 and TX=1 constexpr uint8_t hardwareRX = RX; constexpr uint8_t hardwareTX = TX; @@ -388,7 +388,7 @@ WLED_GLOBAL bool noWifiSleep _INIT(false); WLED_GLOBAL bool force802_3g _INIT(false); #endif // WLED_SAVE_RAM #ifdef ARDUINO_ARCH_ESP32 - #if defined(LOLIN_WIFI_FIX) && (defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)) + #if defined(LOLIN_WIFI_FIX) && (defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)) WLED_GLOBAL uint8_t txPower _INIT(WIFI_POWER_8_5dBm); #else WLED_GLOBAL uint8_t txPower _INIT(WIFI_POWER_19_5dBm); @@ -415,7 +415,7 @@ WLED_GLOBAL byte bootPreset _INIT(0); // save preset to load WLED_GLOBAL bool useGlobalLedBuffer _INIT(false); // double buffering disabled on ESP8266 #else WLED_GLOBAL bool useGlobalLedBuffer _INIT(true); // double buffering enabled on ESP32 - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) WLED_GLOBAL bool useParallelI2S _INIT(false); // parallel I2S for ESP32 #endif #endif @@ -469,7 +469,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 - #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) + #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) WLED_GLOBAL DMXESPSerial dmx; #else //ESP32 WLED_GLOBAL SparkFunDMX dmx; From 8268c4a9486fb6d757396c1266df7f6b2e1bcae4 Mon Sep 17 00:00:00 2001 From: Jonny Davey Date: Sat, 7 Feb 2026 16:16:11 +0000 Subject: [PATCH 26/83] Applied changes based on comments on PR --- .claude/settings.local.json | 7 + .vscode/extensions.json | 3 +- platformio.ini | 20 +- wled00/NodeStruct.h | 11 +- wled00/idf_component.yml | 2 + wled00/idf_component.yml.orig | 2 + wled00/js_iro.h | 636 ++++++++++++++++++++++++++++++++++ wled00/wled.cpp | 49 --- 8 files changed, 668 insertions(+), 62 deletions(-) create mode 100644 .claude/settings.local.json create mode 100644 wled00/idf_component.yml create mode 100644 wled00/idf_component.yml.orig create mode 100644 wled00/js_iro.h diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000000..0e384661ea --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "allow": [ + "Bash(gh pr view:*)" + ] + } +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 080e70d08b..8057bc70a7 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,6 @@ { - // See http://go.microsoft.com/fwlink/?LinkId=827846 - // for the documentation about the extensions.json format "recommendations": [ + "pioarduino.pioarduino-ide", "platformio.platformio-ide" ], "unwantedRecommendations": [ diff --git a/platformio.ini b/platformio.ini index 1f80fb2a5f..663e0b037c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -468,7 +468,9 @@ build_flags = -g -DCONFIG_IDF_TARGET_ESP32C5=1 -D CONFIG_ASYNC_TCP_USE_WDT=0 -DCO - -DARDUINO_USB_MODE=1 + ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: + ;; ARDUINO_USB_MODE + ;; ARDUINO_USB_CDC_ON_BOOT ${esp32_idf_V5.build_flags} lib_deps = ${esp32_idf_V5.lib_deps} @@ -476,22 +478,22 @@ lib_ignore = ${esp32_idf_V5.lib_ignore} esp_dmx ;; esp_dmx library doesn't support C5 UART registers yet [env:esp32c5dev] -;; ESP32-C5 "devkit C" with 4MB flash - EXPERIMENTAL +;; ESP32-C5 "devkit C" with 4MB flash, no PSRAM - EXPERIMENTAL extends = esp32c5 platform = ${esp32c5.platform} platform_packages = ${esp32c5.platform_packages} -framework = arduino board = esp32-c5-devkitc-1 build_unflags = ${esp32c5.build_unflags} build_flags = ${common.build_flags} ${esp32c5.build_flags} -D WLED_RELEASE_NAME=\"ESP32-C5\" -Wno-volatile -Wno-deprecated-declarations -D WLED_WATCHDOG_TIMEOUT=0 - -DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip - -D WLED_DISABLE_INFRARED ;; library not compatible with -C5 - -D WLED_DISABLE_ESPNOW ;; not yet tested - -D WLED_DISABLE_ALEXA ;; compile errors - -D WLED_DISABLE_WEBSOCKETS ;; not yet tested + -DARDUINO_USB_MODE=1 ;; this flag is mandatory for ESP32-C5 + -DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip + -D WLED_DISABLE_INFRARED ;; library not compatible with -C5 + -D WLED_DISABLE_ESPNOW ;; not yet tested + -D WLED_DISABLE_ALEXA ;; compile errors + -D WLED_DISABLE_WEBSOCKETS ;; not yet tested upload_speed = 460800 lib_deps = ${esp32c5.lib_deps} lib_ignore = ${esp32c5.lib_ignore} @@ -501,7 +503,7 @@ lib_ignore = ${esp32c5.lib_ignore} board_build.partitions = ${esp32.big_partitions} board_build.f_flash = 80000000L board_build.flash_mode = qio -board_build.arduino.memory_type = qio_qspi +board_build.arduino.memory_type = qio_qspi ;; flash config only, this board has no PSRAM monitor_filters = esp32_exception_decoder diff --git a/wled00/NodeStruct.h b/wled00/NodeStruct.h index f436a6519e..9f0965220a 100644 --- a/wled00/NodeStruct.h +++ b/wled00/NodeStruct.h @@ -14,8 +14,15 @@ #define NODE_TYPE_ID_ESP32S2 33 // etc #define NODE_TYPE_ID_ESP32S3 34 #define NODE_TYPE_ID_ESP32C3 35 -#define NODE_TYPE_ID_ESP32C6 36 -#define NODE_TYPE_ID_ESP32C5 41 + +// updated node types from the ESP Easy project +// https://github.com/letscontrolit/ESPEasy/blob/mega/src/src/DataTypes/NodeTypeID.h +#define NODE_TYPE_ID_ESP32C2 37 +#define NODE_TYPE_ID_ESP32H2 38 +#define NODE_TYPE_ID_ESP32C6 39 +#define NODE_TYPE_ID_ESP32C61 40 +#define NODE_TYPE_ID_ESP32C5 41 +#define NODE_TYPE_ID_ESP32P4 42 /*********************************************************************************************\ * NodeStruct diff --git a/wled00/idf_component.yml b/wled00/idf_component.yml new file mode 100644 index 0000000000..d752765ffb --- /dev/null +++ b/wled00/idf_component.yml @@ -0,0 +1,2 @@ +dependencies: + idf: '>=5.1' diff --git a/wled00/idf_component.yml.orig b/wled00/idf_component.yml.orig new file mode 100644 index 0000000000..d752765ffb --- /dev/null +++ b/wled00/idf_component.yml.orig @@ -0,0 +1,2 @@ +dependencies: + idf: '>=5.1' diff --git a/wled00/js_iro.h b/wled00/js_iro.h new file mode 100644 index 0000000000..2dfc6daa6c --- /dev/null +++ b/wled00/js_iro.h @@ -0,0 +1,636 @@ +/* + * More web UI HTML source arrays. + * This file is auto generated, please don't make any changes manually. + * + * Instead, see https://kno.wled.ge/advanced/custom-features/#changing-web-ui + * to find out how to easily modify the web UI source! + */ + +// Autogenerated from wled00/data//iro.js, do not edit!! +const uint16_t JS_iro_length = 9964; +const uint8_t JS_iro[] PROGMEM = { + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xc5, 0x7d, 0x6b, 0x73, 0xe3, 0x36, + 0xb2, 0xe8, 0xf7, 0x5b, 0x75, 0xff, 0x83, 0xcd, 0x64, 0x54, 0x80, 0x04, 0xc1, 0x94, 0x6c, 0x79, + 0xc6, 0x94, 0x71, 0x54, 0xc9, 0xe4, 0x31, 0xb3, 0x9b, 0xd9, 0xc9, 0xc9, 0xcc, 0x66, 0x77, 0xa3, + 0x51, 0x52, 0x14, 0x05, 0x49, 0x18, 0x53, 0xa0, 0x02, 0x82, 0xb2, 0x1d, 0x91, 0xff, 0xfd, 0x56, + 0x03, 0xe0, 0x43, 0x0f, 0x3f, 0xb2, 0xf7, 0xec, 0xbd, 0x95, 0xd4, 0x08, 0xc4, 0xa3, 0x01, 0x34, + 0xba, 0x1b, 0xdd, 0x8d, 0x06, 0xfc, 0xbf, 0xff, 0xd7, 0xe9, 0x3c, 0x93, 0x91, 0x16, 0x89, 0x44, + 0x9a, 0x48, 0xbc, 0xf5, 0x92, 0xe9, 0x67, 0x1e, 0x69, 0x8f, 0x31, 0x7d, 0xbf, 0xe6, 0xc9, 0xfc, + 0x84, 0xdf, 0xad, 0x13, 0xa5, 0xd3, 0x56, 0xcb, 0xcb, 0xe4, 0x8c, 0xcf, 0x85, 0xe4, 0x33, 0xef, + 0xb4, 0x2c, 0x5c, 0x25, 0xb3, 0x2c, 0xe6, 0x23, 0xfb, 0x43, 0x5d, 0x55, 0x26, 0x11, 0x0e, 0xbc, + 0x12, 0x6c, 0x0d, 0xc9, 0xb6, 0x6e, 0xb5, 0xec, 0x2f, 0x0d, 0x57, 0xb3, 0x91, 0x4d, 0x22, 0x89, + 0x03, 0xa4, 0x99, 0xce, 0xf3, 0x94, 0xc7, 0x73, 0x4c, 0x85, 0x4a, 0x00, 0x46, 0x81, 0xf4, 0x52, + 0xa4, 0xa4, 0x1a, 0x1f, 0xde, 0x7a, 0x59, 0xca, 0x4f, 0x52, 0xad, 0x44, 0xa4, 0xbd, 0xe1, 0x26, + 0x54, 0x27, 0x2b, 0x92, 0x12, 0x49, 0x04, 0x49, 0xc8, 0x1d, 0xdb, 0x16, 0xe4, 0x33, 0x1b, 0x4f, + 0x88, 0x62, 0x67, 0x61, 0x24, 0x74, 0xce, 0xef, 0xd0, 0x28, 0x48, 0xf3, 0x45, 0x2e, 0xf3, 0x75, + 0xfe, 0x25, 0xce, 0xd5, 0x7a, 0x99, 0x2f, 0x94, 0x98, 0xe5, 0xc9, 0x6d, 0x9a, 0xaf, 0x64, 0x94, + 0x4b, 0x7d, 0x9b, 0x0b, 0xc9, 0xc7, 0xd1, 0x72, 0x92, 0xff, 0x91, 0x24, 0xf9, 0xaf, 0x89, 0x9a, + 0xe5, 0xbf, 0x76, 0xbb, 0x67, 0x62, 0x58, 0xf6, 0x79, 0xf2, 0xce, 0x62, 0x65, 0x9e, 0x28, 0x04, + 0xfd, 0x89, 0x13, 0x21, 0x4f, 0x24, 0xd6, 0x63, 0x31, 0x61, 0x72, 0x2c, 0x26, 0x43, 0xc5, 0x75, + 0xa6, 0xe4, 0x89, 0x2e, 0xaa, 0x16, 0xf7, 0x48, 0xe3, 0x2d, 0xd4, 0x95, 0x4c, 0xd3, 0x75, 0xa8, + 0xb8, 0xd4, 0x7f, 0x4b, 0x66, 0x7c, 0x28, 0x5b, 0x2d, 0x49, 0x15, 0x5f, 0x25, 0x1b, 0xfe, 0x7a, + 0x29, 0xe2, 0x19, 0xd2, 0xb8, 0x6e, 0xb4, 0x84, 0x6e, 0x88, 0xb0, 0x0d, 0x15, 0xe1, 0x24, 0x23, + 0x09, 0x89, 0x59, 0xa8, 0x16, 0xd9, 0x8a, 0x4b, 0x9d, 0x0e, 0xc5, 0x1c, 0x49, 0xf6, 0x0e, 0x6d, + 0x0b, 0x22, 0x31, 0x39, 0xbf, 0xae, 0x0a, 0x68, 0xcc, 0xe5, 0x42, 0x2f, 0x31, 0x0c, 0x50, 0xb0, + 0xb1, 0x80, 0xe9, 0x9f, 0x0f, 0xd5, 0x41, 0x85, 0xa1, 0xea, 0x74, 0xb0, 0xa0, 0xeb, 0x2c, 0x5d, + 0xa2, 0x78, 0xac, 0x26, 0xd8, 0x40, 0xcc, 0xe2, 0xf8, 0x94, 0x89, 0x56, 0x0b, 0x49, 0x1a, 0xc1, + 0x98, 0x14, 0x97, 0x4c, 0x60, 0x62, 0xf3, 0x75, 0xab, 0xe5, 0x12, 0x74, 0xc6, 0xe7, 0x61, 0x16, + 0xeb, 0x1f, 0x55, 0xb2, 0x4e, 0x4d, 0x57, 0x1c, 0xf0, 0xb0, 0x97, 0xbf, 0x49, 0xc4, 0xec, 0xc4, + 0x67, 0x8c, 0xc9, 0x31, 0x9f, 0x00, 0xcc, 0x31, 0x9f, 0xec, 0xb5, 0x1d, 0xf3, 0x09, 0x2e, 0x51, + 0x96, 0x30, 0x49, 0x6f, 0xf8, 0xbd, 0xeb, 0x0c, 0x65, 0x0c, 0xb0, 0x33, 0xc7, 0x40, 0x1e, 0x31, + 0xd7, 0xfc, 0xc4, 0x7c, 0xba, 0xd2, 0xa4, 0x91, 0x0b, 0x6d, 0x22, 0x83, 0xae, 0x84, 0x64, 0x0d, + 0x14, 0xda, 0x3c, 0x41, 0x94, 0x45, 0x22, 0x67, 0x5b, 0x20, 0xbb, 0x40, 0x93, 0x35, 0xf4, 0x1c, + 0x48, 0x72, 0xc3, 0xef, 0x03, 0x41, 0x14, 0x9f, 0x07, 0x8a, 0xc8, 0x00, 0x00, 0x13, 0x61, 0x7f, + 0x78, 0xe0, 0x93, 0xc4, 0x26, 0x63, 0xfb, 0x13, 0xb9, 0x9f, 0x44, 0xa6, 0x5a, 0x65, 0x91, 0x4e, + 0x54, 0x60, 0xa7, 0x57, 0x94, 0xc3, 0x5f, 0xd1, 0x8d, 0x4c, 0x66, 0xbc, 0xd5, 0x72, 0x09, 0xc4, + 0x31, 0xe1, 0xf5, 0x68, 0xde, 0x03, 0x15, 0x94, 0xc4, 0x51, 0x21, 0xb7, 0x2e, 0x7f, 0x6b, 0xe9, + 0x0a, 0x08, 0x9c, 0x9a, 0x01, 0x32, 0x4d, 0xcc, 0x47, 0x94, 0x48, 0xcd, 0xef, 0x34, 0x6b, 0xd4, + 0xbd, 0xb5, 0x75, 0xdd, 0x82, 0x31, 0x26, 0x71, 0x05, 0x58, 0x8c, 0x6e, 0x91, 0xa6, 0x82, 0x68, + 0x2a, 0xa8, 0xa4, 0x42, 0xce, 0xf8, 0xdd, 0xfb, 0x39, 0xd2, 0xb8, 0xd3, 0xc3, 0x66, 0x06, 0xc3, + 0x8a, 0x70, 0x87, 0xf2, 0x5a, 0x53, 0x59, 0x52, 0x83, 0x04, 0x6a, 0x28, 0x09, 0x00, 0x09, 0xa6, + 0xa9, 0x1c, 0xcb, 0x09, 0x2e, 0x57, 0x5c, 0xd0, 0xa4, 0xec, 0x43, 0xd0, 0xc4, 0x4d, 0xf9, 0x08, + 0x47, 0x6b, 0x0a, 0x09, 0x18, 0x83, 0xed, 0xae, 0x1e, 0x73, 0x58, 0x71, 0x01, 0x11, 0x35, 0xa9, + 0x01, 0x93, 0x53, 0x81, 0x6b, 0xc2, 0x8a, 0x2c, 0x6b, 0x69, 0x9a, 0xc0, 0x07, 0x9d, 0x86, 0x29, + 0x67, 0x06, 0xf3, 0x92, 0xf9, 0x7f, 0x7a, 0xc4, 0xdb, 0x1d, 0x30, 0x30, 0xf0, 0xa9, 0xe2, 0xe1, + 0x4d, 0xe1, 0x66, 0x02, 0x43, 0x2a, 0xea, 0x11, 0x72, 0x18, 0x21, 0x3a, 0xd5, 0x74, 0xde, 0x6a, + 0x21, 0x4d, 0xe7, 0xec, 0xd4, 0xc7, 0xad, 0x56, 0x8f, 0x31, 0x96, 0x5a, 0x36, 0xd1, 0x38, 0xcf, + 0xc5, 0x29, 0x63, 0x2b, 0x3a, 0xe3, 0xd3, 0x24, 0x93, 0x11, 0xff, 0x89, 0xcb, 0x19, 0x57, 0x42, + 0x2e, 0x70, 0xab, 0x85, 0xc4, 0xb1, 0x02, 0x82, 0x8e, 0x64, 0xe6, 0xb9, 0xc4, 0x28, 0xc3, 0x0d, + 0x5a, 0xcd, 0x90, 0x45, 0x8e, 0xa3, 0xd8, 0x92, 0xdf, 0xcd, 0x6a, 0xa5, 0x34, 0x4d, 0x94, 0x46, + 0xbb, 0x52, 0xd9, 0x4d, 0x41, 0xd2, 0x19, 0xe5, 0x5d, 0x0d, 0xff, 0x16, 0x78, 0xa8, 0x61, 0xa4, + 0xc9, 0x1a, 0xe1, 0x21, 0xb6, 0xb3, 0x50, 0x4c, 0x30, 0x4b, 0xa6, 0x24, 0x63, 0x88, 0x33, 0x24, + 0x99, 0xc6, 0x74, 0x86, 0x69, 0x42, 0x80, 0xdb, 0xd6, 0x24, 0x66, 0x92, 0x66, 0x44, 0xd2, 0x8c, + 0x9d, 0xf6, 0x48, 0x62, 0x26, 0x61, 0x04, 0xe6, 0x0d, 0x4a, 0x08, 0x27, 0x46, 0xbc, 0x70, 0x4c, + 0x24, 0xbd, 0x25, 0x16, 0xcc, 0x29, 0x63, 0x09, 0x4d, 0x6e, 0x25, 0x57, 0x1f, 0x7e, 0xfe, 0xfe, + 0xdb, 0x98, 0x83, 0x44, 0x21, 0x96, 0x73, 0x48, 0x4c, 0x2c, 0x35, 0x66, 0xa3, 0x5b, 0xc4, 0x71, + 0x90, 0x61, 0x32, 0x43, 0x02, 0x9a, 0xab, 0x53, 0x96, 0xb5, 0x5a, 0x21, 0xe2, 0xb8, 0x39, 0xe5, + 0x0f, 0x08, 0xa6, 0xaa, 0xeb, 0xc9, 0x92, 0xd4, 0xe2, 0x20, 0x22, 0x21, 0x99, 0x93, 0x25, 0xd9, + 0x90, 0x19, 0x59, 0x90, 0x29, 0x88, 0x1d, 0x4d, 0x65, 0x9e, 0x7f, 0x26, 0x6b, 0x36, 0x2d, 0x57, + 0x5f, 0xcc, 0x51, 0xcc, 0xd8, 0x5d, 0xab, 0x85, 0x62, 0x66, 0x17, 0x3c, 0x1b, 0x65, 0x63, 0x7f, + 0x12, 0xac, 0x81, 0xf8, 0x88, 0x6f, 0xc9, 0x0f, 0x93, 0x88, 0xf9, 0x44, 0x50, 0xc9, 0xbe, 0x42, + 0x82, 0xca, 0x7a, 0xe7, 0xd0, 0x15, 0xf7, 0x9c, 0x32, 0x9b, 0xd6, 0x54, 0x30, 0x60, 0x1b, 0xa0, + 0x13, 0xde, 0xe9, 0xb9, 0xb9, 0x30, 0x34, 0x67, 0xd3, 0x71, 0x34, 0xc1, 0x79, 0x3e, 0x87, 0x61, + 0xdc, 0xf0, 0x7b, 0xc6, 0xe6, 0xf0, 0x03, 0x5f, 0x40, 0xeb, 0x0c, 0xbe, 0x21, 0x81, 0xa1, 0x9e, + 0xc3, 0xf6, 0x90, 0xc7, 0x29, 0x3f, 0x81, 0xc5, 0x0b, 0x99, 0x3f, 0x0c, 0xaf, 0xd7, 0xc3, 0xb0, + 0xd3, 0x31, 0xdd, 0x18, 0x78, 0x21, 0x90, 0xe9, 0xe3, 0xc0, 0xb6, 0x50, 0xab, 0x84, 0x66, 0xa9, + 0x76, 0x6e, 0x26, 0x5a, 0x88, 0x39, 0x5a, 0xb2, 0x1b, 0x24, 0x89, 0x26, 0x73, 0x36, 0xcf, 0xf3, + 0xbb, 0x0a, 0x83, 0x56, 0x5e, 0x91, 0x14, 0x13, 0x14, 0x32, 0xed, 0x84, 0xe7, 0x1c, 0x7e, 0x4f, + 0x59, 0xd8, 0x6a, 0xa1, 0x05, 0x5b, 0xe4, 0xf9, 0x78, 0x82, 0x2d, 0x35, 0x87, 0x44, 0xd3, 0x28, + 0xcf, 0x97, 0x44, 0x97, 0xf2, 0x7d, 0xd9, 0x10, 0x29, 0xb3, 0x56, 0x0b, 0xcd, 0xd8, 0xb2, 0x12, + 0xfd, 0x34, 0xc6, 0x4b, 0xf8, 0x97, 0x68, 0x6a, 0x11, 0x6e, 0xa7, 0x28, 0xe6, 0x28, 0x63, 0x30, + 0x8a, 0xe5, 0x29, 0x8b, 0xf3, 0xdc, 0xb6, 0x5d, 0x36, 0x76, 0x39, 0xbc, 0xd5, 0x41, 0x05, 0x34, + 0xce, 0xf3, 0xb8, 0x51, 0x76, 0x0a, 0x92, 0x4b, 0xd2, 0x70, 0xbd, 0xe6, 0x72, 0x66, 0xb7, 0xc0, + 0x25, 0x36, 0x70, 0xed, 0xf6, 0xca, 0x62, 0x02, 0xe8, 0x43, 0x1b, 0xb6, 0xa1, 0x92, 0xdf, 0xe9, + 0x0f, 0x62, 0x1a, 0x5b, 0x5e, 0xb3, 0x18, 0x65, 0x7d, 0x10, 0x00, 0x1b, 0xc6, 0x96, 0xd8, 0x60, + 0xe8, 0x44, 0x0f, 0x41, 0xe4, 0xa5, 0x5c, 0xe9, 0xaf, 0xf9, 0x3c, 0x51, 0x1c, 0x2d, 0x49, 0x8c, + 0x0b, 0x2f, 0x59, 0x3b, 0x21, 0x25, 0x0c, 0x6e, 0xcd, 0xee, 0xb6, 0x09, 0xe3, 0x8c, 0x33, 0xcf, + 0xc3, 0x45, 0xcc, 0x96, 0x4d, 0xe8, 0xe4, 0x88, 0x54, 0xab, 0xda, 0x09, 0x1a, 0xb3, 0x25, 0x2e, + 0x4a, 0x01, 0x12, 0x75, 0x3a, 0x44, 0x17, 0x98, 0x08, 0x9a, 0xb0, 0x99, 0xc3, 0x54, 0xd6, 0x6a, + 0xd5, 0x10, 0x4e, 0x77, 0x21, 0x98, 0x9d, 0x32, 0x62, 0x59, 0x49, 0xc4, 0x51, 0xb7, 0x3b, 0xc4, + 0xae, 0xd9, 0x38, 0x9a, 0xb4, 0x5a, 0xf7, 0x08, 0x7e, 0xf1, 0xd0, 0xd6, 0x5b, 0x37, 0x2b, 0x4c, + 0x4d, 0x85, 0xbf, 0x21, 0xf8, 0x25, 0x86, 0x24, 0x81, 0x07, 0x16, 0x0e, 0xa4, 0x3f, 0x8c, 0xae, + 0x17, 0x15, 0xd8, 0x4e, 0x07, 0x7f, 0x8b, 0x16, 0x50, 0x71, 0x31, 0xee, 0x74, 0xaa, 0x9f, 0x06, + 0xf3, 0x7d, 0x55, 0xaa, 0x17, 0xd5, 0xda, 0x08, 0xc7, 0xfc, 0xd8, 0x51, 0xbe, 0xce, 0x73, 0x6f, + 0x9a, 0x24, 0x31, 0x0f, 0x9b, 0xe2, 0x1d, 0xcb, 0x56, 0xcb, 0x29, 0x0d, 0xd2, 0x34, 0xc4, 0xb8, + 0x22, 0x84, 0xaf, 0x94, 0x0a, 0xef, 0xa9, 0x48, 0xcd, 0x2f, 0xd2, 0x18, 0x97, 0x5b, 0x8d, 0x62, + 0xfe, 0x50, 0x5d, 0xeb, 0xa6, 0xe2, 0xf1, 0x15, 0xd2, 0x63, 0x35, 0x31, 0x43, 0x70, 0xed, 0x1d, + 0xd0, 0x91, 0x44, 0x47, 0x98, 0xf4, 0xc1, 0xe1, 0x94, 0x62, 0x10, 0x08, 0x52, 0xcc, 0x91, 0x07, + 0xaa, 0xa0, 0x5c, 0x34, 0x6a, 0xe4, 0xb9, 0x27, 0xb3, 0xd5, 0x94, 0xab, 0x23, 0xad, 0x22, 0x03, + 0x9b, 0x38, 0x01, 0x66, 0x66, 0x33, 0xac, 0x3b, 0xa4, 0x89, 0xdd, 0x4a, 0x98, 0xd9, 0x95, 0xca, + 0x0d, 0x76, 0x68, 0x15, 0xb9, 0x08, 0x59, 0x86, 0x25, 0xda, 0x6e, 0xd6, 0x44, 0x57, 0xaa, 0x4b, + 0xa5, 0xcf, 0x48, 0xb3, 0xf9, 0x24, 0x44, 0x16, 0x80, 0x8c, 0x40, 0x57, 0x05, 0xa2, 0x5e, 0x87, + 0x79, 0xb9, 0x0e, 0x5e, 0xd7, 0x33, 0x8a, 0x92, 0x3f, 0x19, 0x69, 0x9a, 0x72, 0xa3, 0x1d, 0x71, + 0xa5, 0xef, 0x41, 0x48, 0xe2, 0x40, 0x8f, 0xe5, 0x84, 0x1d, 0x4c, 0x44, 0xb4, 0x5a, 0xa7, 0xb0, + 0x3d, 0x29, 0xaa, 0x79, 0xaa, 0x91, 0xc4, 0x23, 0xd1, 0xf1, 0xd6, 0x77, 0x5e, 0xe0, 0x56, 0x74, + 0xe4, 0x79, 0x41, 0xa3, 0xaf, 0x9f, 0x50, 0xb5, 0xbb, 0x58, 0x41, 0xeb, 0xa4, 0x2e, 0x89, 0x0c, + 0xea, 0x6e, 0xf8, 0x3d, 0x0c, 0x01, 0x49, 0xc6, 0x47, 0x5e, 0x14, 0x87, 0x69, 0xfa, 0xb7, 0x70, + 0xc5, 0xcd, 0xa8, 0xdc, 0xb7, 0x17, 0xc8, 0xc0, 0xa5, 0x1a, 0xb9, 0xa6, 0x56, 0x20, 0x71, 0x9e, + 0x7b, 0xa5, 0x56, 0x63, 0x8a, 0x6b, 0xc2, 0xf0, 0x52, 0x7d, 0x1f, 0x5b, 0x48, 0xd8, 0x08, 0x0c, + 0x4d, 0x4d, 0x0e, 0x39, 0x58, 0x2e, 0x81, 0x33, 0x1a, 0xa5, 0xe9, 0x47, 0xd0, 0x77, 0x84, 0x95, + 0x04, 0xc7, 0x56, 0x55, 0xb5, 0x5a, 0xa8, 0xae, 0xe8, 0x79, 0x44, 0x31, 0x2b, 0xed, 0x95, 0xa1, + 0xb9, 0x04, 0x74, 0x51, 0x85, 0x45, 0xab, 0x65, 0x52, 0x22, 0xcf, 0xe7, 0x08, 0xe6, 0xea, 0x79, + 0x66, 0x7d, 0x85, 0xa9, 0x14, 0x9b, 0x22, 0xac, 0x5a, 0x2d, 0x31, 0x8e, 0x27, 0x80, 0xc5, 0x71, + 0x3c, 0xb1, 0x35, 0x63, 0x02, 0x59, 0xb8, 0x80, 0xfe, 0xbd, 0xa4, 0x5c, 0x97, 0x56, 0xcb, 0xb3, + 0x13, 0x1b, 0xf7, 0x26, 0x23, 0x94, 0x32, 0x79, 0x6a, 0x90, 0x05, 0x5a, 0xe9, 0x3a, 0x0e, 0x23, + 0x8e, 0xce, 0x5e, 0x87, 0x6b, 0x9d, 0x29, 0xfe, 0xe5, 0x19, 0xf4, 0x84, 0x89, 0x64, 0x08, 0x45, + 0x4c, 0x52, 0x9d, 0xfc, 0x90, 0xdc, 0x72, 0xf5, 0x3a, 0x4c, 0x39, 0xc2, 0x18, 0xd4, 0xe4, 0x51, + 0x14, 0x48, 0x4c, 0xd3, 0x58, 0x44, 0x1c, 0xf5, 0x31, 0x11, 0x23, 0xa4, 0xf2, 0x5c, 0xd3, 0x70, + 0x36, 0xfb, 0x76, 0xc3, 0xa5, 0xfe, 0x41, 0xa4, 0x9a, 0x4b, 0xae, 0x90, 0x24, 0x1b, 0x23, 0xcd, + 0x35, 0xd5, 0x79, 0x0e, 0xff, 0xb2, 0x6d, 0x81, 0x31, 0xd0, 0x02, 0xd0, 0x84, 0xb3, 0x1d, 0x8e, + 0x35, 0xc1, 0x81, 0x17, 0x8b, 0x54, 0x7b, 0x20, 0x61, 0x5b, 0x2d, 0x4f, 0x87, 0x0b, 0xb3, 0x4a, + 0xee, 0x73, 0x9e, 0xa8, 0x95, 0x4b, 0x9f, 0xf2, 0x56, 0x4b, 0x1a, 0xd5, 0x7d, 0x64, 0x68, 0xac, + 0x49, 0x39, 0xc1, 0x31, 0x39, 0xd6, 0x6a, 0x79, 0xb3, 0x50, 0x2e, 0xb8, 0x4a, 0xb2, 0x34, 0xbe, + 0xff, 0xc0, 0xf5, 0x5b, 0x29, 0xb9, 0x7a, 0xf3, 0xf1, 0xdd, 0x0f, 0x0e, 0x22, 0x3a, 0xc4, 0xcb, + 0xaf, 0x77, 0xb1, 0x90, 0x37, 0xc1, 0xc8, 0xe2, 0x65, 0xe4, 0xfa, 0xc8, 0x73, 0x43, 0xbc, 0x62, + 0x54, 0x4e, 0xe4, 0x2b, 0xad, 0x95, 0x98, 0x66, 0x9a, 0xff, 0xed, 0x03, 0xf2, 0x96, 0x5a, 0xaf, + 0x83, 0xb3, 0xb3, 0xdb, 0xdb, 0x5b, 0x7a, 0x7b, 0x4e, 0x13, 0xb5, 0x38, 0xeb, 0x5d, 0x5d, 0x5d, + 0x9d, 0x19, 0x48, 0x1e, 0xd9, 0x47, 0x6a, 0x60, 0x78, 0xe6, 0xdf, 0x07, 0x00, 0x3c, 0xf6, 0xe4, + 0xb0, 0xc0, 0x28, 0xdd, 0xed, 0xc7, 0x30, 0x67, 0x43, 0xaa, 0x6e, 0x9a, 0x3a, 0x3e, 0xe8, 0xee, + 0x7a, 0x6c, 0xc5, 0xc4, 0x04, 0xad, 0x28, 0x87, 0x75, 0x1a, 0xb9, 0x5f, 0xd0, 0x8f, 0x9b, 0xe6, + 0xde, 0x0d, 0xda, 0xd3, 0xfc, 0x80, 0x2d, 0x2d, 0x97, 0xee, 0x28, 0x43, 0x64, 0x4d, 0xee, 0xc9, + 0x2d, 0xb9, 0x01, 0xb2, 0xba, 0x5f, 0x73, 0x20, 0xe7, 0x4a, 0x31, 0x93, 0xb4, 0x61, 0x9d, 0xec, + 0x48, 0x46, 0x14, 0xb2, 0x15, 0xe5, 0xb0, 0x6f, 0x22, 0x89, 0x87, 0x5a, 0xdd, 0xdb, 0x4d, 0xf9, + 0xc8, 0x4e, 0x77, 0x63, 0x44, 0xee, 0x1a, 0x74, 0x43, 0x23, 0xd6, 0xee, 0x19, 0x0a, 0xd9, 0x4d, + 0x69, 0x83, 0x7c, 0x84, 0x3d, 0xac, 0xd5, 0x52, 0xe3, 0x90, 0x46, 0x13, 0x72, 0xcb, 0xc2, 0xd1, + 0xfd, 0xe8, 0xde, 0xd6, 0xb4, 0x1b, 0x6a, 0x10, 0x52, 0x11, 0x28, 0x22, 0x68, 0x34, 0x9a, 0x82, + 0xea, 0x24, 0x69, 0xc4, 0x04, 0x8d, 0x30, 0x15, 0xa0, 0xe7, 0x04, 0xc8, 0x5b, 0xab, 0x44, 0x27, + 0xd0, 0x97, 0x27, 0xe4, 0xc9, 0x4d, 0xab, 0x75, 0x43, 0xab, 0x1c, 0xaa, 0x8c, 0x7a, 0x3c, 0x82, + 0x36, 0x73, 0x26, 0xf9, 0xed, 0xc9, 0x0d, 0x5a, 0x93, 0x5b, 0x1c, 0xa0, 0x3a, 0xe7, 0xad, 0xc9, + 0x21, 0xf3, 0xe6, 0x4c, 0xd9, 0x0d, 0x99, 0xbb, 0xb6, 0xec, 0x0f, 0x4c, 0xee, 0x5b, 0xad, 0x7b, + 0x9a, 0x66, 0x53, 0x34, 0x87, 0x7a, 0xd6, 0x92, 0x5a, 0x93, 0x39, 0x4d, 0x75, 0xa8, 0x79, 0x9e, + 0x23, 0x97, 0x02, 0x4e, 0xb2, 0x70, 0x8c, 0x71, 0x75, 0x4b, 0xe6, 0xf4, 0x96, 0x29, 0xb2, 0x64, + 0x73, 0xa3, 0xf8, 0x93, 0x39, 0x5d, 0x35, 0x36, 0xc3, 0x39, 0xfd, 0xdc, 0x6a, 0xa1, 0x39, 0xfd, + 0xcc, 0x5c, 0xf3, 0x52, 0x2f, 0xba, 0xa1, 0x0b, 0xae, 0xbf, 0xe1, 0x4a, 0x6c, 0xf8, 0xec, 0x03, + 0x14, 0x7c, 0xa7, 0x92, 0x95, 0xb1, 0x6c, 0x5b, 0xad, 0x77, 0xa6, 0x41, 0xd9, 0x62, 0x04, 0x1f, + 0x46, 0xa1, 0x9e, 0xd3, 0xcf, 0x38, 0x98, 0xd3, 0xcf, 0xe4, 0xe1, 0xc6, 0x68, 0x6d, 0x6a, 0x61, + 0xb2, 0xc4, 0x76, 0x00, 0x8f, 0xf5, 0x63, 0x47, 0x02, 0x73, 0x59, 0xad, 0x13, 0xc9, 0xa5, 0xfe, + 0x87, 0x88, 0xe3, 0x77, 0x49, 0x26, 0x35, 0x68, 0x7f, 0x87, 0xb9, 0xa8, 0x1c, 0x7c, 0xa3, 0xf0, + 0x1b, 0x31, 0x73, 0x2d, 0x12, 0xbb, 0x11, 0xcf, 0x71, 0x25, 0x7e, 0x9f, 0x37, 0x02, 0xc6, 0xe2, + 0x07, 0x86, 0xf2, 0x13, 0x8f, 0xb8, 0xd8, 0x70, 0x57, 0xf7, 0x91, 0x42, 0xbb, 0xb8, 0xa7, 0x0d, + 0x38, 0xe9, 0x32, 0xc9, 0xe2, 0xd9, 0xeb, 0xb2, 0xc1, 0xdf, 0xd7, 0xb3, 0x50, 0x73, 0xb7, 0xeb, + 0x3d, 0x50, 0x6a, 0x51, 0x47, 0x6e, 0xb1, 0x35, 0x24, 0x0f, 0x48, 0x00, 0xd6, 0x92, 0x98, 0x45, + 0xee, 0x11, 0x34, 0xa7, 0x33, 0x26, 0x31, 0x4d, 0x9c, 0x09, 0x91, 0x8e, 0xd2, 0x53, 0xd0, 0x12, + 0x93, 0x51, 0x1a, 0x08, 0xea, 0x1c, 0x00, 0x92, 0x4a, 0x06, 0xb6, 0x83, 0xd5, 0xe4, 0x65, 0x6d, + 0x80, 0x82, 0x4a, 0x2f, 0xa9, 0x1c, 0x87, 0xc6, 0xb7, 0x61, 0x12, 0x54, 0xc0, 0xbe, 0xe7, 0x94, + 0xd1, 0xe2, 0x28, 0x36, 0xca, 0x39, 0x1c, 0xcd, 0xae, 0x06, 0x5f, 0x58, 0x05, 0xd8, 0x8d, 0x9e, + 0xcc, 0x4a, 0x2a, 0xda, 0x23, 0xd9, 0x63, 0x73, 0x33, 0xcc, 0xfe, 0xce, 0x31, 0x7b, 0x39, 0x53, + 0x33, 0x51, 0x68, 0xc0, 0x34, 0x09, 0x59, 0xc9, 0x2f, 0x25, 0x76, 0xc8, 0x01, 0x74, 0x6c, 0xa6, + 0xfd, 0x95, 0xb3, 0x90, 0xc2, 0x56, 0x2b, 0x74, 0xf6, 0xc9, 0xfb, 0x72, 0xb5, 0x43, 0x50, 0x78, + 0x46, 0xa1, 0xe3, 0xfe, 0x72, 0xe7, 0x0f, 0xc2, 0x9a, 0xb8, 0x16, 0x5c, 0x1b, 0xa5, 0xfe, 0xb5, + 0x05, 0x69, 0xcc, 0xd1, 0x77, 0xc8, 0xb0, 0x80, 0x82, 0x81, 0xed, 0x95, 0x23, 0x0c, 0xf4, 0x5e, + 0xda, 0x10, 0xa6, 0xf8, 0x83, 0x0c, 0xd7, 0xe9, 0x32, 0x71, 0xda, 0xbc, 0x45, 0x51, 0x9e, 0xa3, + 0xc5, 0xc3, 0xa5, 0x68, 0x43, 0x66, 0x18, 0x93, 0x0f, 0x7b, 0xe2, 0x14, 0x84, 0x29, 0x99, 0x3b, + 0x6f, 0x02, 0x4d, 0x86, 0x80, 0x82, 0x55, 0x69, 0x2a, 0x97, 0xcc, 0x5d, 0xa1, 0x10, 0x93, 0x90, + 0x46, 0x61, 0x1c, 0x03, 0x13, 0x54, 0x03, 0xda, 0xd4, 0x23, 0x6b, 0x72, 0x4d, 0x39, 0xa8, 0x63, + 0xb9, 0xc8, 0x08, 0x6d, 0x4c, 0xa6, 0x06, 0xfc, 0x0d, 0x9b, 0x03, 0x79, 0x80, 0x9e, 0x62, 0x34, + 0x0b, 0xa3, 0x1f, 0x36, 0x8d, 0xfa, 0xa6, 0xf8, 0xb7, 0xa2, 0x3f, 0x25, 0xce, 0x16, 0x66, 0xc2, + 0x2d, 0xd4, 0xa6, 0x94, 0xcc, 0x20, 0xf9, 0x39, 0xf3, 0xd2, 0xcd, 0xc2, 0xe8, 0x24, 0x66, 0x75, + 0xf2, 0x9c, 0x97, 0xca, 0x7b, 0xc9, 0x42, 0x99, 0xd1, 0x75, 0x52, 0xe6, 0x0f, 0xd3, 0xeb, 0xca, + 0xec, 0x48, 0x77, 0x3c, 0x27, 0x11, 0xcb, 0xc6, 0x29, 0x18, 0xa4, 0x8e, 0xd1, 0x1d, 0xb0, 0xd1, + 0x39, 0x63, 0x2c, 0xa2, 0xe0, 0xc9, 0x02, 0xb1, 0x1f, 0x44, 0x34, 0x4e, 0xa2, 0x30, 0x06, 0x3d, + 0xa2, 0xaa, 0x83, 0xf1, 0x56, 0xb3, 0x88, 0x40, 0x7b, 0x6b, 0x13, 0x5a, 0x43, 0xb5, 0xd6, 0xa1, + 0x1b, 0x0a, 0x7c, 0xd9, 0xc4, 0xed, 0x4b, 0xb3, 0x24, 0x32, 0xee, 0x48, 0x1a, 0x29, 0x1e, 0x6a, + 0x0e, 0x8a, 0x1c, 0x98, 0x84, 0x68, 0x03, 0x5e, 0x0c, 0x3e, 0xda, 0x2b, 0x76, 0x9e, 0x86, 0xe3, + 0xfb, 0x7a, 0xdf, 0xf7, 0xfd, 0x33, 0x40, 0x04, 0x71, 0x5d, 0x04, 0xc7, 0x5b, 0x23, 0x57, 0x4c, + 0x32, 0x6b, 0x48, 0x37, 0x76, 0xc8, 0x7a, 0xd6, 0xcb, 0x53, 0xc6, 0x36, 0x0e, 0x17, 0xc6, 0x98, + 0x43, 0xd9, 0x38, 0x6b, 0xf8, 0xd1, 0x26, 0x4e, 0xd3, 0xd4, 0x74, 0x16, 0xea, 0x90, 0x6d, 0x70, + 0x00, 0xfa, 0x8e, 0xd8, 0x6d, 0xc1, 0x3e, 0x5b, 0xe5, 0xce, 0x52, 0x91, 0xf3, 0xf6, 0xc1, 0xf4, + 0x52, 0x8c, 0x49, 0xc8, 0x50, 0xb5, 0x9e, 0x79, 0x7e, 0x87, 0xe9, 0x03, 0xfa, 0x14, 0x99, 0xb3, + 0xcd, 0x83, 0x65, 0x31, 0xec, 0x64, 0x79, 0x1e, 0xc2, 0xb2, 0xcd, 0x5b, 0xad, 0x10, 0xe4, 0xc9, + 0x7b, 0x60, 0xca, 0xf7, 0x46, 0x51, 0x14, 0x65, 0x45, 0x36, 0x37, 0x25, 0x79, 0x6e, 0x34, 0xd2, + 0x43, 0x6a, 0x73, 0x86, 0x80, 0x31, 0x38, 0x33, 0xab, 0x11, 0x9b, 0x1f, 0x99, 0xe7, 0x60, 0x2e, + 0x64, 0xce, 0xb7, 0x33, 0xce, 0x26, 0x44, 0xe1, 0xba, 0x96, 0xc4, 0xfc, 0xa8, 0x99, 0x2b, 0xc7, + 0xd9, 0x24, 0xcf, 0x3d, 0xa3, 0x0b, 0x00, 0x5d, 0x66, 0xc6, 0x28, 0xe0, 0xd1, 0x0d, 0x9f, 0xb9, + 0x4f, 0x00, 0x65, 0x94, 0x68, 0xa8, 0xe8, 0xba, 0x00, 0xe8, 0xae, 0x8b, 0x02, 0x69, 0xb2, 0x21, + 0x4b, 0xc2, 0x49, 0x6c, 0x45, 0x90, 0xdc, 0x13, 0x30, 0x64, 0x9e, 0xe7, 0x35, 0x77, 0x83, 0x2a, + 0xcb, 0xc5, 0x42, 0xbe, 0xb7, 0x47, 0x14, 0xa7, 0xe5, 0x32, 0xb6, 0x5a, 0x96, 0x8f, 0xee, 0x00, + 0x0c, 0xe0, 0xca, 0x0d, 0x49, 0xc8, 0x93, 0x4d, 0xab, 0x55, 0x69, 0x4c, 0x1b, 0xab, 0xb5, 0xb4, + 0x5a, 0x2e, 0x71, 0x0a, 0xb6, 0x9e, 0xcb, 0x42, 0x2e, 0xe5, 0x54, 0x62, 0x57, 0x03, 0x14, 0x63, + 0x97, 0xc4, 0xa4, 0x9a, 0xda, 0x01, 0x58, 0x57, 0x00, 0x80, 0x5d, 0xd2, 0x80, 0xae, 0xb2, 0x51, + 0x95, 0xae, 0x2b, 0x83, 0xf8, 0xd3, 0x05, 0x12, 0x60, 0x31, 0x36, 0x44, 0x41, 0x84, 0xad, 0xfa, + 0x36, 0x13, 0xf3, 0x39, 0x9f, 0x39, 0xb1, 0x5e, 0x44, 0xa1, 0x8e, 0xc0, 0x21, 0xb9, 0x5d, 0xd1, + 0xc4, 0x99, 0x90, 0x45, 0x6d, 0x76, 0xd6, 0x7a, 0xe5, 0x6c, 0xef, 0xb4, 0x62, 0x08, 0x7e, 0xd2, + 0xd2, 0x45, 0xa8, 0xee, 0xb7, 0xe2, 0x50, 0x05, 0x40, 0x07, 0xd0, 0x05, 0x9d, 0xe1, 0x62, 0x45, + 0x23, 0x70, 0x6d, 0x47, 0xd0, 0x7b, 0x05, 0xfe, 0xdb, 0xd2, 0x7c, 0x05, 0x58, 0xc7, 0xdc, 0xc1, + 0x23, 0x6d, 0xb5, 0xe6, 0x28, 0x53, 0xe0, 0xf5, 0x61, 0xf2, 0x00, 0x76, 0xd3, 0x03, 0xfb, 0xb7, + 0x83, 0x43, 0x0f, 0x10, 0x73, 0x2b, 0x9a, 0xc9, 0x95, 0x55, 0x4e, 0xaa, 0x24, 0xd2, 0x98, 0x20, + 0x55, 0x39, 0xb9, 0xbe, 0x45, 0xca, 0x19, 0xf1, 0x98, 0x88, 0x3c, 0x7f, 0xd0, 0x31, 0x9d, 0xe7, + 0x48, 0xb8, 0xbd, 0x1e, 0x71, 0x30, 0xce, 0x01, 0xe7, 0xc6, 0x4c, 0x8f, 0x59, 0xe5, 0x04, 0x38, + 0x65, 0x06, 0x72, 0x84, 0x8d, 0xf4, 0x52, 0x7b, 0xfb, 0xb4, 0xed, 0xdf, 0x20, 0xef, 0x78, 0xd1, + 0x21, 0xfe, 0x24, 0x2e, 0x94, 0xdd, 0x7b, 0x14, 0x5d, 0x57, 0x4e, 0x3c, 0xe8, 0x43, 0x1a, 0xf1, + 0x9c, 0x31, 0x7f, 0x98, 0x5d, 0xab, 0x52, 0x3c, 0x67, 0x9d, 0x0e, 0x56, 0xe3, 0xcc, 0x78, 0x7b, + 0xe0, 0xd7, 0x7a, 0x49, 0xec, 0xc8, 0x38, 0xf8, 0x88, 0x78, 0x63, 0x05, 0xfe, 0x28, 0x51, 0xd6, + 0x34, 0x3b, 0x1a, 0xda, 0xb1, 0x45, 0x71, 0x55, 0x7d, 0xb1, 0x47, 0x0f, 0xcc, 0x1f, 0x8a, 0xeb, + 0x4a, 0xa3, 0x11, 0xe0, 0xa4, 0xb4, 0x1e, 0x1b, 0x7b, 0x96, 0x45, 0xb9, 0xcc, 0x56, 0x5c, 0x85, + 0xd3, 0x18, 0xc6, 0x5e, 0x7f, 0x80, 0x91, 0x44, 0x60, 0xfa, 0x72, 0x2e, 0x16, 0x99, 0x2d, 0x3f, + 0xf5, 0x49, 0xcd, 0x65, 0x60, 0xa1, 0x2b, 0x7a, 0xab, 0x84, 0x76, 0x65, 0x98, 0x58, 0x1e, 0xa5, + 0xf6, 0x80, 0xaf, 0x72, 0x6f, 0x68, 0xa2, 0x8c, 0xe7, 0x44, 0x35, 0xe9, 0x60, 0x8a, 0xca, 0xf9, + 0xa0, 0x29, 0x73, 0xed, 0xc2, 0x34, 0x15, 0x0b, 0x99, 0xe7, 0x4d, 0xef, 0x50, 0x39, 0x0d, 0x59, + 0x9f, 0x8b, 0x11, 0xc1, 0x7a, 0x43, 0x71, 0x78, 0xda, 0xb5, 0x3f, 0xb5, 0xb2, 0x29, 0xb7, 0xbe, + 0x02, 0xd7, 0x49, 0x6d, 0x8c, 0x2c, 0xc3, 0xf4, 0xfd, 0xad, 0x2c, 0x87, 0x69, 0x05, 0x39, 0xc8, + 0x4b, 0xe0, 0x5d, 0x38, 0xc6, 0x52, 0x70, 0x72, 0x55, 0x54, 0x87, 0x7d, 0x18, 0xbc, 0x98, 0xf1, + 0xbd, 0x3d, 0x9f, 0xac, 0x3a, 0xc7, 0xc5, 0x0a, 0x0e, 0x21, 0xdf, 0x36, 0xe0, 0xa6, 0x5c, 0x7f, + 0xb0, 0x7a, 0xc6, 0x8e, 0x3b, 0xdf, 0x2e, 0x86, 0x59, 0xbc, 0xcf, 0x20, 0x2a, 0x20, 0x61, 0xf4, + 0x91, 0x56, 0xcb, 0x66, 0x82, 0x58, 0x37, 0x09, 0x6b, 0x43, 0xd4, 0x15, 0x30, 0x1e, 0x1e, 0x23, + 0xf7, 0x56, 0xeb, 0x14, 0xce, 0x56, 0x90, 0x20, 0xf5, 0x89, 0x12, 0xc6, 0x79, 0xfe, 0x0e, 0x72, + 0x1a, 0x07, 0x7a, 0xa6, 0xd4, 0x48, 0x24, 0x48, 0x98, 0x63, 0x00, 0xe9, 0x72, 0x57, 0xce, 0x25, + 0x87, 0x09, 0x37, 0xa5, 0x18, 0xef, 0x4e, 0x65, 0x9e, 0xa8, 0xc8, 0xa9, 0x5d, 0xac, 0xb9, 0x2a, + 0x35, 0xc8, 0x5d, 0x40, 0x1a, 0x93, 0xb2, 0x13, 0xff, 0x01, 0x90, 0xce, 0x8c, 0x7b, 0x4f, 0x52, + 0x38, 0x86, 0x90, 0xec, 0xc8, 0xcc, 0x7e, 0x54, 0xc9, 0x4a, 0xa4, 0x7c, 0xe4, 0x7e, 0x1b, 0x8d, + 0xf5, 0x92, 0x4b, 0x3a, 0x15, 0x72, 0x86, 0xca, 0x32, 0xc5, 0xd3, 0x24, 0xde, 0x18, 0x07, 0x41, + 0xca, 0xf5, 0x47, 0xb1, 0xe2, 0x49, 0xa6, 0xc9, 0xf1, 0x73, 0x9a, 0xd5, 0x81, 0x36, 0x56, 0xd3, + 0x97, 0x1a, 0xc2, 0x46, 0x24, 0x86, 0xa0, 0x35, 0x21, 0x05, 0x56, 0x2d, 0x6e, 0xb5, 0x4e, 0x15, + 0x15, 0x56, 0x86, 0x5a, 0x21, 0x51, 0xb1, 0x5c, 0xa9, 0x7b, 0xed, 0x64, 0x1e, 0xb3, 0x9e, 0xbe, + 0x55, 0x0a, 0x0c, 0xf5, 0x8a, 0x26, 0xd0, 0xf3, 0x5a, 0x80, 0x37, 0x71, 0xcf, 0x38, 0x53, 0x3b, + 0x62, 0xfc, 0x35, 0x88, 0x1f, 0x0c, 0x9a, 0xbc, 0x90, 0x19, 0x1f, 0x1e, 0x29, 0x84, 0x83, 0x2f, + 0x47, 0xbb, 0xd0, 0xeb, 0x0d, 0x53, 0xa5, 0xd0, 0x82, 0x23, 0x48, 0x26, 0x0b, 0xbd, 0x54, 0xc9, + 0xed, 0x89, 0x2e, 0x48, 0xc2, 0xee, 0x8c, 0xcb, 0x53, 0x33, 0x0f, 0x8d, 0x82, 0x71, 0xf7, 0xd3, + 0xa7, 0xce, 0x64, 0xf4, 0xe9, 0xd3, 0xac, 0xfd, 0xe9, 0x13, 0xfd, 0xf4, 0x69, 0xd6, 0x79, 0x31, + 0xc2, 0xf9, 0x4e, 0x01, 0xe4, 0x78, 0x24, 0x66, 0xde, 0xf8, 0xd3, 0xa7, 0x34, 0xff, 0xf4, 0x09, + 0x4d, 0x3a, 0xc8, 0xeb, 0xe8, 0x8e, 0x87, 0xc7, 0x24, 0xff, 0xf4, 0x29, 0x7d, 0xe8, 0xf3, 0xd3, + 0xa7, 0xb4, 0xfd, 0xe9, 0x13, 0x1e, 0x79, 0x64, 0xfd, 0xa7, 0xdb, 0x3e, 0x08, 0xea, 0x37, 0xe3, + 0x35, 0xf8, 0x89, 0x2f, 0xbe, 0xbd, 0x5b, 0x23, 0x4f, 0x2d, 0xa6, 0x5e, 0x27, 0xc6, 0xe4, 0xcd, + 0x7e, 0x6e, 0xe8, 0x75, 0xd6, 0x98, 0xfc, 0xb8, 0x93, 0xbd, 0x4c, 0x63, 0x53, 0xf9, 0xcb, 0xfd, + 0x5c, 0x5b, 0xf9, 0x23, 0xf3, 0x7e, 0x45, 0xa3, 0xe0, 0x8b, 0x51, 0xee, 0xdf, 0xc1, 0x84, 0xff, + 0xc1, 0x3c, 0x34, 0xf6, 0xbb, 0x57, 0x61, 0x77, 0xfe, 0x55, 0xf7, 0xbb, 0xc9, 0xb6, 0x57, 0x60, + 0x8f, 0xbc, 0xde, 0xcb, 0xec, 0x43, 0xe6, 0x37, 0x4d, 0x80, 0x1f, 0x3b, 0xff, 0x30, 0xff, 0x79, + 0x5f, 0x7a, 0x98, 0x7c, 0x77, 0xac, 0xc4, 0x95, 0xfd, 0xb0, 0x5b, 0xf6, 0xda, 0xfc, 0x67, 0x4a, + 0xbe, 0x3e, 0x56, 0xe2, 0xca, 0x7e, 0x67, 0xef, 0x42, 0xbd, 0xa4, 0x71, 0xb2, 0x20, 0xdf, 0xdb, + 0xa4, 0x4a, 0x32, 0x39, 0x23, 0xbf, 0xd8, 0x8f, 0x79, 0x9c, 0x24, 0xaa, 0x0e, 0x6d, 0xf8, 0xcb, + 0xde, 0x5e, 0x62, 0xea, 0xac, 0x84, 0x44, 0x36, 0x11, 0xde, 0x19, 0x59, 0xb5, 0xb3, 0x9f, 0xfc, + 0xb5, 0x29, 0xbe, 0xba, 0xbd, 0x6b, 0x5d, 0xa9, 0xca, 0xde, 0x0b, 0x0f, 0x13, 0xc5, 0xd6, 0xa1, + 0x4a, 0xf9, 0x77, 0x71, 0x12, 0xc2, 0x96, 0x5d, 0x39, 0xc0, 0x47, 0xf2, 0xac, 0xe7, 0xfb, 0x6d, + 0x15, 0xa8, 0x1a, 0xd4, 0x7f, 0x37, 0x9c, 0x67, 0xa6, 0xd5, 0x5b, 0xd8, 0xe6, 0x49, 0xef, 0xb2, + 0xd1, 0xdd, 0xdf, 0x77, 0x0e, 0xd1, 0x75, 0xf2, 0xc1, 0x38, 0x86, 0x51, 0xef, 0x12, 0xd3, 0x75, + 0x08, 0x6c, 0xa2, 0x34, 0xea, 0x13, 0xcf, 0xf7, 0x70, 0x01, 0x43, 0xfa, 0x99, 0x35, 0x42, 0x45, + 0x2a, 0x20, 0x71, 0xe3, 0xa4, 0xfd, 0x4b, 0xb6, 0x5d, 0x06, 0x3e, 0x49, 0x03, 0x9f, 0x6c, 0x02, + 0x9f, 0x84, 0x41, 0xaf, 0x20, 0xa5, 0xd8, 0x4a, 0xb9, 0xae, 0x64, 0x56, 0x22, 0x5f, 0x2f, 0x41, + 0x15, 0x67, 0xd2, 0x7e, 0x0b, 0x29, 0xb4, 0x08, 0xe3, 0x9f, 0x8d, 0x86, 0x38, 0xad, 0x24, 0xf2, + 0x97, 0xb6, 0x5f, 0xcd, 0xe2, 0x5a, 0x2e, 0x55, 0x11, 0x21, 0x00, 0x90, 0xed, 0x1d, 0x6e, 0x1c, + 0x1e, 0x58, 0xe0, 0xb3, 0x06, 0x5d, 0x35, 0x89, 0xe7, 0x9c, 0xbc, 0x2a, 0xbe, 0x3c, 0xb3, 0xae, + 0x7e, 0x8d, 0x47, 0xa6, 0xbf, 0x25, 0xbf, 0xb3, 0x28, 0x60, 0x3a, 0x38, 0xfb, 0x15, 0x28, 0x79, + 0xb4, 0x57, 0x43, 0x2d, 0xa6, 0x8d, 0x1a, 0x40, 0xbe, 0x75, 0x8d, 0x52, 0xea, 0x2f, 0xd3, 0xb8, + 0xac, 0x53, 0x0b, 0x96, 0x32, 0xec, 0xe7, 0xb4, 0x1e, 0x99, 0x15, 0x0a, 0x40, 0x6d, 0x56, 0x0e, + 0x79, 0x6f, 0xe5, 0x26, 0x8c, 0xc5, 0xec, 0x24, 0x4a, 0xe2, 0x44, 0x9d, 0xd8, 0xcd, 0x1f, 0x0f, + 0xf5, 0x89, 0x90, 0xa9, 0x0e, 0x65, 0x04, 0xad, 0x62, 0x37, 0xd0, 0x74, 0x03, 0x47, 0x92, 0xf0, + 0x13, 0x78, 0x0a, 0x34, 0x04, 0xdd, 0x6a, 0x79, 0x8b, 0x32, 0x31, 0xf5, 0xac, 0x0b, 0xda, 0x8d, + 0x98, 0xe9, 0xc0, 0x5b, 0x96, 0x65, 0x69, 0x99, 0xd8, 0x34, 0x2a, 0x2d, 0xd3, 0xcd, 0xf1, 0x4a, + 0xf1, 0x4e, 0xa5, 0x18, 0x2a, 0xdd, 0xf0, 0x78, 0x23, 0xa4, 0xab, 0x60, 0x67, 0x6c, 0xb3, 0x98, + 0x76, 0x09, 0x5c, 0x14, 0xc4, 0x2c, 0x0f, 0x2c, 0xb2, 0xe4, 0xf1, 0xc1, 0x46, 0x60, 0x37, 0x01, + 0x68, 0x3a, 0xd6, 0x93, 0x7a, 0xbd, 0xc7, 0x7a, 0x42, 0x60, 0x43, 0xd8, 0x16, 0xd6, 0x29, 0x4f, + 0x14, 0x6c, 0x68, 0xa0, 0x94, 0xee, 0x2c, 0xb5, 0xa3, 0x35, 0x8b, 0x83, 0x7d, 0xea, 0x81, 0xfa, + 0x51, 0x9c, 0x48, 0xde, 0xac, 0x5f, 0xaa, 0xf2, 0xfc, 0x16, 0xa8, 0x15, 0x36, 0x4a, 0xa8, 0x96, + 0x49, 0xd8, 0xdd, 0x0e, 0xe0, 0x56, 0xb4, 0xe9, 0x02, 0x52, 0x48, 0x0c, 0x5d, 0x7d, 0x4c, 0x7e, + 0x5a, 0x4c, 0x77, 0xc8, 0xad, 0x0c, 0x41, 0x5a, 0x9e, 0x5d, 0xfa, 0x04, 0xec, 0x80, 0x14, 0x98, + 0x90, 0x80, 0x1e, 0xba, 0x31, 0x29, 0xce, 0x7e, 0x81, 0xdd, 0x3e, 0x63, 0xb2, 0xcb, 0x49, 0xc2, + 0x54, 0x1b, 0xf5, 0xba, 0x02, 0x93, 0xd8, 0xa6, 0xb2, 0xb6, 0xc0, 0x24, 0xb5, 0x69, 0xf8, 0xc4, + 0xf0, 0x1d, 0x31, 0xfe, 0xe2, 0x92, 0x84, 0x6c, 0x9c, 0x12, 0x45, 0x14, 0x89, 0x49, 0x42, 0x92, + 0x09, 0x1c, 0x3c, 0xce, 0xd9, 0x38, 0x31, 0x8e, 0x17, 0x93, 0x0d, 0x59, 0x8e, 0x0f, 0xb6, 0x2a, + 0xf8, 0x0b, 0xea, 0x0f, 0x06, 0xed, 0xb1, 0xab, 0x0e, 0x75, 0x4c, 0x13, 0x9f, 0xf4, 0x07, 0x03, + 0x4c, 0x16, 0xae, 0x3c, 0x2c, 0x33, 0xa6, 0x2e, 0x63, 0xee, 0x32, 0x0a, 0x98, 0xa1, 0x5a, 0x4c, + 0x3f, 0x26, 0x6f, 0xd2, 0xcd, 0xd1, 0x19, 0xaa, 0xb3, 0xfe, 0x60, 0x60, 0xa6, 0xb8, 0x30, 0x29, + 0x98, 0xe2, 0xd4, 0xa4, 0x38, 0xab, 0x64, 0x99, 0x0d, 0x0d, 0x22, 0x19, 0xab, 0xc4, 0x9c, 0xcb, + 0x49, 0x18, 0xef, 0x66, 0x24, 0x66, 0x3e, 0x49, 0x19, 0x87, 0x00, 0x02, 0xc6, 0x18, 0x1f, 0xf9, + 0x41, 0x72, 0xc6, 0x87, 0xe9, 0xad, 0x80, 0x5d, 0x92, 0xe3, 0x6d, 0x14, 0xa6, 0xfc, 0x24, 0x0b, + 0x62, 0xe6, 0x8e, 0xe7, 0x87, 0x26, 0x43, 0x06, 0x31, 0x43, 0xa2, 0xab, 0xf0, 0x59, 0xd2, 0x41, + 0xe2, 0x5a, 0x8d, 0x2e, 0x03, 0x1f, 0x37, 0x2b, 0x08, 0xa8, 0xa0, 0xba, 0x12, 0x2a, 0xf4, 0x9b, + 0x05, 0x0a, 0x0a, 0x64, 0x57, 0x40, 0xc1, 0x85, 0xdb, 0x9c, 0xb7, 0xcb, 0xe0, 0xd2, 0x6f, 0xc7, + 0x2f, 0xce, 0x2f, 0x41, 0x44, 0xfd, 0x05, 0x81, 0xcc, 0x8c, 0x88, 0x4f, 0x7a, 0xbe, 0x8f, 0xc9, + 0xc6, 0x65, 0xa4, 0x2e, 0xa3, 0xa8, 0x16, 0xfe, 0x4d, 0x1a, 0x1f, 0x45, 0x8b, 0x5d, 0x6f, 0x51, + 0xad, 0xb7, 0x62, 0xa8, 0xdf, 0x95, 0xb8, 0x2d, 0x08, 0x67, 0xea, 0x9a, 0xf5, 0x46, 0x2a, 0xe8, + 0x77, 0x15, 0xc9, 0x18, 0xbf, 0xee, 0xf1, 0xee, 0xd5, 0xc8, 0x0f, 0x64, 0x5b, 0x9c, 0x95, 0x02, + 0x6c, 0xbb, 0x0c, 0x34, 0x5d, 0x56, 0xe3, 0xc8, 0xca, 0x71, 0xc4, 0xc1, 0x5f, 0xd0, 0xc0, 0x6f, + 0xab, 0xdd, 0x61, 0xc4, 0x0f, 0xad, 0x4e, 0xbf, 0x0d, 0x51, 0x04, 0x86, 0xfc, 0xda, 0x48, 0x5e, + 0xb3, 0x9e, 0xef, 0x8f, 0x64, 0xd0, 0xf7, 0x7d, 0xc0, 0x89, 0x1d, 0x95, 0xec, 0x88, 0x72, 0x00, + 0xfd, 0xb6, 0x38, 0x43, 0xb2, 0x23, 0xf0, 0xf1, 0x41, 0xa8, 0x26, 0x32, 0x4c, 0xbd, 0xb3, 0x7e, + 0x73, 0x1c, 0x96, 0xbd, 0x1f, 0x60, 0x05, 0x6b, 0x64, 0x33, 0x0d, 0xbd, 0x96, 0x42, 0x5a, 0x31, + 0x7e, 0x7d, 0x79, 0x39, 0x42, 0x92, 0x59, 0x0a, 0xea, 0xf6, 0x06, 0x03, 0xda, 0x1f, 0x5c, 0xbc, + 0x1a, 0x0c, 0x2e, 0xfb, 0x2f, 0xfd, 0xab, 0xde, 0xcb, 0xab, 0x2e, 0xbd, 0xb8, 0x18, 0x5c, 0x5d, + 0x5e, 0x0d, 0xfc, 0x8b, 0xcb, 0xab, 0xc1, 0xcb, 0xab, 0xde, 0xf9, 0x79, 0x1b, 0x09, 0xc6, 0xbb, + 0x7d, 0xdc, 0xe9, 0xf9, 0x17, 0xf4, 0xe2, 0xaa, 0xdf, 0xbb, 0xec, 0x5d, 0x5d, 0x9d, 0x5f, 0x9d, + 0xbf, 0x7a, 0xf5, 0xaa, 0xfd, 0x3b, 0x12, 0x98, 0xf0, 0xeb, 0xbe, 0x3f, 0xf2, 0x03, 0xfa, 0xaa, + 0xff, 0xf2, 0xc2, 0xbf, 0xba, 0xf4, 0x2f, 0x2f, 0x7c, 0xff, 0xe5, 0xf9, 0xd5, 0xa0, 0x8d, 0x14, + 0xe3, 0xdd, 0x9e, 0x8f, 0xbb, 0xfd, 0xc1, 0x05, 0x7d, 0x79, 0x79, 0x75, 0x3e, 0xe8, 0xbd, 0xba, + 0xe8, 0xf5, 0xfd, 0x2b, 0xbf, 0xdf, 0xe9, 0xf5, 0x06, 0xf4, 0xf2, 0xe5, 0xd5, 0xd5, 0xc5, 0x85, + 0xdf, 0xf3, 0x2f, 0x2f, 0x7b, 0x17, 0x2f, 0xdb, 0xbf, 0x23, 0x85, 0xe1, 0x40, 0x84, 0x9d, 0x0f, + 0x7a, 0xf4, 0xea, 0xe5, 0xe5, 0x95, 0x3f, 0xb8, 0xbc, 0x7c, 0xe5, 0x0f, 0x2e, 0xaf, 0xce, 0x3b, + 0xb4, 0xd7, 0xbb, 0xe8, 0xfb, 0x97, 0x17, 0x83, 0xf3, 0x97, 0xaf, 0x2e, 0x7a, 0x97, 0x83, 0x36, + 0x9c, 0xe4, 0x76, 0x07, 0x03, 0xdc, 0xbd, 0xf0, 0x69, 0x7f, 0x70, 0x7e, 0x79, 0x79, 0xee, 0x5f, + 0x9d, 0x9f, 0xf7, 0x7b, 0x7d, 0x80, 0x03, 0xfb, 0x38, 0x3b, 0xef, 0x0f, 0xe8, 0xc5, 0xc5, 0xd5, + 0x45, 0xaf, 0x3f, 0x78, 0xd9, 0xeb, 0x5d, 0xbd, 0xbc, 0xe8, 0x50, 0xff, 0xe5, 0xd5, 0xc5, 0xf9, + 0xc5, 0xe0, 0x12, 0xea, 0x5f, 0xf6, 0xcf, 0x2f, 0xfa, 0x76, 0x6e, 0x03, 0x18, 0xe2, 0x2b, 0xea, + 0xbf, 0x1a, 0xf4, 0xaf, 0x2e, 0xcf, 0x07, 0xfe, 0xcb, 0xab, 0xc1, 0x4b, 0x3b, 0x35, 0xc3, 0xa2, + 0x86, 0xa9, 0x8d, 0xf0, 0x68, 0x30, 0xf1, 0x2f, 0x50, 0xdc, 0xe0, 0xe1, 0x5f, 0x90, 0xc2, 0x07, + 0x2c, 0xfc, 0x57, 0x2b, 0x89, 0x8f, 0x5a, 0x75, 0x86, 0x4a, 0x94, 0xe5, 0x5e, 0xc2, 0x59, 0x9f, + 0x9f, 0x93, 0x8c, 0x5d, 0xf0, 0x8b, 0x21, 0xbd, 0xb8, 0xce, 0xba, 0x7c, 0x68, 0xd7, 0x31, 0x61, + 0x3b, 0xeb, 0x8c, 0x24, 0xa3, 0x83, 0x36, 0xca, 0x3a, 0x60, 0x19, 0x25, 0x74, 0x7a, 0x96, 0x50, + 0xf5, 0x5f, 0x4c, 0x9d, 0x89, 0x51, 0xc6, 0x64, 0xc0, 0x99, 0xac, 0xfc, 0x24, 0x05, 0xd9, 0x17, + 0xf3, 0xb2, 0xd5, 0x5a, 0xa0, 0x86, 0x15, 0x68, 0xb4, 0x1d, 0x93, 0x07, 0x4a, 0x0f, 0x8a, 0xc9, + 0x78, 0x0b, 0x31, 0x83, 0xde, 0x32, 0xdd, 0x78, 0x64, 0xc1, 0x75, 0xd0, 0x10, 0xc5, 0x76, 0xdf, + 0xb7, 0x5a, 0xc0, 0x3e, 0xb1, 0x6a, 0x9a, 0x92, 0x4d, 0xa0, 0xe9, 0xa6, 0x28, 0x48, 0xda, 0x6c, + 0x56, 0x33, 0xa7, 0x6d, 0x07, 0x71, 0x48, 0x76, 0x7b, 0x91, 0x64, 0x5f, 0xf5, 0x28, 0xb5, 0xac, + 0xed, 0x32, 0x38, 0xed, 0x91, 0x0d, 0xfc, 0x93, 0xc2, 0x3f, 0x61, 0x70, 0xda, 0x2b, 0x2a, 0x7b, + 0x56, 0x59, 0xf7, 0x9c, 0x18, 0xab, 0x09, 0x83, 0x10, 0x8b, 0x53, 0x26, 0xc7, 0x6a, 0x32, 0x74, + 0xca, 0x8e, 0x26, 0x48, 0xd0, 0x65, 0x9e, 0x0b, 0x9a, 0xc2, 0x3f, 0x1b, 0xf8, 0x07, 0x7c, 0x88, + 0x3b, 0x1d, 0x59, 0x23, 0x56, 0x38, 0x2f, 0x75, 0xd9, 0xb2, 0x28, 0x48, 0x35, 0xf9, 0xf0, 0x60, + 0xf6, 0x0e, 0xa7, 0x3b, 0x9a, 0xd0, 0xc1, 0x54, 0xeb, 0x9d, 0xbb, 0x06, 0x96, 0xf1, 0x87, 0x60, + 0x59, 0x30, 0x74, 0xf9, 0x08, 0x1c, 0x40, 0x70, 0x51, 0xc1, 0x4a, 0x43, 0x9d, 0xa9, 0xd0, 0x58, + 0x8b, 0x8f, 0x83, 0x4c, 0x1f, 0x03, 0x99, 0x36, 0x41, 0x5a, 0x95, 0xe6, 0x71, 0x68, 0x9b, 0xc7, + 0xa0, 0x6d, 0x9a, 0xd0, 0xc2, 0x78, 0xbd, 0x0c, 0x9f, 0x80, 0x16, 0x3e, 0x02, 0xad, 0xc6, 0xee, + 0x32, 0xdd, 0x90, 0x6d, 0x18, 0xe8, 0x02, 0x57, 0xc0, 0x9d, 0x96, 0xf3, 0x00, 0xf4, 0x1d, 0x6e, + 0x43, 0xa5, 0x9e, 0xf5, 0xd0, 0x1a, 0x81, 0x0a, 0xb6, 0xcb, 0x54, 0xba, 0xee, 0x48, 0xf1, 0xd9, + 0xa3, 0x73, 0x50, 0x8b, 0x29, 0x55, 0x8f, 0x00, 0xae, 0x67, 0xa1, 0x16, 0x53, 0x90, 0x1c, 0xcd, + 0x59, 0x2c, 0x14, 0xe7, 0xf2, 0x49, 0xf0, 0x8b, 0xe7, 0x83, 0x5f, 0xec, 0x80, 0x9f, 0x3e, 0xb5, + 0x9c, 0x00, 0x7d, 0xfa, 0x7c, 0xe8, 0xd3, 0x1d, 0xe8, 0x60, 0x5f, 0x1e, 0x17, 0x0b, 0xb5, 0x46, + 0x86, 0x1c, 0x77, 0x10, 0xa3, 0xa7, 0x58, 0x1d, 0xc5, 0x4a, 0xb8, 0x5a, 0x3f, 0xfa, 0x1e, 0x04, + 0xe9, 0x22, 0xf8, 0x1e, 0xe4, 0xe7, 0x34, 0xf8, 0x1e, 0x81, 0x6f, 0xec, 0x09, 0xaa, 0xa8, 0x15, + 0x22, 0x30, 0x59, 0xb6, 0x61, 0x50, 0xc5, 0x5e, 0x6b, 0x1a, 0x8e, 0x7a, 0x81, 0xa6, 0xe1, 0xee, + 0x40, 0x9f, 0xc1, 0xc2, 0x66, 0x86, 0x61, 0x60, 0xd2, 0x86, 0x74, 0x8b, 0xc7, 0xe8, 0xa5, 0x29, + 0x20, 0xe2, 0xc7, 0xd1, 0xf0, 0x26, 0x8d, 0x77, 0xd0, 0xb0, 0xb4, 0xea, 0x80, 0x41, 0x43, 0x5c, + 0xcb, 0x4e, 0x83, 0x86, 0xd4, 0xa2, 0x21, 0x7e, 0x2e, 0x1a, 0x4a, 0xcd, 0xe3, 0x39, 0x68, 0x30, + 0xc6, 0xfc, 0x93, 0x68, 0x58, 0xa6, 0xf1, 0x33, 0xd1, 0x60, 0xec, 0x8d, 0x26, 0x92, 0xad, 0x55, + 0xf5, 0xd8, 0x56, 0xa1, 0x16, 0xe5, 0xba, 0x43, 0x7d, 0xf0, 0x5f, 0x50, 0xd5, 0xf1, 0xc8, 0x09, + 0x24, 0x16, 0x65, 0x62, 0xda, 0xf1, 0xb0, 0xf7, 0xc0, 0xce, 0x51, 0x9e, 0x14, 0x80, 0xd7, 0x73, + 0x8e, 0x90, 0x64, 0xbf, 0x51, 0x7e, 0xc7, 0x23, 0xf0, 0x11, 0x8d, 0x90, 0x60, 0x7f, 0x45, 0x10, + 0xae, 0x64, 0xf7, 0x60, 0x65, 0xbe, 0xfa, 0xee, 0x8b, 0x9b, 0xaf, 0x73, 0xfb, 0x65, 0x74, 0x8a, + 0x37, 0x55, 0x4b, 0x13, 0x0a, 0xf8, 0xcc, 0xa6, 0x24, 0x33, 0x5f, 0x17, 0x13, 0xd2, 0xc3, 0x98, + 0x9c, 0xca, 0x87, 0xad, 0x44, 0xb5, 0x98, 0x9e, 0x38, 0x73, 0x17, 0x0f, 0x2b, 0xba, 0xd9, 0xaa, + 0x40, 0x90, 0x45, 0xa0, 0xc8, 0x34, 0xe0, 0x24, 0x0c, 0xb2, 0x62, 0x87, 0x4a, 0x9f, 0x85, 0xc1, + 0xb0, 0x81, 0xc2, 0xf0, 0x61, 0x1c, 0xda, 0x44, 0x78, 0x1c, 0x99, 0xfb, 0xc6, 0x72, 0x4d, 0x24, + 0xa5, 0x89, 0xfd, 0xcc, 0x65, 0xfc, 0xc2, 0xeb, 0xfc, 0x1d, 0x69, 0xaa, 0xb0, 0xf9, 0x59, 0xd8, + 0x9f, 0x63, 0x92, 0x76, 0x77, 0xf9, 0xfa, 0x83, 0x81, 0x5b, 0xc0, 0x6f, 0x76, 0x16, 0xb0, 0xf7, + 0xb2, 0xfd, 0xdf, 0x66, 0x21, 0x60, 0x11, 0xdc, 0x47, 0x7f, 0x02, 0x6b, 0xe0, 0x3e, 0xce, 0x27, + 0x76, 0xf5, 0xbe, 0xfb, 0xd3, 0xcd, 0x80, 0x68, 0xec, 0xc7, 0x85, 0x83, 0xf1, 0xc3, 0x0e, 0x8c, + 0x1a, 0x40, 0xdd, 0xba, 0xd9, 0xe3, 0xd7, 0xbb, 0xf4, 0xf2, 0x48, 0x75, 0x92, 0xb1, 0xb2, 0x9b, + 0x47, 0x29, 0x64, 0xc9, 0xef, 0x9e, 0x41, 0x21, 0x60, 0xc8, 0x15, 0xcd, 0xf5, 0x79, 0xf5, 0xe7, + 0xa8, 0xe4, 0x81, 0x15, 0xea, 0xfc, 0x1d, 0xfd, 0x62, 0xec, 0x4c, 0x4d, 0x43, 0xfc, 0x20, 0x8b, + 0xd7, 0x0e, 0x97, 0xa6, 0x18, 0x79, 0x7a, 0x00, 0xcb, 0xb4, 0x94, 0x6c, 0x50, 0xdf, 0x10, 0xe9, + 0xb2, 0x24, 0xc9, 0xb4, 0xe3, 0xbd, 0xb0, 0xa9, 0xb8, 0xe3, 0xbd, 0x78, 0x3e, 0xab, 0xff, 0x78, + 0x8c, 0xd5, 0xcf, 0x2f, 0xfd, 0x06, 0xbf, 0x1a, 0xe3, 0xa8, 0xe2, 0x57, 0xf8, 0x32, 0x4b, 0xf7, + 0xe5, 0x51, 0x56, 0x7f, 0xaa, 0xe9, 0xf3, 0x59, 0x7d, 0x99, 0xc6, 0x7b, 0x0b, 0x09, 0xb2, 0x71, + 0xbb, 0x0c, 0x04, 0x49, 0x03, 0x45, 0xe2, 0x7d, 0x56, 0x07, 0x49, 0xfc, 0x2c, 0x1c, 0x86, 0x0d, + 0x24, 0x86, 0x8f, 0x61, 0xf1, 0x69, 0x66, 0x6f, 0x78, 0xbd, 0x8a, 0x62, 0x82, 0x49, 0x5c, 0x20, + 0x5c, 0xfb, 0x42, 0xff, 0xd9, 0x40, 0x3b, 0xd3, 0xf4, 0x56, 0xcc, 0xf4, 0xd2, 0x6c, 0x50, 0x69, + 0x2c, 0x66, 0x5c, 0x7d, 0x10, 0x7f, 0x70, 0xb0, 0x1d, 0xe9, 0x34, 0x51, 0x33, 0xae, 0xfe, 0x61, + 0x8a, 0x21, 0xb0, 0x75, 0x19, 0xca, 0x59, 0xcc, 0x7f, 0x0a, 0x67, 0x22, 0x4b, 0x49, 0x62, 0x2e, + 0x7c, 0xcd, 0x66, 0x70, 0xbe, 0x10, 0xd7, 0x6d, 0x97, 0xe1, 0x9a, 0x93, 0x94, 0x79, 0xcb, 0x44, + 0x89, 0x3f, 0x12, 0xa9, 0xc3, 0xd8, 0x33, 0x3b, 0x54, 0x1c, 0xde, 0x27, 0x99, 0xfe, 0x46, 0x28, + 0x6e, 0xc6, 0x50, 0xdb, 0xa4, 0xee, 0x54, 0x52, 0x32, 0x85, 0xc1, 0x56, 0x6e, 0x27, 0x9d, 0x7e, + 0x3b, 0x23, 0x5e, 0x24, 0x54, 0x64, 0xe3, 0x6a, 0xe3, 0xd1, 0xd6, 0x76, 0x6c, 0x5c, 0xa0, 0x41, + 0xd5, 0x6b, 0x67, 0x6f, 0x40, 0xe5, 0x87, 0x5c, 0xf0, 0x40, 0x74, 0xfb, 0xed, 0xa4, 0x0b, 0x80, + 0xcc, 0xe4, 0x02, 0x41, 0x96, 0x5c, 0x2c, 0x96, 0x3a, 0x10, 0x24, 0xba, 0x0b, 0xc4, 0x59, 0x9f, + 0x44, 0xf7, 0xe6, 0x47, 0x99, 0xb6, 0x90, 0xec, 0xf2, 0xb3, 0x7e, 0x11, 0xec, 0x74, 0xa5, 0xce, + 0xfa, 0x7b, 0x50, 0x55, 0xd9, 0x00, 0x8a, 0xee, 0x02, 0x9f, 0xdc, 0x07, 0xbe, 0xeb, 0x22, 0x1d, + 0xa9, 0xba, 0x9b, 0x74, 0x24, 0x02, 0xd5, 0x38, 0xf4, 0xfb, 0x57, 0xd3, 0x95, 0x0c, 0xe8, 0x27, + 0x8a, 0x09, 0x87, 0x78, 0xb8, 0x94, 0x61, 0x9b, 0x91, 0x0c, 0x92, 0x75, 0x87, 0x24, 0xa9, 0xbe, + 0xcd, 0x80, 0xe0, 0xe4, 0xe1, 0x09, 0xbc, 0x92, 0x94, 0xc5, 0x23, 0x75, 0xd6, 0x0f, 0x38, 0xcc, + 0x91, 0x25, 0x9d, 0x63, 0x47, 0x71, 0xd2, 0xb8, 0xeb, 0xc0, 0x19, 0x61, 0x84, 0xbb, 0xf3, 0xfb, + 0x94, 0x4b, 0x68, 0x02, 0x21, 0x8d, 0x0b, 0xc8, 0xa8, 0xc3, 0x41, 0xb9, 0x52, 0xe0, 0x79, 0xa2, + 0x83, 0x81, 0xf1, 0xe8, 0x38, 0x5d, 0xb6, 0x2e, 0x5b, 0x34, 0xca, 0x8c, 0x22, 0x5a, 0x17, 0x4d, + 0x1b, 0x45, 0xd6, 0x4a, 0x28, 0xcb, 0xc0, 0xcb, 0x21, 0x68, 0x68, 0x8b, 0x9c, 0x8e, 0x1f, 0xd8, + 0xeb, 0x6c, 0x1a, 0x9c, 0x56, 0x1f, 0xf9, 0x6a, 0xcd, 0x15, 0x58, 0x3e, 0xdc, 0xd0, 0xdf, 0x2a, + 0xbc, 0x6b, 0x64, 0x19, 0x3f, 0x1e, 0x92, 0x4e, 0x95, 0xef, 0x72, 0x7c, 0x96, 0xb5, 0x1b, 0xde, + 0x8e, 0xca, 0x17, 0xe6, 0x93, 0xca, 0x09, 0x96, 0x58, 0x29, 0x61, 0x3b, 0x5c, 0x36, 0x46, 0x29, + 0xe8, 0xf2, 0x8c, 0x9d, 0xd3, 0x4b, 0x5b, 0xd2, 0x30, 0xb6, 0xea, 0x0a, 0xa9, 0x2d, 0xb3, 0x56, + 0x53, 0xe0, 0xee, 0xf9, 0xd5, 0xc5, 0x9b, 0xa2, 0x30, 0x28, 0x36, 0xbe, 0xff, 0xac, 0x1c, 0x44, + 0xdc, 0x6a, 0xa1, 0x88, 0x75, 0x7b, 0xed, 0xa8, 0x93, 0x75, 0xfa, 0xed, 0x04, 0x93, 0xed, 0x5d, + 0x10, 0x8f, 0xd2, 0x20, 0x22, 0xf7, 0x41, 0x3c, 0x8a, 0x82, 0xb4, 0xb0, 0x4e, 0x75, 0x4d, 0xa4, + 0x66, 0xfd, 0xb6, 0x19, 0xe9, 0x8f, 0x6f, 0x89, 0xd0, 0xec, 0xd8, 0x95, 0x28, 0xa4, 0x5f, 0xc8, + 0x8e, 0xc4, 0x2f, 0x64, 0x41, 0xd4, 0xf1, 0x1a, 0x76, 0xda, 0xe9, 0xef, 0x4a, 0x23, 0xdd, 0xd6, + 0x1d, 0xd9, 0x96, 0xb8, 0xa8, 0x19, 0xdf, 0x38, 0xfd, 0xeb, 0x33, 0x06, 0x43, 0x7f, 0x67, 0xfd, + 0x6e, 0xc5, 0x52, 0xdd, 0x5d, 0x96, 0xea, 0xee, 0x88, 0x80, 0xc6, 0x85, 0x2e, 0xdd, 0xf4, 0xbc, + 0x39, 0x28, 0xa5, 0x6e, 0x6b, 0xb9, 0xa1, 0x92, 0x2a, 0x96, 0x5d, 0xe4, 0x2e, 0x28, 0x60, 0x42, + 0x09, 0x2c, 0x28, 0x1b, 0x3c, 0x92, 0xe8, 0x1d, 0x8f, 0x34, 0x40, 0x5e, 0x72, 0x1e, 0x7f, 0x25, + 0x17, 0xb1, 0x15, 0x47, 0xe6, 0xf3, 0x40, 0x82, 0x40, 0xd4, 0x76, 0x14, 0x27, 0xd1, 0xcd, 0xad, + 0x48, 0x8d, 0xbc, 0xe0, 0x23, 0xc9, 0x54, 0xc7, 0x44, 0xf3, 0xef, 0xe5, 0x9e, 0x5f, 0xfa, 0x5d, + 0x28, 0x81, 0x26, 0xa1, 0xd4, 0xe2, 0x48, 0xb3, 0xde, 0x2b, 0xbf, 0x2b, 0x83, 0x23, 0xa5, 0x10, + 0x04, 0xc5, 0xc0, 0xb7, 0x49, 0x84, 0x46, 0xd2, 0x6c, 0x27, 0xf5, 0xd0, 0xe3, 0xbd, 0xa1, 0x1b, + 0x04, 0x81, 0xe3, 0x91, 0x46, 0x77, 0x24, 0x83, 0x9f, 0x7b, 0xf0, 0xbc, 0x9a, 0x63, 0x22, 0x70, + 0x5c, 0x81, 0xdc, 0xcd, 0xba, 0xc2, 0x1c, 0x3e, 0xc6, 0xcc, 0x4c, 0xdc, 0xac, 0x5b, 0xa8, 0x43, + 0xd9, 0x47, 0x5d, 0x41, 0xc0, 0x73, 0x89, 0xce, 0x2f, 0xfd, 0x33, 0xa9, 0x31, 0x38, 0xa6, 0x2b, + 0x0a, 0x56, 0xda, 0xc4, 0x65, 0x93, 0xa4, 0xe1, 0x34, 0xac, 0xcf, 0xbe, 0x50, 0x0c, 0x46, 0x45, + 0xe3, 0xbb, 0xe7, 0xfb, 0x67, 0x49, 0x3b, 0x6d, 0xc6, 0x1f, 0xa4, 0x87, 0x8b, 0x67, 0x76, 0x81, + 0x69, 0x72, 0xf7, 0xc6, 0x48, 0xa1, 0xdd, 0x85, 0x94, 0xa5, 0x48, 0x73, 0x37, 0x0f, 0x47, 0x22, + 0x90, 0xe5, 0xaa, 0x3e, 0x24, 0x8a, 0x1b, 0xbd, 0x45, 0x7b, 0x98, 0x49, 0x2b, 0xcc, 0xdc, 0xba, + 0x6d, 0x45, 0x95, 0xc2, 0x2f, 0x61, 0x8a, 0x5a, 0xc0, 0xc4, 0x78, 0x8b, 0x13, 0x7c, 0x86, 0x38, + 0xc8, 0x71, 0x0c, 0x6c, 0x4d, 0x52, 0xf0, 0x3d, 0x43, 0x5e, 0x56, 0xe5, 0x95, 0x23, 0x75, 0x53, + 0xde, 0x63, 0xf6, 0xd8, 0x32, 0x3b, 0xd9, 0x1c, 0x2d, 0xed, 0xf9, 0x7e, 0x37, 0xb5, 0x35, 0x1a, + 0xc3, 0x0d, 0x75, 0x7d, 0xaf, 0xb6, 0x8a, 0xa2, 0x60, 0xfe, 0x90, 0xd7, 0x11, 0x2c, 0xbc, 0x0c, + 0xb6, 0xc8, 0x4c, 0x9c, 0x04, 0xbd, 0xeb, 0x4a, 0x18, 0x3a, 0x24, 0xef, 0xbb, 0xe6, 0xf6, 0x67, + 0xcd, 0x82, 0x59, 0x3b, 0xeb, 0x24, 0xed, 0x04, 0x5f, 0xef, 0xe2, 0xa7, 0x8c, 0x13, 0xe4, 0xcd, + 0x30, 0xbd, 0xc6, 0xbd, 0x99, 0x06, 0x97, 0x6e, 0xa7, 0xc9, 0xdd, 0x07, 0xf1, 0x87, 0x90, 0x8b, + 0xc0, 0xb3, 0x0c, 0xd4, 0x9d, 0x26, 0x77, 0x1e, 0xb1, 0xe9, 0x60, 0x87, 0xab, 0xe0, 0x7e, 0xcc, + 0x49, 0x9a, 0x80, 0x8e, 0x62, 0xac, 0x02, 0x53, 0xf2, 0x1a, 0x8e, 0xaf, 0x1a, 0x33, 0x5c, 0xea, + 0xfd, 0xa0, 0x9a, 0x8e, 0xd7, 0x5d, 0x00, 0xde, 0x21, 0x8a, 0xd0, 0xeb, 0x48, 0xab, 0x72, 0x08, + 0xba, 0x0a, 0xd7, 0xe8, 0x88, 0x2f, 0x6f, 0xec, 0xd7, 0xd7, 0xc0, 0xc7, 0xbd, 0x49, 0xc7, 0x3b, + 0x31, 0x6d, 0x5e, 0x78, 0x05, 0xa6, 0x9f, 0x13, 0x21, 0x91, 0x47, 0x3c, 0x6c, 0x34, 0x93, 0xfa, + 0xe6, 0x40, 0x63, 0x3e, 0x87, 0x67, 0x82, 0x23, 0x1d, 0x68, 0x73, 0xb3, 0xc7, 0x08, 0xc2, 0x99, + 0x66, 0x63, 0x6f, 0x95, 0x64, 0xa9, 0xb9, 0x9e, 0xe0, 0x11, 0x4f, 0x27, 0x59, 0xb4, 0x74, 0x69, + 0x93, 0x9f, 0xad, 0xcb, 0x5c, 0x2e, 0x67, 0xde, 0x84, 0x2c, 0x1a, 0x82, 0x50, 0x36, 0x4e, 0x42, + 0x4d, 0xa7, 0xd2, 0x45, 0x29, 0x82, 0xd3, 0xaf, 0x0a, 0xd1, 0x10, 0x33, 0x66, 0xd7, 0x48, 0x85, + 0x72, 0x96, 0xac, 0x10, 0xdc, 0x1f, 0xae, 0xcf, 0x5b, 0xcf, 0x2f, 0x31, 0x84, 0xd8, 0xdb, 0x71, + 0xa2, 0x41, 0x1d, 0x7a, 0x66, 0x22, 0xdb, 0x7e, 0xfb, 0xcd, 0x38, 0x50, 0x7f, 0xfb, 0x8d, 0x49, + 0x4c, 0x50, 0xd3, 0x9f, 0x5a, 0xc6, 0xf2, 0xd8, 0xb0, 0x4c, 0x64, 0x2e, 0xc0, 0x57, 0x85, 0x18, + 0xef, 0x44, 0xf5, 0x6b, 0x7c, 0x18, 0x17, 0xf2, 0x80, 0xdf, 0xd4, 0xd2, 0x8d, 0xb9, 0x07, 0x63, + 0xe3, 0x3f, 0xcc, 0x89, 0x19, 0x11, 0x6c, 0x9b, 0xc8, 0x77, 0x80, 0x8f, 0x6f, 0x92, 0x5b, 0x19, + 0x48, 0x92, 0x48, 0x83, 0x93, 0xd4, 0x28, 0x2e, 0xb0, 0x3f, 0x3c, 0xad, 0x2a, 0x94, 0xe1, 0x7f, + 0x66, 0x67, 0x55, 0x0b, 0x21, 0x47, 0xa5, 0x0a, 0xf0, 0xce, 0x7c, 0x06, 0x65, 0x3e, 0xc9, 0xd8, + 0x36, 0xd9, 0x70, 0x35, 0x8f, 0x93, 0xdb, 0xc0, 0xdb, 0x88, 0x54, 0x4c, 0x63, 0xee, 0x91, 0x99, + 0x48, 0xd7, 0x71, 0x78, 0x1f, 0xa8, 0x91, 0x27, 0x64, 0x2c, 0x24, 0xef, 0x4e, 0x41, 0x64, 0x7a, + 0xe0, 0x8a, 0x82, 0xdf, 0xea, 0xf6, 0xb8, 0x5f, 0x1e, 0x9d, 0x9b, 0x88, 0x53, 0x35, 0xf2, 0x2c, + 0xd8, 0x1f, 0xf8, 0x5c, 0x7b, 0x81, 0xfb, 0xf8, 0x98, 0xac, 0xbd, 0x09, 0xe3, 0x98, 0x2c, 0xd1, + 0x7b, 0x1b, 0xee, 0x56, 0x5f, 0x24, 0x47, 0xe5, 0xba, 0x11, 0x41, 0x32, 0x7b, 0x0a, 0xd9, 0x0c, + 0x66, 0xaa, 0x10, 0xf4, 0x00, 0x0e, 0x89, 0x0b, 0x3e, 0xb2, 0xc1, 0x96, 0x89, 0x7c, 0x2b, 0xd7, + 0x99, 0x06, 0x7d, 0x17, 0x32, 0x21, 0x74, 0x0d, 0xa2, 0x51, 0xbe, 0x06, 0x79, 0x29, 0xe4, 0xe2, + 0x75, 0x0c, 0x8c, 0xf0, 0x13, 0x8f, 0x34, 0xc2, 0x43, 0xe8, 0xc7, 0x5c, 0x69, 0xf9, 0xc6, 0x6e, + 0xf7, 0x08, 0x0f, 0x4b, 0xf5, 0xc4, 0x52, 0x60, 0x3a, 0x82, 0x51, 0x82, 0xae, 0x36, 0xfb, 0x68, + 0x33, 0xe0, 0x9a, 0x2e, 0x28, 0x72, 0x9c, 0x46, 0x06, 0xd2, 0x3f, 0xbb, 0x20, 0x39, 0xe6, 0x20, + 0xde, 0xca, 0xac, 0x7f, 0x75, 0x15, 0xd5, 0xc9, 0xba, 0xd6, 0xbb, 0x74, 0xad, 0x71, 0x19, 0x12, + 0x9f, 0x25, 0xb7, 0xd2, 0x0b, 0xcc, 0x77, 0xbd, 0xa8, 0x5e, 0x70, 0xda, 0x83, 0x68, 0x5c, 0x73, + 0xdb, 0x0b, 0x2e, 0x6f, 0xcf, 0x34, 0x44, 0x29, 0x7d, 0x1b, 0x46, 0xcb, 0x1d, 0x3e, 0xad, 0xe2, + 0x83, 0x0f, 0x6e, 0x5c, 0x01, 0xdf, 0x6f, 0xd7, 0x10, 0x6b, 0xb6, 0xe1, 0xe0, 0x57, 0xc7, 0x45, + 0xf3, 0xf4, 0xae, 0xc1, 0x75, 0x8d, 0xae, 0xed, 0xb7, 0xed, 0xb4, 0x77, 0x58, 0x3d, 0x5b, 0x37, + 0x2b, 0x03, 0x43, 0xba, 0xba, 0x7d, 0x4c, 0x9e, 0x1a, 0xdf, 0xb1, 0x1b, 0x5e, 0x47, 0x86, 0x08, + 0xc7, 0xd7, 0x05, 0x7a, 0xdb, 0x30, 0x5f, 0xa6, 0x3b, 0x3b, 0x98, 0xf5, 0x33, 0x66, 0x2a, 0x06, + 0x7d, 0x16, 0x68, 0xba, 0xa4, 0xba, 0x25, 0x32, 0x11, 0xe4, 0x64, 0x5b, 0xdd, 0xe4, 0x0b, 0xbc, + 0xb7, 0x2a, 0x79, 0x63, 0xe8, 0xe5, 0xa4, 0x4a, 0x75, 0xbb, 0x20, 0x2c, 0x0d, 0x79, 0x1a, 0x61, + 0x06, 0x11, 0xc6, 0xe9, 0x57, 0x91, 0x16, 0x1b, 0x3e, 0xf2, 0x1a, 0xb5, 0xca, 0x4c, 0x2f, 0xf0, + 0x3c, 0x4c, 0xcc, 0x1d, 0xbf, 0x60, 0xeb, 0x75, 0x6f, 0xf9, 0xf4, 0x46, 0xe8, 0xae, 0x0e, 0xd7, + 0xdd, 0xa5, 0x58, 0x2c, 0x63, 0xd8, 0xca, 0xba, 0x26, 0x66, 0xc0, 0xb3, 0x5e, 0x1e, 0xe4, 0x93, + 0x13, 0xf7, 0x3f, 0x1e, 0x7a, 0x44, 0xab, 0x50, 0xa6, 0x70, 0x49, 0x2d, 0xf0, 0x4c, 0x32, 0x06, + 0x61, 0xe1, 0x75, 0x40, 0x46, 0xd2, 0x3b, 0x6c, 0x85, 0xaf, 0xf9, 0xb8, 0x37, 0x52, 0x94, 0xdc, + 0x8a, 0x38, 0xb6, 0x47, 0x17, 0xae, 0x81, 0xb9, 0xe0, 0x46, 0x74, 0xb2, 0x0e, 0x36, 0x1a, 0x81, + 0x3e, 0x02, 0xd4, 0x55, 0xa6, 0xed, 0x9e, 0xbd, 0xd1, 0xa8, 0xdf, 0x96, 0xb8, 0xdc, 0xb9, 0xcb, + 0xcf, 0x75, 0x92, 0x0a, 0x40, 0x60, 0xe0, 0x85, 0xd3, 0x34, 0x89, 0x33, 0xcd, 0x3d, 0x72, 0xc8, + 0xd6, 0x45, 0x01, 0xc7, 0x42, 0x4b, 0x04, 0xaf, 0x8f, 0x78, 0x64, 0x27, 0x40, 0x11, 0x6d, 0xcd, + 0x0d, 0xb3, 0x37, 0xf0, 0xaa, 0xc4, 0x8e, 0xc9, 0xa9, 0x99, 0xd6, 0x79, 0x5e, 0xad, 0xec, 0x82, + 0x6b, 0x17, 0x96, 0x9e, 0x7e, 0x7d, 0xff, 0xd1, 0xde, 0xcf, 0x43, 0x1e, 0x70, 0x9a, 0x87, 0xdd, + 0x1d, 0xd3, 0x5b, 0x21, 0x67, 0xc9, 0x2d, 0x95, 0xe1, 0x46, 0x2c, 0x42, 0x08, 0x08, 0xcb, 0x52, + 0xae, 0xbe, 0x5a, 0xc0, 0x8d, 0x7b, 0xc1, 0xce, 0x7e, 0x45, 0x68, 0x74, 0x1a, 0x2d, 0x55, 0xb2, + 0xe2, 0x79, 0x28, 0x67, 0x2a, 0x11, 0x33, 0x4c, 0x71, 0x3b, 0x0d, 0xe7, 0xa1, 0x12, 0x67, 0xa2, + 0xbc, 0x12, 0x0a, 0x8f, 0x9f, 0x88, 0x1f, 0x97, 0x89, 0xe4, 0xb9, 0xf8, 0x31, 0x99, 0xe5, 0xe2, + 0xc7, 0x70, 0xd6, 0x28, 0xe5, 0x65, 0x2f, 0x10, 0xdc, 0xdf, 0x50, 0x19, 0x91, 0xc8, 0x73, 0x85, + 0x5b, 0x2d, 0xff, 0x5a, 0x97, 0xf7, 0x76, 0x47, 0x2e, 0xd6, 0x2e, 0x4a, 0xe2, 0x8e, 0x77, 0x76, + 0xe6, 0x75, 0x38, 0x5d, 0x26, 0xa9, 0xee, 0x70, 0xba, 0x0e, 0xf5, 0x52, 0x86, 0x2b, 0xde, 0x81, + 0xf0, 0xc6, 0x50, 0x45, 0xcb, 0x8e, 0x0e, 0x20, 0x92, 0xb9, 0x94, 0x42, 0x10, 0x79, 0x48, 0x4e, + 0x2d, 0xc6, 0x9c, 0xcd, 0x4a, 0xb6, 0xd1, 0x5d, 0xa0, 0x40, 0xbd, 0xe5, 0x44, 0x05, 0x92, 0xcc, + 0x45, 0x1c, 0x07, 0x9e, 0x4c, 0x24, 0xec, 0x61, 0xa9, 0x56, 0xc9, 0x0d, 0xef, 0x9a, 0x85, 0xf2, + 0x82, 0x3e, 0xb1, 0xdf, 0x81, 0xf7, 0x85, 0xef, 0xfb, 0x5e, 0xf1, 0x04, 0xa8, 0x6e, 0xdf, 0x02, + 0xd3, 0x14, 0x7e, 0x1e, 0x01, 0x36, 0x9f, 0xcf, 0xbd, 0xa2, 0x79, 0x7b, 0x6f, 0xad, 0x11, 0x2f, + 0xfd, 0x0d, 0x9c, 0x86, 0x86, 0x92, 0xdf, 0x02, 0xcd, 0x93, 0x8c, 0x55, 0xb1, 0xdd, 0x10, 0x1c, + 0x74, 0xcd, 0xa9, 0xa1, 0xde, 0xb4, 0xc6, 0x8c, 0xfd, 0x1e, 0xeb, 0x49, 0xe0, 0xd2, 0x44, 0xb2, + 0x7f, 0xc2, 0x0b, 0x20, 0x60, 0x40, 0x5a, 0x35, 0x0e, 0x1e, 0x5c, 0x70, 0x6a, 0x1c, 0xbc, 0xba, + 0xe0, 0xd4, 0xb8, 0x94, 0xfd, 0x0b, 0x71, 0x92, 0x41, 0x24, 0xc5, 0x83, 0x66, 0xe8, 0x9f, 0xb3, + 0x42, 0xc7, 0x63, 0x9f, 0x18, 0x67, 0xb2, 0x4f, 0xbc, 0x8e, 0x32, 0x1e, 0x50, 0xf8, 0x35, 0x4e, + 0xe4, 0x09, 0x19, 0x83, 0x9e, 0x68, 0x8a, 0xe1, 0x80, 0xfb, 0xb0, 0xc2, 0xe4, 0x88, 0xed, 0x5a, + 0x41, 0x84, 0x6a, 0xe0, 0x5a, 0xf5, 0x8f, 0x43, 0x2c, 0x8b, 0x4b, 0xc8, 0x3b, 0x10, 0x9b, 0x16, + 0xef, 0x01, 0xc0, 0x72, 0x1c, 0xfe, 0x71, 0x80, 0x65, 0x31, 0xf8, 0x9b, 0x2b, 0x80, 0x3b, 0x76, + 0x72, 0x09, 0x31, 0x3c, 0x68, 0xe3, 0x06, 0xf2, 0x14, 0xe8, 0x83, 0xf1, 0x96, 0xb6, 0x76, 0xad, + 0xe2, 0x8e, 0x27, 0xd6, 0xc2, 0xde, 0x35, 0xba, 0x93, 0x03, 0xa3, 0x9b, 0xc4, 0x2c, 0xe9, 0x66, + 0x24, 0x65, 0x19, 0x04, 0x8f, 0x0c, 0xd3, 0xeb, 0x64, 0x98, 0x76, 0x58, 0x7c, 0xf6, 0x8a, 0x44, + 0x1d, 0xd6, 0x73, 0x97, 0x3a, 0xd9, 0xcf, 0x3b, 0xe7, 0x6b, 0x29, 0x26, 0x73, 0x16, 0x52, 0xb8, + 0x80, 0x18, 0xd2, 0x05, 0xd9, 0xb0, 0x90, 0x4e, 0x87, 0xdc, 0xc6, 0xcd, 0x8e, 0x7b, 0x7d, 0x3a, + 0x68, 0x47, 0xe5, 0xb8, 0xe7, 0x66, 0xb4, 0x4b, 0xf3, 0xef, 0xc6, 0x8c, 0xb8, 0x8e, 0xe5, 0x3c, + 0xb0, 0xda, 0x0d, 0x5e, 0xbe, 0x98, 0xfb, 0xbe, 0x99, 0xfc, 0x25, 0xbd, 0xbc, 0xbc, 0x84, 0xef, + 0xb9, 0xf9, 0x3e, 0x3f, 0xa7, 0xe7, 0xe7, 0xe7, 0xc4, 0xfb, 0xc2, 0xb7, 0xdf, 0x03, 0xdf, 0xa4, + 0xe7, 0x90, 0xbe, 0x2c, 0xeb, 0xfa, 0xbe, 0xf9, 0x7e, 0x55, 0xd6, 0x9d, 0xdb, 0x6f, 0x83, 0x48, + 0x0b, 0x78, 0x72, 0xe8, 0x11, 0x30, 0x6a, 0x2a, 0xfb, 0xb9, 0x3e, 0xee, 0x01, 0xd7, 0x9f, 0x39, + 0x0a, 0x87, 0x38, 0x3b, 0xf0, 0x04, 0x60, 0xb2, 0x38, 0x5a, 0x0e, 0x70, 0x5d, 0x8d, 0x61, 0x63, + 0x0a, 0xd6, 0x67, 0x3a, 0xa3, 0x76, 0xda, 0x33, 0xeb, 0xec, 0x83, 0x84, 0xf5, 0x98, 0x96, 0x03, + 0xb2, 0xd5, 0x16, 0xae, 0xda, 0xa2, 0xac, 0xb6, 0x28, 0xab, 0x4d, 0x8e, 0x3a, 0x28, 0x60, 0xb4, + 0xd3, 0xa3, 0xa3, 0x11, 0xe6, 0xe0, 0xbe, 0xe7, 0xfb, 0xbb, 0xa3, 0x31, 0x82, 0x68, 0xb7, 0xcf, + 0xa9, 0xeb, 0x73, 0x5a, 0xf6, 0x39, 0xad, 0xfa, 0x2c, 0x0a, 0xc3, 0xe1, 0xf5, 0x9e, 0xbb, 0xd0, + 0xfb, 0x7b, 0x46, 0x41, 0x38, 0xd9, 0x3a, 0xad, 0x2b, 0x38, 0x1a, 0x7c, 0x76, 0x3c, 0x24, 0x8d, + 0x70, 0xeb, 0x29, 0x03, 0x5d, 0x6a, 0xd7, 0x29, 0xc6, 0x9b, 0x4e, 0xb1, 0xe1, 0xd3, 0x9a, 0xee, + 0xa8, 0xdb, 0x6b, 0x8b, 0x4e, 0xd6, 0x49, 0x02, 0xd9, 0x4d, 0x88, 0xaa, 0xc3, 0xa4, 0x6a, 0xb3, + 0x1a, 0xa4, 0x94, 0x8f, 0x9d, 0x41, 0xbe, 0x67, 0x40, 0x67, 0x6d, 0x85, 0x1f, 0x11, 0x4f, 0x4d, + 0xc7, 0x55, 0x7a, 0xc0, 0x43, 0x25, 0x66, 0xd2, 0x4e, 0x6c, 0x5c, 0x43, 0xe8, 0xc0, 0x8d, 0x95, + 0xe2, 0x63, 0xbe, 0x31, 0x53, 0xfb, 0xd0, 0x51, 0x75, 0x4e, 0x2f, 0xdb, 0xf1, 0xb0, 0x16, 0x8b, + 0x0d, 0xf1, 0x73, 0xc4, 0x2f, 0x07, 0x8e, 0xb7, 0x76, 0x3c, 0xdc, 0x73, 0x56, 0xc5, 0x66, 0xd1, + 0x40, 0x10, 0x03, 0x17, 0x9a, 0x17, 0x4b, 0xa8, 0x80, 0xd5, 0xb1, 0x0a, 0x0e, 0x44, 0xb0, 0x67, + 0x63, 0xde, 0x98, 0xe8, 0x84, 0x29, 0xc2, 0x4b, 0xc5, 0x19, 0x9e, 0xbd, 0xa1, 0x62, 0x86, 0x8b, + 0x02, 0x1f, 0xc4, 0x98, 0xd4, 0x9a, 0xd7, 0x4c, 0x6c, 0xbc, 0x43, 0x42, 0x90, 0xfb, 0xca, 0xd8, + 0x07, 0xd3, 0x87, 0xe7, 0xd4, 0xa9, 0x83, 0xfa, 0xdb, 0x5a, 0x65, 0x51, 0x3c, 0x0e, 0x8d, 0xfa, + 0x55, 0xeb, 0x38, 0xaa, 0xa9, 0xe1, 0x24, 0xd8, 0xd9, 0xc4, 0xd6, 0xc4, 0x86, 0xac, 0x18, 0x93, + 0x69, 0x18, 0xdd, 0x2c, 0xcc, 0x4a, 0x06, 0x5e, 0x94, 0x48, 0x11, 0xd5, 0xa6, 0xee, 0x17, 0x51, + 0x14, 0x9d, 0xf4, 0x07, 0x2f, 0xc8, 0x09, 0xec, 0x96, 0x27, 0xfe, 0xc9, 0xc0, 0x87, 0x34, 0xe4, + 0xfa, 0x27, 0x2f, 0xeb, 0x7c, 0xec, 0x35, 0xa0, 0x80, 0x6b, 0x3c, 0xf0, 0x5e, 0xad, 0xef, 0x4e, + 0x5e, 0x81, 0xc5, 0x0a, 0x81, 0x24, 0x60, 0xb1, 0xd8, 0xe9, 0x1e, 0x9d, 0xdb, 0xf7, 0xae, 0xbf, + 0xe7, 0xcc, 0xb1, 0x56, 0xcb, 0x40, 0xbd, 0xf3, 0xad, 0x66, 0x57, 0xfa, 0x97, 0xbd, 0x9e, 0xef, + 0xbf, 0xf0, 0xca, 0x19, 0xbb, 0xaf, 0xc7, 0xa7, 0xbc, 0xd4, 0xc8, 0x03, 0xbb, 0x2c, 0x54, 0x1e, + 0xd9, 0xe3, 0x11, 0x7e, 0xc0, 0x23, 0x9e, 0x4e, 0x4e, 0x74, 0xb2, 0xf6, 0x02, 0x48, 0x28, 0xe8, + 0xc4, 0x23, 0x11, 0x2e, 0xc8, 0x1c, 0x34, 0x07, 0x3b, 0xcd, 0xa9, 0x26, 0xdb, 0x52, 0x0d, 0x0e, + 0x4e, 0x7d, 0x62, 0x94, 0xe6, 0xc0, 0xdd, 0x20, 0x24, 0x2a, 0xe0, 0xbb, 0x0e, 0xf9, 0x4c, 0xc5, + 0x55, 0xd6, 0x87, 0xcd, 0xc2, 0x3d, 0x4d, 0x56, 0xe6, 0x98, 0x5b, 0xd1, 0xe4, 0x2e, 0x48, 0xe9, + 0x1d, 0xb9, 0x0f, 0x52, 0x7a, 0x0f, 0xfa, 0x4a, 0x43, 0x63, 0xb9, 0x6f, 0x68, 0x2c, 0xa9, 0xb6, + 0xea, 0x86, 0xae, 0xbc, 0x46, 0xba, 0xf6, 0x1a, 0xe9, 0xda, 0x6b, 0x54, 0xea, 0x2a, 0x10, 0xdc, + 0xe8, 0x28, 0x9b, 0xc8, 0x3d, 0x7d, 0x27, 0xaa, 0xf5, 0x1d, 0xb0, 0xd1, 0x1f, 0xd6, 0x77, 0x64, + 0xad, 0xef, 0x84, 0x47, 0x7d, 0xad, 0x63, 0xb7, 0x01, 0xcd, 0xe7, 0x7b, 0xf2, 0x52, 0xd2, 0x65, + 0xc6, 0x3b, 0x1e, 0x78, 0x97, 0x5e, 0x90, 0x81, 0x6f, 0x04, 0x25, 0xa9, 0x77, 0x71, 0x9f, 0x98, + 0xff, 0x6a, 0xc9, 0x6e, 0x45, 0xee, 0x64, 0x52, 0x20, 0xdf, 0xdc, 0xe5, 0x65, 0xf1, 0x81, 0xf7, + 0xc5, 0x71, 0xd6, 0x31, 0x35, 0xca, 0xba, 0xd4, 0x1e, 0x3c, 0x4f, 0x50, 0xe5, 0x71, 0x8d, 0x55, + 0xb7, 0x62, 0x06, 0xbb, 0xb7, 0x32, 0x67, 0x23, 0x11, 0x04, 0xf6, 0x55, 0xce, 0x6a, 0xf0, 0x4c, + 0x77, 0x12, 0x1b, 0x48, 0xd9, 0x4e, 0xc1, 0x3f, 0xdd, 0x41, 0x51, 0x37, 0xb1, 0xf1, 0x94, 0xed, + 0x08, 0x5b, 0xa9, 0x81, 0x8b, 0x7f, 0x5f, 0xd8, 0x8b, 0x39, 0x82, 0x70, 0x85, 0x4a, 0xec, 0x87, + 0xda, 0xca, 0x21, 0x32, 0x2f, 0xaf, 0x80, 0x31, 0x35, 0x32, 0xb1, 0xe9, 0x96, 0xc6, 0x8c, 0xef, + 0x0a, 0x29, 0x1c, 0xa0, 0x74, 0x5f, 0x40, 0x45, 0x26, 0x2e, 0x22, 0x72, 0x00, 0xf0, 0xa1, 0x78, + 0x72, 0x11, 0x5e, 0xe6, 0xb9, 0x8b, 0x56, 0xeb, 0x49, 0x00, 0x20, 0x0a, 0xff, 0x13, 0x02, 0xee, + 0x6b, 0x70, 0xd6, 0x3d, 0xc4, 0xf9, 0xc7, 0x25, 0x59, 0xd6, 0xb4, 0xd4, 0x2a, 0xb1, 0xf7, 0xb8, + 0xac, 0x79, 0x46, 0x37, 0xcf, 0x92, 0x1f, 0x49, 0xc9, 0xf0, 0x64, 0xfb, 0x90, 0x1c, 0xd1, 0xc9, + 0xc9, 0x34, 0xd1, 0x3a, 0x59, 0x79, 0x24, 0x84, 0x33, 0x71, 0xab, 0xb1, 0xed, 0xd5, 0x70, 0xf2, + 0x23, 0x1c, 0xfb, 0x13, 0x60, 0x6a, 0x4c, 0x62, 0xb0, 0x58, 0x34, 0xdc, 0xca, 0x3f, 0x24, 0x6a, + 0x7d, 0xca, 0x58, 0x54, 0xe0, 0x87, 0x68, 0x7e, 0x5f, 0xee, 0xf4, 0x9c, 0xdc, 0x71, 0x46, 0x7b, + 0x69, 0x11, 0x55, 0x47, 0x9e, 0xff, 0xae, 0x20, 0x9a, 0x8f, 0x1d, 0xc4, 0x89, 0x91, 0x48, 0x8d, + 0xcf, 0xfb, 0xe2, 0x31, 0xf9, 0x17, 0x35, 0xc7, 0x11, 0xed, 0x8d, 0xc3, 0x4a, 0x9e, 0x37, 0x8d, + 0xd1, 0xe4, 0xf9, 0xbf, 0x39, 0xba, 0x68, 0x77, 0x74, 0x51, 0x63, 0x74, 0x80, 0xe3, 0xe9, 0xee, + 0xe3, 0x93, 0x6c, 0xdb, 0x34, 0x3b, 0xcb, 0xa3, 0x4a, 0x15, 0xbc, 0x32, 0xfd, 0x19, 0x07, 0x9b, + 0xed, 0x68, 0xeb, 0xca, 0x8a, 0x82, 0xac, 0xf7, 0x40, 0x1c, 0x92, 0x52, 0xe3, 0x90, 0x37, 0xf0, + 0xa6, 0xb0, 0xda, 0xb5, 0x96, 0x50, 0x45, 0x14, 0xee, 0x2a, 0x40, 0x41, 0xbf, 0xef, 0xfb, 0x64, + 0x57, 0xe7, 0x09, 0x7a, 0x3d, 0x7e, 0x5e, 0x34, 0x5c, 0x3a, 0xb7, 0x95, 0xb0, 0x37, 0x87, 0x27, + 0x1c, 0x57, 0x82, 0xbe, 0x12, 0xe9, 0x09, 0x43, 0x7c, 0xe7, 0x0c, 0xa9, 0x94, 0xf0, 0xb8, 0x16, + 0xfc, 0x70, 0xfa, 0x69, 0xa4, 0x1c, 0xbc, 0x43, 0xf6, 0x27, 0x44, 0x68, 0x69, 0x89, 0x3e, 0x72, + 0x6e, 0x03, 0x67, 0x12, 0xbd, 0x57, 0x7e, 0xc7, 0x1c, 0xd6, 0x80, 0x02, 0x7d, 0xea, 0x63, 0xdc, + 0x46, 0x52, 0x9f, 0x99, 0xc8, 0x82, 0x94, 0x09, 0x27, 0x39, 0x13, 0x12, 0xb1, 0xdd, 0xa3, 0xa7, + 0xfd, 0x93, 0xab, 0x51, 0xb7, 0x17, 0xf4, 0x6a, 0xa1, 0xcb, 0x3b, 0xa9, 0x3d, 0xf7, 0x8b, 0x92, + 0x14, 0xc5, 0xb8, 0x0d, 0x47, 0x83, 0x59, 0x99, 0x97, 0xc2, 0x41, 0x06, 0x6e, 0x47, 0x95, 0xf0, + 0x25, 0x21, 0xfb, 0x9f, 0xd3, 0x18, 0xbc, 0x81, 0xcd, 0x3a, 0x76, 0xc4, 0x50, 0xfc, 0x0f, 0x88, + 0x79, 0x31, 0x47, 0xa7, 0xc7, 0x35, 0xfe, 0xe3, 0x98, 0xde, 0x3f, 0x4c, 0x3c, 0x51, 0x1a, 0xc1, + 0x69, 0x59, 0xd6, 0x15, 0xf8, 0x3a, 0x29, 0xb5, 0x56, 0x77, 0x7c, 0x72, 0xda, 0x1b, 0xee, 0x6d, + 0x23, 0x51, 0x63, 0x1b, 0x49, 0x8e, 0x6d, 0x23, 0xc9, 0xfe, 0x2e, 0x60, 0xa8, 0x85, 0xc5, 0xcf, + 0xde, 0x46, 0x9e, 0x02, 0xf0, 0x9f, 0xda, 0x46, 0xfe, 0x01, 0x04, 0xf4, 0x67, 0x37, 0x12, 0xf5, + 0x6f, 0x6c, 0x24, 0xa6, 0xa3, 0x37, 0xc0, 0xc5, 0x0f, 0xf4, 0x15, 0x92, 0x6d, 0xc3, 0x85, 0xa9, + 0x12, 0xb8, 0xbd, 0xf9, 0x0b, 0xf2, 0x3a, 0x88, 0x37, 0x8e, 0x6b, 0x3b, 0x57, 0x3e, 0xee, 0x78, + 0x33, 0xbe, 0xd8, 0x51, 0x9e, 0xf7, 0x4f, 0x64, 0xf7, 0xd9, 0x62, 0x5f, 0x43, 0x57, 0x7c, 0x46, + 0x4e, 0xee, 0x79, 0x1c, 0x27, 0xb7, 0xe4, 0x24, 0x16, 0x2b, 0x4e, 0x4e, 0xc2, 0xdf, 0xb3, 0x90, + 0x9c, 0x80, 0xbd, 0x43, 0x4e, 0x56, 0x21, 0xb8, 0x0b, 0x43, 0x72, 0xa2, 0xf8, 0x0c, 0x7b, 0xc1, + 0xd1, 0xd6, 0x55, 0x1d, 0xdb, 0xc4, 0x36, 0xb7, 0xa0, 0x4a, 0xc0, 0xa6, 0x75, 0xf1, 0x14, 0x4a, + 0x3e, 0x34, 0xe2, 0xaf, 0x1f, 0xc6, 0x4c, 0x73, 0xae, 0x30, 0x8e, 0x30, 0xae, 0xc7, 0x63, 0x3d, + 0x7a, 0x27, 0x51, 0x9c, 0xa4, 0x3c, 0xd5, 0xdd, 0x54, 0xcc, 0xb8, 0x35, 0x31, 0xc8, 0x89, 0x41, + 0xa8, 0x13, 0x66, 0x76, 0x28, 0x0e, 0x37, 0x3f, 0xc0, 0x52, 0x4a, 0x9e, 0xa6, 0xc6, 0x27, 0xf8, + 0xe0, 0xe0, 0xaa, 0x6a, 0xcf, 0x1d, 0x9b, 0x51, 0x38, 0x49, 0xb2, 0x86, 0x97, 0xa3, 0xef, 0x83, + 0x5e, 0x37, 0xb5, 0x4a, 0xde, 0x93, 0x58, 0xf8, 0xda, 0x88, 0x87, 0x47, 0x7a, 0xa9, 0x8c, 0x85, + 0xec, 0x89, 0xfd, 0x3e, 0xfe, 0xff, 0xbf, 0xdf, 0x47, 0xbb, 0xfb, 0x7d, 0xf4, 0xdc, 0xfd, 0x3e, + 0x6e, 0x8e, 0x23, 0xfe, 0x4f, 0xed, 0xf7, 0xd1, 0x38, 0xde, 0x1d, 0x5d, 0xbc, 0xb7, 0xdf, 0x83, + 0xec, 0xbb, 0x69, 0x1c, 0x79, 0x89, 0xfd, 0xb3, 0xcf, 0xfa, 0x00, 0x6c, 0x28, 0x8e, 0x1c, 0x83, + 0xda, 0x6d, 0x15, 0x1c, 0x7f, 0xee, 0xda, 0x5e, 0x43, 0xae, 0xf5, 0x6c, 0x9e, 0x39, 0xfa, 0x4a, + 0x59, 0x19, 0x2c, 0x6c, 0xe7, 0xf6, 0xed, 0x6e, 0xe6, 0x8c, 0xcf, 0xb9, 0x52, 0x7c, 0xb6, 0x97, + 0x2d, 0x66, 0xf0, 0xf6, 0xf1, 0x8c, 0x20, 0x38, 0xfb, 0xdb, 0x35, 0xb0, 0xca, 0xef, 0x60, 0xec, + 0x52, 0x13, 0x7c, 0xf4, 0xa0, 0xa8, 0x7a, 0xf2, 0x23, 0x9c, 0xcd, 0xac, 0x08, 0x37, 0xfb, 0x5f, + 0x79, 0x7d, 0xb5, 0x29, 0xdb, 0x7d, 0xdc, 0x78, 0x34, 0xe0, 0x50, 0x6d, 0xd1, 0x64, 0x6b, 0x3a, + 0x0a, 0xea, 0x89, 0x13, 0x37, 0x86, 0x06, 0x2a, 0x88, 0xb5, 0x88, 0x83, 0xd2, 0x7d, 0x54, 0x54, + 0xae, 0x47, 0xb1, 0x77, 0xf4, 0x2b, 0x1e, 0x3f, 0xfa, 0x15, 0xe6, 0x19, 0xd1, 0xe7, 0x1c, 0xfd, + 0x96, 0x33, 0xdb, 0x77, 0x8f, 0x57, 0x6f, 0x8b, 0x9b, 0xa8, 0x93, 0xc6, 0x18, 0xcb, 0x07, 0xd0, + 0x87, 0x4e, 0x6f, 0xe1, 0xb7, 0x27, 0x3f, 0x23, 0x5d, 0xdd, 0xa5, 0x81, 0x3a, 0xf6, 0xb0, 0xa8, + 0x71, 0x56, 0xec, 0x82, 0x14, 0x1d, 0x80, 0x74, 0x6d, 0x5e, 0x66, 0x94, 0xc4, 0x87, 0x30, 0x92, + 0x66, 0xc9, 0xe1, 0x1a, 0x34, 0xc2, 0x8a, 0x1c, 0x6f, 0x30, 0x59, 0x34, 0x51, 0x5d, 0x5f, 0x26, + 0xb6, 0x77, 0xfc, 0xb7, 0x87, 0x58, 0x2d, 0xeb, 0x57, 0x74, 0xb2, 0x12, 0x1a, 0x79, 0x76, 0x39, + 0xe0, 0xaa, 0xa8, 0x47, 0xc4, 0xde, 0x81, 0xae, 0x7b, 0x35, 0x7e, 0x0f, 0x2f, 0x3b, 0x87, 0xe2, + 0xbb, 0x73, 0xd1, 0xa4, 0x87, 0x21, 0x2c, 0x41, 0xba, 0x4b, 0xa4, 0xe8, 0xff, 0xd1, 0xbc, 0xdc, + 0x13, 0xe4, 0x8c, 0x35, 0x06, 0x55, 0x9e, 0x73, 0x3f, 0x46, 0xa5, 0xbc, 0x81, 0x02, 0xe5, 0xe2, + 0x1c, 0xe4, 0x1e, 0x12, 0x76, 0x9b, 0x1e, 0x3e, 0x41, 0x61, 0x5a, 0x37, 0x91, 0x01, 0xd7, 0x75, + 0x9f, 0x9a, 0x40, 0x63, 0xfc, 0xc5, 0x91, 0xb1, 0x54, 0x7d, 0x7a, 0x0d, 0xfc, 0x1d, 0x8e, 0xeb, + 0xb5, 0x15, 0x1c, 0x0f, 0xbd, 0xf1, 0x31, 0xdc, 0xa3, 0x5e, 0xff, 0xa9, 0xd5, 0x68, 0xac, 0x45, + 0xb9, 0x7e, 0xc5, 0xa1, 0x8c, 0x7a, 0xac, 0xa1, 0x78, 0x86, 0x88, 0x90, 0x0f, 0x4c, 0x38, 0x8e, + 0x9b, 0xb3, 0x4d, 0xf7, 0xa6, 0x9b, 0xc8, 0x07, 0xe7, 0x59, 0x06, 0x10, 0x58, 0x21, 0x39, 0x3c, + 0x78, 0x21, 0x78, 0xa4, 0x83, 0xb1, 0x7e, 0x40, 0xb4, 0x21, 0x35, 0xd6, 0x93, 0x3c, 0x37, 0x3f, + 0xf0, 0x12, 0x23, 0xae, 0x5e, 0x23, 0x11, 0x7b, 0x02, 0x75, 0xac, 0x27, 0xe6, 0x69, 0xe6, 0x83, + 0xdc, 0xa3, 0x70, 0xa5, 0x7b, 0xa9, 0xc5, 0xc6, 0x4f, 0xe0, 0xe2, 0x28, 0x3c, 0xe8, 0xb0, 0xd8, + 0x9f, 0xe7, 0x7c, 0xde, 0x9c, 0x68, 0x1d, 0x83, 0x07, 0x0b, 0xfa, 0xa7, 0xa6, 0x66, 0xb9, 0x54, + 0x39, 0xb4, 0x8c, 0xf5, 0xc4, 0xfe, 0x29, 0x88, 0x52, 0xec, 0x54, 0x4f, 0x28, 0x08, 0x4c, 0x7a, + 0x07, 0xc3, 0x80, 0xc5, 0x39, 0x7e, 0x5d, 0xb2, 0x0c, 0xe4, 0x30, 0x0f, 0xb8, 0xef, 0x3f, 0x80, + 0xd3, 0xed, 0x0d, 0xfd, 0x6b, 0x05, 0xcf, 0x49, 0x9b, 0xab, 0x81, 0x55, 0xf1, 0x58, 0x75, 0x7a, + 0x93, 0x32, 0x62, 0x63, 0x7f, 0x07, 0x1b, 0x9e, 0x9e, 0xee, 0xbf, 0x84, 0x63, 0x9e, 0x0d, 0xe0, + 0x76, 0x69, 0xe0, 0x07, 0x14, 0x7c, 0xd4, 0x58, 0x64, 0x53, 0x32, 0x7e, 0x7c, 0xbb, 0xd2, 0xe5, + 0x12, 0x58, 0x35, 0xdb, 0x82, 0xe9, 0xed, 0xcd, 0xb3, 0x29, 0x0c, 0x1f, 0xbc, 0x1e, 0xfa, 0x7f, + 0x37, 0xd5, 0xdd, 0x65, 0x1f, 0xba, 0x6d, 0x04, 0x1b, 0x14, 0x57, 0x43, 0x04, 0x3a, 0x8a, 0x12, + 0x19, 0x85, 0x1a, 0x09, 0x8c, 0x09, 0x6a, 0xce, 0xbd, 0x26, 0x4b, 0x71, 0x28, 0x03, 0xde, 0x9b, + 0x57, 0xc7, 0xd3, 0x43, 0xb9, 0x54, 0x49, 0x1c, 0x7d, 0x20, 0xd5, 0x53, 0xf1, 0x07, 0x3f, 0xda, + 0xc0, 0x01, 0x43, 0x65, 0xe8, 0x68, 0x71, 0xd8, 0xf4, 0xc8, 0x8b, 0x03, 0xcf, 0x91, 0x27, 0xa6, + 0x25, 0x6a, 0x8a, 0x84, 0x47, 0xe4, 0xf9, 0x3e, 0xe7, 0x9b, 0x07, 0xc3, 0x0e, 0x07, 0xcc, 0xe3, + 0xf2, 0x8f, 0x57, 0xec, 0x6e, 0x69, 0xe6, 0x7d, 0x2c, 0x2b, 0x4b, 0x0e, 0x40, 0x35, 0x36, 0xe6, + 0x3d, 0x79, 0xf2, 0x4c, 0x31, 0xdd, 0xd0, 0xce, 0xca, 0x67, 0x1e, 0x8e, 0x2a, 0x6c, 0x66, 0x24, + 0xa6, 0x24, 0xb0, 0x61, 0x49, 0x9e, 0x35, 0x4b, 0x0f, 0x65, 0x5f, 0xb3, 0xf8, 0x90, 0x09, 0x8d, + 0x05, 0xbb, 0x1f, 0x53, 0x05, 0xe3, 0x35, 0xd7, 0xcd, 0x46, 0x07, 0x9d, 0xd9, 0x08, 0xa5, 0x86, + 0x20, 0x25, 0x12, 0x07, 0xbd, 0xe3, 0x75, 0xed, 0x86, 0xb7, 0x5b, 0xb5, 0xcf, 0x58, 0xf5, 0x60, + 0x53, 0xb3, 0x2e, 0x44, 0x14, 0xed, 0x56, 0xdd, 0x27, 0x8d, 0xbd, 0xd8, 0xb9, 0xea, 0xd5, 0x3f, + 0x2b, 0x30, 0x64, 0x75, 0xd0, 0x51, 0x7a, 0x14, 0x76, 0x65, 0x19, 0xbc, 0xec, 0x8d, 0x24, 0x1b, + 0x6f, 0xab, 0x57, 0x84, 0x82, 0x5b, 0x5d, 0x90, 0xc6, 0xe7, 0x5a, 0x17, 0x13, 0xc2, 0x69, 0x6d, + 0xa2, 0x45, 0xf7, 0x26, 0xb2, 0x0f, 0x18, 0x63, 0xa7, 0x1a, 0xb1, 0x2f, 0xf1, 0xa7, 0xc1, 0xb6, + 0xe9, 0x12, 0xb3, 0x87, 0x7a, 0x45, 0x81, 0xf7, 0x0d, 0x2b, 0x63, 0x54, 0x19, 0xba, 0xf8, 0x51, + 0x44, 0x37, 0x60, 0x54, 0x89, 0x59, 0x00, 0x0e, 0x83, 0x32, 0xb4, 0xa8, 0x8c, 0xae, 0xe3, 0xd4, + 0xa5, 0x8a, 0x82, 0xc8, 0x3d, 0x9b, 0xa9, 0xb1, 0x23, 0xd5, 0xef, 0x20, 0x99, 0x73, 0x12, 0x37, + 0x98, 0xda, 0x87, 0x23, 0x8e, 0xb9, 0x70, 0x14, 0xd9, 0x42, 0x2c, 0x8f, 0xfb, 0x2b, 0x1a, 0xa5, + 0x3f, 0x27, 0xdb, 0x23, 0x01, 0xab, 0x4b, 0x82, 0x5b, 0xda, 0x98, 0xa8, 0x41, 0xe6, 0x0c, 0x21, + 0x69, 0x0c, 0x11, 0x5c, 0xc6, 0x67, 0xdd, 0x3c, 0xe9, 0x3d, 0xb4, 0xfc, 0x7d, 0xee, 0xfb, 0xa5, + 0x93, 0x02, 0x92, 0x96, 0x1c, 0xed, 0x31, 0x4a, 0xa9, 0x95, 0x8f, 0x27, 0xc4, 0x45, 0x16, 0x07, + 0x97, 0x64, 0xef, 0xa0, 0x2a, 0xf0, 0x36, 0x5c, 0x69, 0x11, 0x85, 0x71, 0xe9, 0xcc, 0x7a, 0xdd, + 0x84, 0xd0, 0xf0, 0x10, 0x06, 0x3e, 0x69, 0x1a, 0x5e, 0xc1, 0x2b, 0x72, 0x68, 0x9d, 0x59, 0x4f, + 0x68, 0x65, 0x8c, 0x35, 0x3f, 0x7f, 0xdc, 0x75, 0x8f, 0x92, 0x5d, 0x8b, 0x1c, 0xec, 0xc1, 0xda, + 0xe1, 0x11, 0xb8, 0x8f, 0xc6, 0x28, 0x77, 0x43, 0xc8, 0x49, 0x7d, 0xb5, 0xc6, 0xf6, 0xb1, 0x13, + 0x68, 0xd9, 0xeb, 0x93, 0x2a, 0xfc, 0xda, 0xfe, 0x69, 0x19, 0xb2, 0xad, 0x51, 0x51, 0x52, 0x82, + 0x0b, 0xab, 0x04, 0x42, 0xb1, 0x7f, 0x0d, 0xc3, 0xda, 0x2b, 0x9e, 0xc3, 0xba, 0x47, 0x6c, 0x24, + 0xa5, 0x05, 0x60, 0x4d, 0x84, 0x95, 0x26, 0x77, 0x9a, 0x7c, 0xd6, 0xe4, 0x9d, 0x26, 0xef, 0x35, + 0x43, 0x6f, 0x9b, 0x56, 0x0b, 0x5a, 0x69, 0x76, 0xd3, 0xb4, 0x47, 0xf6, 0x48, 0xe4, 0xad, 0x26, + 0x2b, 0x8d, 0xc9, 0x5b, 0x4d, 0xdf, 0xb2, 0x95, 0x26, 0x6f, 0x75, 0xc3, 0x61, 0xfb, 0x16, 0xe2, + 0xd0, 0xdd, 0x76, 0x2f, 0x88, 0x62, 0x0f, 0xbc, 0x4a, 0x6a, 0x28, 0xbe, 0xd1, 0x8c, 0x57, 0x97, + 0x9e, 0x64, 0xf3, 0x21, 0x1d, 0x57, 0x7d, 0x24, 0xeb, 0xd7, 0x4d, 0x7f, 0xcf, 0xb8, 0xba, 0xff, + 0xc0, 0x63, 0x6e, 0x1e, 0xfa, 0x83, 0x97, 0xbd, 0x77, 0xfe, 0x96, 0x86, 0x30, 0x81, 0x9b, 0xe6, + 0xaf, 0x53, 0x58, 0x41, 0xdd, 0x78, 0xf5, 0xeb, 0x81, 0x68, 0x02, 0x92, 0x0d, 0x57, 0x54, 0xc0, + 0x3b, 0x8b, 0xc2, 0xbe, 0xf5, 0xc4, 0x99, 0xf9, 0x1b, 0x32, 0x8c, 0x25, 0xf6, 0xdd, 0xf6, 0xc0, + 0x18, 0x6e, 0x32, 0xcf, 0x25, 0x95, 0x44, 0xb3, 0x2a, 0x10, 0x15, 0x74, 0x1d, 0x92, 0xc1, 0x7e, + 0x0c, 0x7f, 0x99, 0x04, 0x1e, 0xf1, 0x96, 0x4c, 0x07, 0x10, 0x45, 0x26, 0x31, 0x24, 0x09, 0x87, + 0x3f, 0x54, 0x72, 0x47, 0x1a, 0x8f, 0x95, 0xef, 0xff, 0x15, 0x19, 0xf8, 0x6b, 0x06, 0x6a, 0x34, + 0x16, 0x93, 0x80, 0xdb, 0xae, 0x76, 0x1e, 0x51, 0x95, 0xcd, 0x47, 0x54, 0x49, 0x46, 0xc0, 0xe5, + 0x61, 0xfe, 0xf6, 0x09, 0xfc, 0x95, 0x99, 0x0c, 0x14, 0x39, 0xb4, 0x44, 0xab, 0x23, 0x4e, 0xd8, + 0xed, 0x7e, 0x24, 0x5e, 0xa9, 0x10, 0x9b, 0x1b, 0x7c, 0x70, 0x75, 0x40, 0x61, 0xe2, 0xc5, 0x49, + 0x08, 0xac, 0x04, 0x2f, 0x88, 0x36, 0x82, 0x2f, 0xc3, 0xd9, 0xbd, 0xd9, 0x74, 0x46, 0x1c, 0x35, + 0x1e, 0x95, 0x3d, 0x08, 0x1a, 0xf5, 0xbe, 0x79, 0xff, 0xce, 0x3c, 0x62, 0x2c, 0xf5, 0x0f, 0x49, + 0x38, 0x83, 0xfb, 0xf1, 0x80, 0x76, 0x87, 0x6b, 0xf4, 0x59, 0xb3, 0x3b, 0xf8, 0x3f, 0xcf, 0xb7, + 0x05, 0xa6, 0x1b, 0xae, 0x52, 0x91, 0x48, 0xe6, 0x0d, 0xe8, 0x80, 0xf6, 0x3d, 0xf2, 0x59, 0x53, + 0x6b, 0xbf, 0xfc, 0x5c, 0x25, 0xad, 0xb4, 0x63, 0xef, 0x35, 0x41, 0xef, 0x34, 0xfb, 0xac, 0x69, + 0x26, 0xf2, 0x1c, 0x99, 0x5f, 0xf3, 0x07, 0x00, 0xe8, 0x92, 0x2d, 0xc9, 0x3b, 0xa8, 0xec, 0xc4, + 0xd9, 0xd7, 0xf0, 0xb6, 0xe4, 0x02, 0x28, 0x98, 0x5a, 0xc6, 0x65, 0x53, 0xf3, 0x61, 0x8f, 0xd7, + 0xd9, 0xda, 0x7c, 0x18, 0xef, 0x14, 0xbb, 0x35, 0xe9, 0xaf, 0x93, 0x3b, 0x76, 0x0f, 0x74, 0x5f, + 0xe0, 0xe1, 0xff, 0x01, 0xdb, 0x7f, 0xac, 0xfd, 0xf1, 0x6d, 0x00, 0x00 +}; + diff --git a/wled00/wled.cpp b/wled00/wled.cpp index c27b0e75a8..a2d97b077f 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -696,56 +696,7 @@ if (multiWiFi.empty()) { // guard: handle empty WiFi list // convert the "serverDescription" into a valid DNS hostname (alphanumeric) char hostname[25]; prepareHostname(hostname); -#if defined(CONFIG_IDF_TARGET_ESP32C5) - // ESP32-C5: Prefer 5GHz WiFi 6 for better performance - DEBUG_PRINTF_P(PSTR("ESP32-C5: Trying 5GHz for SSID: %s\n"), multiWiFi[selectedWiFi].clientSSID); - - WiFi.disconnect(true); - WiFi.mode(WIFI_STA); - - // Set country code to enable all 5GHz channels - wifi_country_t country = { - .cc = "US", - .schan = 1, - .nchan = 14, - .max_tx_power = 80, - .policy = WIFI_COUNTRY_POLICY_MANUAL - }; - esp_wifi_set_country(&country); - WiFi.setBandMode(WIFI_BAND_MODE_5G_ONLY); - DEBUG_PRINTLN(F("ESP32-C5: Band mode set to 5GHz ONLY")); - - wifi_config_t wifi_config = {}; - strncpy((char*)wifi_config.sta.ssid, multiWiFi[selectedWiFi].clientSSID, sizeof(wifi_config.sta.ssid) - 1); - strncpy((char*)wifi_config.sta.password, multiWiFi[selectedWiFi].clientPass, sizeof(wifi_config.sta.password) - 1); - wifi_config.sta.scan_method = WIFI_ALL_CHANNEL_SCAN; - wifi_config.sta.sort_method = WIFI_CONNECT_AP_BY_SIGNAL; - wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; - esp_wifi_set_config(WIFI_IF_STA, &wifi_config); - esp_wifi_connect(); - - // Wait up to 20 seconds for 5GHz connection - DEBUG_PRINTLN(F("ESP32-C5: Waiting for 5GHz connection (20s timeout)...")); - unsigned long c5start = millis(); - while (WiFi.status() != WL_CONNECTED && millis() - c5start < 20000) { - delay(250); - if ((millis() - c5start) % 3000 < 250) { - DEBUG_PRINTF_P(PSTR(" ...%lus, status=%d\n"), (millis() - c5start) / 1000, WiFi.status()); - } - } - - if (WiFi.status() != WL_CONNECTED) { - DEBUG_PRINTLN(F("ESP32-C5: 5GHz failed, falling back to AUTO mode")); - esp_wifi_disconnect(); - WiFi.setBandMode(WIFI_BAND_MODE_AUTO); - esp_wifi_set_config(WIFI_IF_STA, &wifi_config); - esp_wifi_connect(); - } else { - DEBUG_PRINTF_P(PSTR("ESP32-C5: Connected on 5GHz, channel: %d\n"), WiFi.channel()); - } -#else WiFi.begin(multiWiFi[selectedWiFi].clientSSID, multiWiFi[selectedWiFi].clientPass); // no harm if called multiple times -#endif #ifdef ARDUINO_ARCH_ESP32 WiFi.setTxPower(wifi_power_t(txPower)); From 11f5be1861f96e92b24aac6040bbae9c8c552379 Mon Sep 17 00:00:00 2001 From: Jonny Davey Date: Sat, 7 Feb 2026 17:02:22 +0000 Subject: [PATCH 27/83] Removed Leftover file --- .claude/settings.local.json | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json deleted file mode 100644 index 0e384661ea..0000000000 --- a/.claude/settings.local.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "permissions": { - "allow": [ - "Bash(gh pr view:*)" - ] - } -} From 35706f094036d3677348d578ef43bf0c4baf4b20 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 7 Feb 2026 17:52:08 +0000 Subject: [PATCH 28/83] Apply suggestion from @coderabbitai[bot] for WiFi band Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- wled00/json.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wled00/json.cpp b/wled00/json.cpp index 60c9c3a036..1c25433bde 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -798,7 +798,9 @@ void serializeInfo(JsonObject root) wifi_info[F("signal")] = getSignalQuality(qrssi); int wifiChannel = WiFi.channel(); wifi_info[F("channel")] = wifiChannel; - wifi_info[F("band")] = (wifiChannel >= 36) ? F("5GHz") : F("2.4GHz"); + if (wifiChannel > 0) { + wifi_info[F("band")] = (wifiChannel >= 36) ? F("5GHz") : F("2.4GHz"); + } wifi_info[F("ap")] = apActive; JsonObject fs_info = root.createNestedObject("fs"); From 5137768a8fec22d69c553614765f903234aee623 Mon Sep 17 00:00:00 2001 From: Jonny Davey Date: Sat, 7 Feb 2026 18:13:12 +0000 Subject: [PATCH 29/83] Address PR review: pin pioarduino, fix I2S1 remap, simplify arch check --- platformio.ini | 3 +- wled00/bus_wrapper.h | 2 +- wled00/idf_component.yml | 2 - wled00/idf_component.yml.orig | 2 - wled00/js_iro.h | 636 ---------------------------------- wled00/json.cpp | 5 +- wled00/ota_update.cpp | 1 + wled00/wled.cpp | 2 +- wled00/wled.h | 8 +- 9 files changed, 14 insertions(+), 647 deletions(-) delete mode 100644 wled00/idf_component.yml delete mode 100644 wled00/idf_component.yml.orig delete mode 100644 wled00/js_iro.h diff --git a/platformio.ini b/platformio.ini index 663e0b037c..9e7b612584 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,6 +30,7 @@ default_envs = ; esp32s3dev_8MB_opi ;; TODO: disabled NeoEsp32RmtMethodIsr ; esp32s3_4M_qspi ;; TODO: disabled NeoEsp32RmtMethodIsr esp32c6dev_4MB + esp32c5dev ; esp32c3dev_qio ; esp32S3_wroom2 ; usermods @@ -457,7 +458,7 @@ build_flags = ${env:esp32c6dev_8MB.build_flags} -D WLED_RELEASE_NAME=\"ESP32 [esp32c5] ;; generic definitions for all ESP32-C5 boards ;; NOTE: ESP32-C5 requires pioarduino platform (Tasmota framework doesn't include C5 Arduino libs yet) -platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.36/platform-espressif32.zip platform_packages = build_unflags = ${esp32_idf_V5.build_unflags} -D WLED_ENABLE_DMX_INPUT ;; esp_dmx library doesn't support C5 UART registers yet diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index 6beab153bf..9a687f19af 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -503,7 +503,7 @@ class PolyBus { } #endif - #if defined(ARDUINO_ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3)) + #if defined(ARDUINO_ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5)) // 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 > 0) channel--; // accommodate I2S1 which is used as 1st bus on classic ESP32 #endif diff --git a/wled00/idf_component.yml b/wled00/idf_component.yml deleted file mode 100644 index d752765ffb..0000000000 --- a/wled00/idf_component.yml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - idf: '>=5.1' diff --git a/wled00/idf_component.yml.orig b/wled00/idf_component.yml.orig deleted file mode 100644 index d752765ffb..0000000000 --- a/wled00/idf_component.yml.orig +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - idf: '>=5.1' diff --git a/wled00/js_iro.h b/wled00/js_iro.h deleted file mode 100644 index 2dfc6daa6c..0000000000 --- a/wled00/js_iro.h +++ /dev/null @@ -1,636 +0,0 @@ -/* - * More web UI HTML source arrays. - * This file is auto generated, please don't make any changes manually. - * - * Instead, see https://kno.wled.ge/advanced/custom-features/#changing-web-ui - * to find out how to easily modify the web UI source! - */ - -// Autogenerated from wled00/data//iro.js, do not edit!! -const uint16_t JS_iro_length = 9964; -const uint8_t JS_iro[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xc5, 0x7d, 0x6b, 0x73, 0xe3, 0x36, - 0xb2, 0xe8, 0xf7, 0x5b, 0x75, 0xff, 0x83, 0xcd, 0x64, 0x54, 0x80, 0x04, 0xc1, 0x94, 0x6c, 0x79, - 0xc6, 0x94, 0x71, 0x54, 0xc9, 0xe4, 0x31, 0xb3, 0x9b, 0xd9, 0xc9, 0xc9, 0xcc, 0x66, 0x77, 0xa3, - 0x51, 0x52, 0x14, 0x05, 0x49, 0x18, 0x53, 0xa0, 0x02, 0x82, 0xb2, 0x1d, 0x91, 0xff, 0xfd, 0x56, - 0x03, 0xe0, 0x43, 0x0f, 0x3f, 0xb2, 0xf7, 0xec, 0xbd, 0x95, 0xd4, 0x08, 0xc4, 0xa3, 0x01, 0x34, - 0xba, 0x1b, 0xdd, 0x8d, 0x06, 0xfc, 0xbf, 0xff, 0xd7, 0xe9, 0x3c, 0x93, 0x91, 0x16, 0x89, 0x44, - 0x9a, 0x48, 0xbc, 0xf5, 0x92, 0xe9, 0x67, 0x1e, 0x69, 0x8f, 0x31, 0x7d, 0xbf, 0xe6, 0xc9, 0xfc, - 0x84, 0xdf, 0xad, 0x13, 0xa5, 0xd3, 0x56, 0xcb, 0xcb, 0xe4, 0x8c, 0xcf, 0x85, 0xe4, 0x33, 0xef, - 0xb4, 0x2c, 0x5c, 0x25, 0xb3, 0x2c, 0xe6, 0x23, 0xfb, 0x43, 0x5d, 0x55, 0x26, 0x11, 0x0e, 0xbc, - 0x12, 0x6c, 0x0d, 0xc9, 0xb6, 0x6e, 0xb5, 0xec, 0x2f, 0x0d, 0x57, 0xb3, 0x91, 0x4d, 0x22, 0x89, - 0x03, 0xa4, 0x99, 0xce, 0xf3, 0x94, 0xc7, 0x73, 0x4c, 0x85, 0x4a, 0x00, 0x46, 0x81, 0xf4, 0x52, - 0xa4, 0xa4, 0x1a, 0x1f, 0xde, 0x7a, 0x59, 0xca, 0x4f, 0x52, 0xad, 0x44, 0xa4, 0xbd, 0xe1, 0x26, - 0x54, 0x27, 0x2b, 0x92, 0x12, 0x49, 0x04, 0x49, 0xc8, 0x1d, 0xdb, 0x16, 0xe4, 0x33, 0x1b, 0x4f, - 0x88, 0x62, 0x67, 0x61, 0x24, 0x74, 0xce, 0xef, 0xd0, 0x28, 0x48, 0xf3, 0x45, 0x2e, 0xf3, 0x75, - 0xfe, 0x25, 0xce, 0xd5, 0x7a, 0x99, 0x2f, 0x94, 0x98, 0xe5, 0xc9, 0x6d, 0x9a, 0xaf, 0x64, 0x94, - 0x4b, 0x7d, 0x9b, 0x0b, 0xc9, 0xc7, 0xd1, 0x72, 0x92, 0xff, 0x91, 0x24, 0xf9, 0xaf, 0x89, 0x9a, - 0xe5, 0xbf, 0x76, 0xbb, 0x67, 0x62, 0x58, 0xf6, 0x79, 0xf2, 0xce, 0x62, 0x65, 0x9e, 0x28, 0x04, - 0xfd, 0x89, 0x13, 0x21, 0x4f, 0x24, 0xd6, 0x63, 0x31, 0x61, 0x72, 0x2c, 0x26, 0x43, 0xc5, 0x75, - 0xa6, 0xe4, 0x89, 0x2e, 0xaa, 0x16, 0xf7, 0x48, 0xe3, 0x2d, 0xd4, 0x95, 0x4c, 0xd3, 0x75, 0xa8, - 0xb8, 0xd4, 0x7f, 0x4b, 0x66, 0x7c, 0x28, 0x5b, 0x2d, 0x49, 0x15, 0x5f, 0x25, 0x1b, 0xfe, 0x7a, - 0x29, 0xe2, 0x19, 0xd2, 0xb8, 0x6e, 0xb4, 0x84, 0x6e, 0x88, 0xb0, 0x0d, 0x15, 0xe1, 0x24, 0x23, - 0x09, 0x89, 0x59, 0xa8, 0x16, 0xd9, 0x8a, 0x4b, 0x9d, 0x0e, 0xc5, 0x1c, 0x49, 0xf6, 0x0e, 0x6d, - 0x0b, 0x22, 0x31, 0x39, 0xbf, 0xae, 0x0a, 0x68, 0xcc, 0xe5, 0x42, 0x2f, 0x31, 0x0c, 0x50, 0xb0, - 0xb1, 0x80, 0xe9, 0x9f, 0x0f, 0xd5, 0x41, 0x85, 0xa1, 0xea, 0x74, 0xb0, 0xa0, 0xeb, 0x2c, 0x5d, - 0xa2, 0x78, 0xac, 0x26, 0xd8, 0x40, 0xcc, 0xe2, 0xf8, 0x94, 0x89, 0x56, 0x0b, 0x49, 0x1a, 0xc1, - 0x98, 0x14, 0x97, 0x4c, 0x60, 0x62, 0xf3, 0x75, 0xab, 0xe5, 0x12, 0x74, 0xc6, 0xe7, 0x61, 0x16, - 0xeb, 0x1f, 0x55, 0xb2, 0x4e, 0x4d, 0x57, 0x1c, 0xf0, 0xb0, 0x97, 0xbf, 0x49, 0xc4, 0xec, 0xc4, - 0x67, 0x8c, 0xc9, 0x31, 0x9f, 0x00, 0xcc, 0x31, 0x9f, 0xec, 0xb5, 0x1d, 0xf3, 0x09, 0x2e, 0x51, - 0x96, 0x30, 0x49, 0x6f, 0xf8, 0xbd, 0xeb, 0x0c, 0x65, 0x0c, 0xb0, 0x33, 0xc7, 0x40, 0x1e, 0x31, - 0xd7, 0xfc, 0xc4, 0x7c, 0xba, 0xd2, 0xa4, 0x91, 0x0b, 0x6d, 0x22, 0x83, 0xae, 0x84, 0x64, 0x0d, - 0x14, 0xda, 0x3c, 0x41, 0x94, 0x45, 0x22, 0x67, 0x5b, 0x20, 0xbb, 0x40, 0x93, 0x35, 0xf4, 0x1c, - 0x48, 0x72, 0xc3, 0xef, 0x03, 0x41, 0x14, 0x9f, 0x07, 0x8a, 0xc8, 0x00, 0x00, 0x13, 0x61, 0x7f, - 0x78, 0xe0, 0x93, 0xc4, 0x26, 0x63, 0xfb, 0x13, 0xb9, 0x9f, 0x44, 0xa6, 0x5a, 0x65, 0x91, 0x4e, - 0x54, 0x60, 0xa7, 0x57, 0x94, 0xc3, 0x5f, 0xd1, 0x8d, 0x4c, 0x66, 0xbc, 0xd5, 0x72, 0x09, 0xc4, - 0x31, 0xe1, 0xf5, 0x68, 0xde, 0x03, 0x15, 0x94, 0xc4, 0x51, 0x21, 0xb7, 0x2e, 0x7f, 0x6b, 0xe9, - 0x0a, 0x08, 0x9c, 0x9a, 0x01, 0x32, 0x4d, 0xcc, 0x47, 0x94, 0x48, 0xcd, 0xef, 0x34, 0x6b, 0xd4, - 0xbd, 0xb5, 0x75, 0xdd, 0x82, 0x31, 0x26, 0x71, 0x05, 0x58, 0x8c, 0x6e, 0x91, 0xa6, 0x82, 0x68, - 0x2a, 0xa8, 0xa4, 0x42, 0xce, 0xf8, 0xdd, 0xfb, 0x39, 0xd2, 0xb8, 0xd3, 0xc3, 0x66, 0x06, 0xc3, - 0x8a, 0x70, 0x87, 0xf2, 0x5a, 0x53, 0x59, 0x52, 0x83, 0x04, 0x6a, 0x28, 0x09, 0x00, 0x09, 0xa6, - 0xa9, 0x1c, 0xcb, 0x09, 0x2e, 0x57, 0x5c, 0xd0, 0xa4, 0xec, 0x43, 0xd0, 0xc4, 0x4d, 0xf9, 0x08, - 0x47, 0x6b, 0x0a, 0x09, 0x18, 0x83, 0xed, 0xae, 0x1e, 0x73, 0x58, 0x71, 0x01, 0x11, 0x35, 0xa9, - 0x01, 0x93, 0x53, 0x81, 0x6b, 0xc2, 0x8a, 0x2c, 0x6b, 0x69, 0x9a, 0xc0, 0x07, 0x9d, 0x86, 0x29, - 0x67, 0x06, 0xf3, 0x92, 0xf9, 0x7f, 0x7a, 0xc4, 0xdb, 0x1d, 0x30, 0x30, 0xf0, 0xa9, 0xe2, 0xe1, - 0x4d, 0xe1, 0x66, 0x02, 0x43, 0x2a, 0xea, 0x11, 0x72, 0x18, 0x21, 0x3a, 0xd5, 0x74, 0xde, 0x6a, - 0x21, 0x4d, 0xe7, 0xec, 0xd4, 0xc7, 0xad, 0x56, 0x8f, 0x31, 0x96, 0x5a, 0x36, 0xd1, 0x38, 0xcf, - 0xc5, 0x29, 0x63, 0x2b, 0x3a, 0xe3, 0xd3, 0x24, 0x93, 0x11, 0xff, 0x89, 0xcb, 0x19, 0x57, 0x42, - 0x2e, 0x70, 0xab, 0x85, 0xc4, 0xb1, 0x02, 0x82, 0x8e, 0x64, 0xe6, 0xb9, 0xc4, 0x28, 0xc3, 0x0d, - 0x5a, 0xcd, 0x90, 0x45, 0x8e, 0xa3, 0xd8, 0x92, 0xdf, 0xcd, 0x6a, 0xa5, 0x34, 0x4d, 0x94, 0x46, - 0xbb, 0x52, 0xd9, 0x4d, 0x41, 0xd2, 0x19, 0xe5, 0x5d, 0x0d, 0xff, 0x16, 0x78, 0xa8, 0x61, 0xa4, - 0xc9, 0x1a, 0xe1, 0x21, 0xb6, 0xb3, 0x50, 0x4c, 0x30, 0x4b, 0xa6, 0x24, 0x63, 0x88, 0x33, 0x24, - 0x99, 0xc6, 0x74, 0x86, 0x69, 0x42, 0x80, 0xdb, 0xd6, 0x24, 0x66, 0x92, 0x66, 0x44, 0xd2, 0x8c, - 0x9d, 0xf6, 0x48, 0x62, 0x26, 0x61, 0x04, 0xe6, 0x0d, 0x4a, 0x08, 0x27, 0x46, 0xbc, 0x70, 0x4c, - 0x24, 0xbd, 0x25, 0x16, 0xcc, 0x29, 0x63, 0x09, 0x4d, 0x6e, 0x25, 0x57, 0x1f, 0x7e, 0xfe, 0xfe, - 0xdb, 0x98, 0x83, 0x44, 0x21, 0x96, 0x73, 0x48, 0x4c, 0x2c, 0x35, 0x66, 0xa3, 0x5b, 0xc4, 0x71, - 0x90, 0x61, 0x32, 0x43, 0x02, 0x9a, 0xab, 0x53, 0x96, 0xb5, 0x5a, 0x21, 0xe2, 0xb8, 0x39, 0xe5, - 0x0f, 0x08, 0xa6, 0xaa, 0xeb, 0xc9, 0x92, 0xd4, 0xe2, 0x20, 0x22, 0x21, 0x99, 0x93, 0x25, 0xd9, - 0x90, 0x19, 0x59, 0x90, 0x29, 0x88, 0x1d, 0x4d, 0x65, 0x9e, 0x7f, 0x26, 0x6b, 0x36, 0x2d, 0x57, - 0x5f, 0xcc, 0x51, 0xcc, 0xd8, 0x5d, 0xab, 0x85, 0x62, 0x66, 0x17, 0x3c, 0x1b, 0x65, 0x63, 0x7f, - 0x12, 0xac, 0x81, 0xf8, 0x88, 0x6f, 0xc9, 0x0f, 0x93, 0x88, 0xf9, 0x44, 0x50, 0xc9, 0xbe, 0x42, - 0x82, 0xca, 0x7a, 0xe7, 0xd0, 0x15, 0xf7, 0x9c, 0x32, 0x9b, 0xd6, 0x54, 0x30, 0x60, 0x1b, 0xa0, - 0x13, 0xde, 0xe9, 0xb9, 0xb9, 0x30, 0x34, 0x67, 0xd3, 0x71, 0x34, 0xc1, 0x79, 0x3e, 0x87, 0x61, - 0xdc, 0xf0, 0x7b, 0xc6, 0xe6, 0xf0, 0x03, 0x5f, 0x40, 0xeb, 0x0c, 0xbe, 0x21, 0x81, 0xa1, 0x9e, - 0xc3, 0xf6, 0x90, 0xc7, 0x29, 0x3f, 0x81, 0xc5, 0x0b, 0x99, 0x3f, 0x0c, 0xaf, 0xd7, 0xc3, 0xb0, - 0xd3, 0x31, 0xdd, 0x18, 0x78, 0x21, 0x90, 0xe9, 0xe3, 0xc0, 0xb6, 0x50, 0xab, 0x84, 0x66, 0xa9, - 0x76, 0x6e, 0x26, 0x5a, 0x88, 0x39, 0x5a, 0xb2, 0x1b, 0x24, 0x89, 0x26, 0x73, 0x36, 0xcf, 0xf3, - 0xbb, 0x0a, 0x83, 0x56, 0x5e, 0x91, 0x14, 0x13, 0x14, 0x32, 0xed, 0x84, 0xe7, 0x1c, 0x7e, 0x4f, - 0x59, 0xd8, 0x6a, 0xa1, 0x05, 0x5b, 0xe4, 0xf9, 0x78, 0x82, 0x2d, 0x35, 0x87, 0x44, 0xd3, 0x28, - 0xcf, 0x97, 0x44, 0x97, 0xf2, 0x7d, 0xd9, 0x10, 0x29, 0xb3, 0x56, 0x0b, 0xcd, 0xd8, 0xb2, 0x12, - 0xfd, 0x34, 0xc6, 0x4b, 0xf8, 0x97, 0x68, 0x6a, 0x11, 0x6e, 0xa7, 0x28, 0xe6, 0x28, 0x63, 0x30, - 0x8a, 0xe5, 0x29, 0x8b, 0xf3, 0xdc, 0xb6, 0x5d, 0x36, 0x76, 0x39, 0xbc, 0xd5, 0x41, 0x05, 0x34, - 0xce, 0xf3, 0xb8, 0x51, 0x76, 0x0a, 0x92, 0x4b, 0xd2, 0x70, 0xbd, 0xe6, 0x72, 0x66, 0xb7, 0xc0, - 0x25, 0x36, 0x70, 0xed, 0xf6, 0xca, 0x62, 0x02, 0xe8, 0x43, 0x1b, 0xb6, 0xa1, 0x92, 0xdf, 0xe9, - 0x0f, 0x62, 0x1a, 0x5b, 0x5e, 0xb3, 0x18, 0x65, 0x7d, 0x10, 0x00, 0x1b, 0xc6, 0x96, 0xd8, 0x60, - 0xe8, 0x44, 0x0f, 0x41, 0xe4, 0xa5, 0x5c, 0xe9, 0xaf, 0xf9, 0x3c, 0x51, 0x1c, 0x2d, 0x49, 0x8c, - 0x0b, 0x2f, 0x59, 0x3b, 0x21, 0x25, 0x0c, 0x6e, 0xcd, 0xee, 0xb6, 0x09, 0xe3, 0x8c, 0x33, 0xcf, - 0xc3, 0x45, 0xcc, 0x96, 0x4d, 0xe8, 0xe4, 0x88, 0x54, 0xab, 0xda, 0x09, 0x1a, 0xb3, 0x25, 0x2e, - 0x4a, 0x01, 0x12, 0x75, 0x3a, 0x44, 0x17, 0x98, 0x08, 0x9a, 0xb0, 0x99, 0xc3, 0x54, 0xd6, 0x6a, - 0xd5, 0x10, 0x4e, 0x77, 0x21, 0x98, 0x9d, 0x32, 0x62, 0x59, 0x49, 0xc4, 0x51, 0xb7, 0x3b, 0xc4, - 0xae, 0xd9, 0x38, 0x9a, 0xb4, 0x5a, 0xf7, 0x08, 0x7e, 0xf1, 0xd0, 0xd6, 0x5b, 0x37, 0x2b, 0x4c, - 0x4d, 0x85, 0xbf, 0x21, 0xf8, 0x25, 0x86, 0x24, 0x81, 0x07, 0x16, 0x0e, 0xa4, 0x3f, 0x8c, 0xae, - 0x17, 0x15, 0xd8, 0x4e, 0x07, 0x7f, 0x8b, 0x16, 0x50, 0x71, 0x31, 0xee, 0x74, 0xaa, 0x9f, 0x06, - 0xf3, 0x7d, 0x55, 0xaa, 0x17, 0xd5, 0xda, 0x08, 0xc7, 0xfc, 0xd8, 0x51, 0xbe, 0xce, 0x73, 0x6f, - 0x9a, 0x24, 0x31, 0x0f, 0x9b, 0xe2, 0x1d, 0xcb, 0x56, 0xcb, 0x29, 0x0d, 0xd2, 0x34, 0xc4, 0xb8, - 0x22, 0x84, 0xaf, 0x94, 0x0a, 0xef, 0xa9, 0x48, 0xcd, 0x2f, 0xd2, 0x18, 0x97, 0x5b, 0x8d, 0x62, - 0xfe, 0x50, 0x5d, 0xeb, 0xa6, 0xe2, 0xf1, 0x15, 0xd2, 0x63, 0x35, 0x31, 0x43, 0x70, 0xed, 0x1d, - 0xd0, 0x91, 0x44, 0x47, 0x98, 0xf4, 0xc1, 0xe1, 0x94, 0x62, 0x10, 0x08, 0x52, 0xcc, 0x91, 0x07, - 0xaa, 0xa0, 0x5c, 0x34, 0x6a, 0xe4, 0xb9, 0x27, 0xb3, 0xd5, 0x94, 0xab, 0x23, 0xad, 0x22, 0x03, - 0x9b, 0x38, 0x01, 0x66, 0x66, 0x33, 0xac, 0x3b, 0xa4, 0x89, 0xdd, 0x4a, 0x98, 0xd9, 0x95, 0xca, - 0x0d, 0x76, 0x68, 0x15, 0xb9, 0x08, 0x59, 0x86, 0x25, 0xda, 0x6e, 0xd6, 0x44, 0x57, 0xaa, 0x4b, - 0xa5, 0xcf, 0x48, 0xb3, 0xf9, 0x24, 0x44, 0x16, 0x80, 0x8c, 0x40, 0x57, 0x05, 0xa2, 0x5e, 0x87, - 0x79, 0xb9, 0x0e, 0x5e, 0xd7, 0x33, 0x8a, 0x92, 0x3f, 0x19, 0x69, 0x9a, 0x72, 0xa3, 0x1d, 0x71, - 0xa5, 0xef, 0x41, 0x48, 0xe2, 0x40, 0x8f, 0xe5, 0x84, 0x1d, 0x4c, 0x44, 0xb4, 0x5a, 0xa7, 0xb0, - 0x3d, 0x29, 0xaa, 0x79, 0xaa, 0x91, 0xc4, 0x23, 0xd1, 0xf1, 0xd6, 0x77, 0x5e, 0xe0, 0x56, 0x74, - 0xe4, 0x79, 0x41, 0xa3, 0xaf, 0x9f, 0x50, 0xb5, 0xbb, 0x58, 0x41, 0xeb, 0xa4, 0x2e, 0x89, 0x0c, - 0xea, 0x6e, 0xf8, 0x3d, 0x0c, 0x01, 0x49, 0xc6, 0x47, 0x5e, 0x14, 0x87, 0x69, 0xfa, 0xb7, 0x70, - 0xc5, 0xcd, 0xa8, 0xdc, 0xb7, 0x17, 0xc8, 0xc0, 0xa5, 0x1a, 0xb9, 0xa6, 0x56, 0x20, 0x71, 0x9e, - 0x7b, 0xa5, 0x56, 0x63, 0x8a, 0x6b, 0xc2, 0xf0, 0x52, 0x7d, 0x1f, 0x5b, 0x48, 0xd8, 0x08, 0x0c, - 0x4d, 0x4d, 0x0e, 0x39, 0x58, 0x2e, 0x81, 0x33, 0x1a, 0xa5, 0xe9, 0x47, 0xd0, 0x77, 0x84, 0x95, - 0x04, 0xc7, 0x56, 0x55, 0xb5, 0x5a, 0xa8, 0xae, 0xe8, 0x79, 0x44, 0x31, 0x2b, 0xed, 0x95, 0xa1, - 0xb9, 0x04, 0x74, 0x51, 0x85, 0x45, 0xab, 0x65, 0x52, 0x22, 0xcf, 0xe7, 0x08, 0xe6, 0xea, 0x79, - 0x66, 0x7d, 0x85, 0xa9, 0x14, 0x9b, 0x22, 0xac, 0x5a, 0x2d, 0x31, 0x8e, 0x27, 0x80, 0xc5, 0x71, - 0x3c, 0xb1, 0x35, 0x63, 0x02, 0x59, 0xb8, 0x80, 0xfe, 0xbd, 0xa4, 0x5c, 0x97, 0x56, 0xcb, 0xb3, - 0x13, 0x1b, 0xf7, 0x26, 0x23, 0x94, 0x32, 0x79, 0x6a, 0x90, 0x05, 0x5a, 0xe9, 0x3a, 0x0e, 0x23, - 0x8e, 0xce, 0x5e, 0x87, 0x6b, 0x9d, 0x29, 0xfe, 0xe5, 0x19, 0xf4, 0x84, 0x89, 0x64, 0x08, 0x45, - 0x4c, 0x52, 0x9d, 0xfc, 0x90, 0xdc, 0x72, 0xf5, 0x3a, 0x4c, 0x39, 0xc2, 0x18, 0xd4, 0xe4, 0x51, - 0x14, 0x48, 0x4c, 0xd3, 0x58, 0x44, 0x1c, 0xf5, 0x31, 0x11, 0x23, 0xa4, 0xf2, 0x5c, 0xd3, 0x70, - 0x36, 0xfb, 0x76, 0xc3, 0xa5, 0xfe, 0x41, 0xa4, 0x9a, 0x4b, 0xae, 0x90, 0x24, 0x1b, 0x23, 0xcd, - 0x35, 0xd5, 0x79, 0x0e, 0xff, 0xb2, 0x6d, 0x81, 0x31, 0xd0, 0x02, 0xd0, 0x84, 0xb3, 0x1d, 0x8e, - 0x35, 0xc1, 0x81, 0x17, 0x8b, 0x54, 0x7b, 0x20, 0x61, 0x5b, 0x2d, 0x4f, 0x87, 0x0b, 0xb3, 0x4a, - 0xee, 0x73, 0x9e, 0xa8, 0x95, 0x4b, 0x9f, 0xf2, 0x56, 0x4b, 0x1a, 0xd5, 0x7d, 0x64, 0x68, 0xac, - 0x49, 0x39, 0xc1, 0x31, 0x39, 0xd6, 0x6a, 0x79, 0xb3, 0x50, 0x2e, 0xb8, 0x4a, 0xb2, 0x34, 0xbe, - 0xff, 0xc0, 0xf5, 0x5b, 0x29, 0xb9, 0x7a, 0xf3, 0xf1, 0xdd, 0x0f, 0x0e, 0x22, 0x3a, 0xc4, 0xcb, - 0xaf, 0x77, 0xb1, 0x90, 0x37, 0xc1, 0xc8, 0xe2, 0x65, 0xe4, 0xfa, 0xc8, 0x73, 0x43, 0xbc, 0x62, - 0x54, 0x4e, 0xe4, 0x2b, 0xad, 0x95, 0x98, 0x66, 0x9a, 0xff, 0xed, 0x03, 0xf2, 0x96, 0x5a, 0xaf, - 0x83, 0xb3, 0xb3, 0xdb, 0xdb, 0x5b, 0x7a, 0x7b, 0x4e, 0x13, 0xb5, 0x38, 0xeb, 0x5d, 0x5d, 0x5d, - 0x9d, 0x19, 0x48, 0x1e, 0xd9, 0x47, 0x6a, 0x60, 0x78, 0xe6, 0xdf, 0x07, 0x00, 0x3c, 0xf6, 0xe4, - 0xb0, 0xc0, 0x28, 0xdd, 0xed, 0xc7, 0x30, 0x67, 0x43, 0xaa, 0x6e, 0x9a, 0x3a, 0x3e, 0xe8, 0xee, - 0x7a, 0x6c, 0xc5, 0xc4, 0x04, 0xad, 0x28, 0x87, 0x75, 0x1a, 0xb9, 0x5f, 0xd0, 0x8f, 0x9b, 0xe6, - 0xde, 0x0d, 0xda, 0xd3, 0xfc, 0x80, 0x2d, 0x2d, 0x97, 0xee, 0x28, 0x43, 0x64, 0x4d, 0xee, 0xc9, - 0x2d, 0xb9, 0x01, 0xb2, 0xba, 0x5f, 0x73, 0x20, 0xe7, 0x4a, 0x31, 0x93, 0xb4, 0x61, 0x9d, 0xec, - 0x48, 0x46, 0x14, 0xb2, 0x15, 0xe5, 0xb0, 0x6f, 0x22, 0x89, 0x87, 0x5a, 0xdd, 0xdb, 0x4d, 0xf9, - 0xc8, 0x4e, 0x77, 0x63, 0x44, 0xee, 0x1a, 0x74, 0x43, 0x23, 0xd6, 0xee, 0x19, 0x0a, 0xd9, 0x4d, - 0x69, 0x83, 0x7c, 0x84, 0x3d, 0xac, 0xd5, 0x52, 0xe3, 0x90, 0x46, 0x13, 0x72, 0xcb, 0xc2, 0xd1, - 0xfd, 0xe8, 0xde, 0xd6, 0xb4, 0x1b, 0x6a, 0x10, 0x52, 0x11, 0x28, 0x22, 0x68, 0x34, 0x9a, 0x82, - 0xea, 0x24, 0x69, 0xc4, 0x04, 0x8d, 0x30, 0x15, 0xa0, 0xe7, 0x04, 0xc8, 0x5b, 0xab, 0x44, 0x27, - 0xd0, 0x97, 0x27, 0xe4, 0xc9, 0x4d, 0xab, 0x75, 0x43, 0xab, 0x1c, 0xaa, 0x8c, 0x7a, 0x3c, 0x82, - 0x36, 0x73, 0x26, 0xf9, 0xed, 0xc9, 0x0d, 0x5a, 0x93, 0x5b, 0x1c, 0xa0, 0x3a, 0xe7, 0xad, 0xc9, - 0x21, 0xf3, 0xe6, 0x4c, 0xd9, 0x0d, 0x99, 0xbb, 0xb6, 0xec, 0x0f, 0x4c, 0xee, 0x5b, 0xad, 0x7b, - 0x9a, 0x66, 0x53, 0x34, 0x87, 0x7a, 0xd6, 0x92, 0x5a, 0x93, 0x39, 0x4d, 0x75, 0xa8, 0x79, 0x9e, - 0x23, 0x97, 0x02, 0x4e, 0xb2, 0x70, 0x8c, 0x71, 0x75, 0x4b, 0xe6, 0xf4, 0x96, 0x29, 0xb2, 0x64, - 0x73, 0xa3, 0xf8, 0x93, 0x39, 0x5d, 0x35, 0x36, 0xc3, 0x39, 0xfd, 0xdc, 0x6a, 0xa1, 0x39, 0xfd, - 0xcc, 0x5c, 0xf3, 0x52, 0x2f, 0xba, 0xa1, 0x0b, 0xae, 0xbf, 0xe1, 0x4a, 0x6c, 0xf8, 0xec, 0x03, - 0x14, 0x7c, 0xa7, 0x92, 0x95, 0xb1, 0x6c, 0x5b, 0xad, 0x77, 0xa6, 0x41, 0xd9, 0x62, 0x04, 0x1f, - 0x46, 0xa1, 0x9e, 0xd3, 0xcf, 0x38, 0x98, 0xd3, 0xcf, 0xe4, 0xe1, 0xc6, 0x68, 0x6d, 0x6a, 0x61, - 0xb2, 0xc4, 0x76, 0x00, 0x8f, 0xf5, 0x63, 0x47, 0x02, 0x73, 0x59, 0xad, 0x13, 0xc9, 0xa5, 0xfe, - 0x87, 0x88, 0xe3, 0x77, 0x49, 0x26, 0x35, 0x68, 0x7f, 0x87, 0xb9, 0xa8, 0x1c, 0x7c, 0xa3, 0xf0, - 0x1b, 0x31, 0x73, 0x2d, 0x12, 0xbb, 0x11, 0xcf, 0x71, 0x25, 0x7e, 0x9f, 0x37, 0x02, 0xc6, 0xe2, - 0x07, 0x86, 0xf2, 0x13, 0x8f, 0xb8, 0xd8, 0x70, 0x57, 0xf7, 0x91, 0x42, 0xbb, 0xb8, 0xa7, 0x0d, - 0x38, 0xe9, 0x32, 0xc9, 0xe2, 0xd9, 0xeb, 0xb2, 0xc1, 0xdf, 0xd7, 0xb3, 0x50, 0x73, 0xb7, 0xeb, - 0x3d, 0x50, 0x6a, 0x51, 0x47, 0x6e, 0xb1, 0x35, 0x24, 0x0f, 0x48, 0x00, 0xd6, 0x92, 0x98, 0x45, - 0xee, 0x11, 0x34, 0xa7, 0x33, 0x26, 0x31, 0x4d, 0x9c, 0x09, 0x91, 0x8e, 0xd2, 0x53, 0xd0, 0x12, - 0x93, 0x51, 0x1a, 0x08, 0xea, 0x1c, 0x00, 0x92, 0x4a, 0x06, 0xb6, 0x83, 0xd5, 0xe4, 0x65, 0x6d, - 0x80, 0x82, 0x4a, 0x2f, 0xa9, 0x1c, 0x87, 0xc6, 0xb7, 0x61, 0x12, 0x54, 0xc0, 0xbe, 0xe7, 0x94, - 0xd1, 0xe2, 0x28, 0x36, 0xca, 0x39, 0x1c, 0xcd, 0xae, 0x06, 0x5f, 0x58, 0x05, 0xd8, 0x8d, 0x9e, - 0xcc, 0x4a, 0x2a, 0xda, 0x23, 0xd9, 0x63, 0x73, 0x33, 0xcc, 0xfe, 0xce, 0x31, 0x7b, 0x39, 0x53, - 0x33, 0x51, 0x68, 0xc0, 0x34, 0x09, 0x59, 0xc9, 0x2f, 0x25, 0x76, 0xc8, 0x01, 0x74, 0x6c, 0xa6, - 0xfd, 0x95, 0xb3, 0x90, 0xc2, 0x56, 0x2b, 0x74, 0xf6, 0xc9, 0xfb, 0x72, 0xb5, 0x43, 0x50, 0x78, - 0x46, 0xa1, 0xe3, 0xfe, 0x72, 0xe7, 0x0f, 0xc2, 0x9a, 0xb8, 0x16, 0x5c, 0x1b, 0xa5, 0xfe, 0xb5, - 0x05, 0x69, 0xcc, 0xd1, 0x77, 0xc8, 0xb0, 0x80, 0x82, 0x81, 0xed, 0x95, 0x23, 0x0c, 0xf4, 0x5e, - 0xda, 0x10, 0xa6, 0xf8, 0x83, 0x0c, 0xd7, 0xe9, 0x32, 0x71, 0xda, 0xbc, 0x45, 0x51, 0x9e, 0xa3, - 0xc5, 0xc3, 0xa5, 0x68, 0x43, 0x66, 0x18, 0x93, 0x0f, 0x7b, 0xe2, 0x14, 0x84, 0x29, 0x99, 0x3b, - 0x6f, 0x02, 0x4d, 0x86, 0x80, 0x82, 0x55, 0x69, 0x2a, 0x97, 0xcc, 0x5d, 0xa1, 0x10, 0x93, 0x90, - 0x46, 0x61, 0x1c, 0x03, 0x13, 0x54, 0x03, 0xda, 0xd4, 0x23, 0x6b, 0x72, 0x4d, 0x39, 0xa8, 0x63, - 0xb9, 0xc8, 0x08, 0x6d, 0x4c, 0xa6, 0x06, 0xfc, 0x0d, 0x9b, 0x03, 0x79, 0x80, 0x9e, 0x62, 0x34, - 0x0b, 0xa3, 0x1f, 0x36, 0x8d, 0xfa, 0xa6, 0xf8, 0xb7, 0xa2, 0x3f, 0x25, 0xce, 0x16, 0x66, 0xc2, - 0x2d, 0xd4, 0xa6, 0x94, 0xcc, 0x20, 0xf9, 0x39, 0xf3, 0xd2, 0xcd, 0xc2, 0xe8, 0x24, 0x66, 0x75, - 0xf2, 0x9c, 0x97, 0xca, 0x7b, 0xc9, 0x42, 0x99, 0xd1, 0x75, 0x52, 0xe6, 0x0f, 0xd3, 0xeb, 0xca, - 0xec, 0x48, 0x77, 0x3c, 0x27, 0x11, 0xcb, 0xc6, 0x29, 0x18, 0xa4, 0x8e, 0xd1, 0x1d, 0xb0, 0xd1, - 0x39, 0x63, 0x2c, 0xa2, 0xe0, 0xc9, 0x02, 0xb1, 0x1f, 0x44, 0x34, 0x4e, 0xa2, 0x30, 0x06, 0x3d, - 0xa2, 0xaa, 0x83, 0xf1, 0x56, 0xb3, 0x88, 0x40, 0x7b, 0x6b, 0x13, 0x5a, 0x43, 0xb5, 0xd6, 0xa1, - 0x1b, 0x0a, 0x7c, 0xd9, 0xc4, 0xed, 0x4b, 0xb3, 0x24, 0x32, 0xee, 0x48, 0x1a, 0x29, 0x1e, 0x6a, - 0x0e, 0x8a, 0x1c, 0x98, 0x84, 0x68, 0x03, 0x5e, 0x0c, 0x3e, 0xda, 0x2b, 0x76, 0x9e, 0x86, 0xe3, - 0xfb, 0x7a, 0xdf, 0xf7, 0xfd, 0x33, 0x40, 0x04, 0x71, 0x5d, 0x04, 0xc7, 0x5b, 0x23, 0x57, 0x4c, - 0x32, 0x6b, 0x48, 0x37, 0x76, 0xc8, 0x7a, 0xd6, 0xcb, 0x53, 0xc6, 0x36, 0x0e, 0x17, 0xc6, 0x98, - 0x43, 0xd9, 0x38, 0x6b, 0xf8, 0xd1, 0x26, 0x4e, 0xd3, 0xd4, 0x74, 0x16, 0xea, 0x90, 0x6d, 0x70, - 0x00, 0xfa, 0x8e, 0xd8, 0x6d, 0xc1, 0x3e, 0x5b, 0xe5, 0xce, 0x52, 0x91, 0xf3, 0xf6, 0xc1, 0xf4, - 0x52, 0x8c, 0x49, 0xc8, 0x50, 0xb5, 0x9e, 0x79, 0x7e, 0x87, 0xe9, 0x03, 0xfa, 0x14, 0x99, 0xb3, - 0xcd, 0x83, 0x65, 0x31, 0xec, 0x64, 0x79, 0x1e, 0xc2, 0xb2, 0xcd, 0x5b, 0xad, 0x10, 0xe4, 0xc9, - 0x7b, 0x60, 0xca, 0xf7, 0x46, 0x51, 0x14, 0x65, 0x45, 0x36, 0x37, 0x25, 0x79, 0x6e, 0x34, 0xd2, - 0x43, 0x6a, 0x73, 0x86, 0x80, 0x31, 0x38, 0x33, 0xab, 0x11, 0x9b, 0x1f, 0x99, 0xe7, 0x60, 0x2e, - 0x64, 0xce, 0xb7, 0x33, 0xce, 0x26, 0x44, 0xe1, 0xba, 0x96, 0xc4, 0xfc, 0xa8, 0x99, 0x2b, 0xc7, - 0xd9, 0x24, 0xcf, 0x3d, 0xa3, 0x0b, 0x00, 0x5d, 0x66, 0xc6, 0x28, 0xe0, 0xd1, 0x0d, 0x9f, 0xb9, - 0x4f, 0x00, 0x65, 0x94, 0x68, 0xa8, 0xe8, 0xba, 0x00, 0xe8, 0xae, 0x8b, 0x02, 0x69, 0xb2, 0x21, - 0x4b, 0xc2, 0x49, 0x6c, 0x45, 0x90, 0xdc, 0x13, 0x30, 0x64, 0x9e, 0xe7, 0x35, 0x77, 0x83, 0x2a, - 0xcb, 0xc5, 0x42, 0xbe, 0xb7, 0x47, 0x14, 0xa7, 0xe5, 0x32, 0xb6, 0x5a, 0x96, 0x8f, 0xee, 0x00, - 0x0c, 0xe0, 0xca, 0x0d, 0x49, 0xc8, 0x93, 0x4d, 0xab, 0x55, 0x69, 0x4c, 0x1b, 0xab, 0xb5, 0xb4, - 0x5a, 0x2e, 0x71, 0x0a, 0xb6, 0x9e, 0xcb, 0x42, 0x2e, 0xe5, 0x54, 0x62, 0x57, 0x03, 0x14, 0x63, - 0x97, 0xc4, 0xa4, 0x9a, 0xda, 0x01, 0x58, 0x57, 0x00, 0x80, 0x5d, 0xd2, 0x80, 0xae, 0xb2, 0x51, - 0x95, 0xae, 0x2b, 0x83, 0xf8, 0xd3, 0x05, 0x12, 0x60, 0x31, 0x36, 0x44, 0x41, 0x84, 0xad, 0xfa, - 0x36, 0x13, 0xf3, 0x39, 0x9f, 0x39, 0xb1, 0x5e, 0x44, 0xa1, 0x8e, 0xc0, 0x21, 0xb9, 0x5d, 0xd1, - 0xc4, 0x99, 0x90, 0x45, 0x6d, 0x76, 0xd6, 0x7a, 0xe5, 0x6c, 0xef, 0xb4, 0x62, 0x08, 0x7e, 0xd2, - 0xd2, 0x45, 0xa8, 0xee, 0xb7, 0xe2, 0x50, 0x05, 0x40, 0x07, 0xd0, 0x05, 0x9d, 0xe1, 0x62, 0x45, - 0x23, 0x70, 0x6d, 0x47, 0xd0, 0x7b, 0x05, 0xfe, 0xdb, 0xd2, 0x7c, 0x05, 0x58, 0xc7, 0xdc, 0xc1, - 0x23, 0x6d, 0xb5, 0xe6, 0x28, 0x53, 0xe0, 0xf5, 0x61, 0xf2, 0x00, 0x76, 0xd3, 0x03, 0xfb, 0xb7, - 0x83, 0x43, 0x0f, 0x10, 0x73, 0x2b, 0x9a, 0xc9, 0x95, 0x55, 0x4e, 0xaa, 0x24, 0xd2, 0x98, 0x20, - 0x55, 0x39, 0xb9, 0xbe, 0x45, 0xca, 0x19, 0xf1, 0x98, 0x88, 0x3c, 0x7f, 0xd0, 0x31, 0x9d, 0xe7, - 0x48, 0xb8, 0xbd, 0x1e, 0x71, 0x30, 0xce, 0x01, 0xe7, 0xc6, 0x4c, 0x8f, 0x59, 0xe5, 0x04, 0x38, - 0x65, 0x06, 0x72, 0x84, 0x8d, 0xf4, 0x52, 0x7b, 0xfb, 0xb4, 0xed, 0xdf, 0x20, 0xef, 0x78, 0xd1, - 0x21, 0xfe, 0x24, 0x2e, 0x94, 0xdd, 0x7b, 0x14, 0x5d, 0x57, 0x4e, 0x3c, 0xe8, 0x43, 0x1a, 0xf1, - 0x9c, 0x31, 0x7f, 0x98, 0x5d, 0xab, 0x52, 0x3c, 0x67, 0x9d, 0x0e, 0x56, 0xe3, 0xcc, 0x78, 0x7b, - 0xe0, 0xd7, 0x7a, 0x49, 0xec, 0xc8, 0x38, 0xf8, 0x88, 0x78, 0x63, 0x05, 0xfe, 0x28, 0x51, 0xd6, - 0x34, 0x3b, 0x1a, 0xda, 0xb1, 0x45, 0x71, 0x55, 0x7d, 0xb1, 0x47, 0x0f, 0xcc, 0x1f, 0x8a, 0xeb, - 0x4a, 0xa3, 0x11, 0xe0, 0xa4, 0xb4, 0x1e, 0x1b, 0x7b, 0x96, 0x45, 0xb9, 0xcc, 0x56, 0x5c, 0x85, - 0xd3, 0x18, 0xc6, 0x5e, 0x7f, 0x80, 0x91, 0x44, 0x60, 0xfa, 0x72, 0x2e, 0x16, 0x99, 0x2d, 0x3f, - 0xf5, 0x49, 0xcd, 0x65, 0x60, 0xa1, 0x2b, 0x7a, 0xab, 0x84, 0x76, 0x65, 0x98, 0x58, 0x1e, 0xa5, - 0xf6, 0x80, 0xaf, 0x72, 0x6f, 0x68, 0xa2, 0x8c, 0xe7, 0x44, 0x35, 0xe9, 0x60, 0x8a, 0xca, 0xf9, - 0xa0, 0x29, 0x73, 0xed, 0xc2, 0x34, 0x15, 0x0b, 0x99, 0xe7, 0x4d, 0xef, 0x50, 0x39, 0x0d, 0x59, - 0x9f, 0x8b, 0x11, 0xc1, 0x7a, 0x43, 0x71, 0x78, 0xda, 0xb5, 0x3f, 0xb5, 0xb2, 0x29, 0xb7, 0xbe, - 0x02, 0xd7, 0x49, 0x6d, 0x8c, 0x2c, 0xc3, 0xf4, 0xfd, 0xad, 0x2c, 0x87, 0x69, 0x05, 0x39, 0xc8, - 0x4b, 0xe0, 0x5d, 0x38, 0xc6, 0x52, 0x70, 0x72, 0x55, 0x54, 0x87, 0x7d, 0x18, 0xbc, 0x98, 0xf1, - 0xbd, 0x3d, 0x9f, 0xac, 0x3a, 0xc7, 0xc5, 0x0a, 0x0e, 0x21, 0xdf, 0x36, 0xe0, 0xa6, 0x5c, 0x7f, - 0xb0, 0x7a, 0xc6, 0x8e, 0x3b, 0xdf, 0x2e, 0x86, 0x59, 0xbc, 0xcf, 0x20, 0x2a, 0x20, 0x61, 0xf4, - 0x91, 0x56, 0xcb, 0x66, 0x82, 0x58, 0x37, 0x09, 0x6b, 0x43, 0xd4, 0x15, 0x30, 0x1e, 0x1e, 0x23, - 0xf7, 0x56, 0xeb, 0x14, 0xce, 0x56, 0x90, 0x20, 0xf5, 0x89, 0x12, 0xc6, 0x79, 0xfe, 0x0e, 0x72, - 0x1a, 0x07, 0x7a, 0xa6, 0xd4, 0x48, 0x24, 0x48, 0x98, 0x63, 0x00, 0xe9, 0x72, 0x57, 0xce, 0x25, - 0x87, 0x09, 0x37, 0xa5, 0x18, 0xef, 0x4e, 0x65, 0x9e, 0xa8, 0xc8, 0xa9, 0x5d, 0xac, 0xb9, 0x2a, - 0x35, 0xc8, 0x5d, 0x40, 0x1a, 0x93, 0xb2, 0x13, 0xff, 0x01, 0x90, 0xce, 0x8c, 0x7b, 0x4f, 0x52, - 0x38, 0x86, 0x90, 0xec, 0xc8, 0xcc, 0x7e, 0x54, 0xc9, 0x4a, 0xa4, 0x7c, 0xe4, 0x7e, 0x1b, 0x8d, - 0xf5, 0x92, 0x4b, 0x3a, 0x15, 0x72, 0x86, 0xca, 0x32, 0xc5, 0xd3, 0x24, 0xde, 0x18, 0x07, 0x41, - 0xca, 0xf5, 0x47, 0xb1, 0xe2, 0x49, 0xa6, 0xc9, 0xf1, 0x73, 0x9a, 0xd5, 0x81, 0x36, 0x56, 0xd3, - 0x97, 0x1a, 0xc2, 0x46, 0x24, 0x86, 0xa0, 0x35, 0x21, 0x05, 0x56, 0x2d, 0x6e, 0xb5, 0x4e, 0x15, - 0x15, 0x56, 0x86, 0x5a, 0x21, 0x51, 0xb1, 0x5c, 0xa9, 0x7b, 0xed, 0x64, 0x1e, 0xb3, 0x9e, 0xbe, - 0x55, 0x0a, 0x0c, 0xf5, 0x8a, 0x26, 0xd0, 0xf3, 0x5a, 0x80, 0x37, 0x71, 0xcf, 0x38, 0x53, 0x3b, - 0x62, 0xfc, 0x35, 0x88, 0x1f, 0x0c, 0x9a, 0xbc, 0x90, 0x19, 0x1f, 0x1e, 0x29, 0x84, 0x83, 0x2f, - 0x47, 0xbb, 0xd0, 0xeb, 0x0d, 0x53, 0xa5, 0xd0, 0x82, 0x23, 0x48, 0x26, 0x0b, 0xbd, 0x54, 0xc9, - 0xed, 0x89, 0x2e, 0x48, 0xc2, 0xee, 0x8c, 0xcb, 0x53, 0x33, 0x0f, 0x8d, 0x82, 0x71, 0xf7, 0xd3, - 0xa7, 0xce, 0x64, 0xf4, 0xe9, 0xd3, 0xac, 0xfd, 0xe9, 0x13, 0xfd, 0xf4, 0x69, 0xd6, 0x79, 0x31, - 0xc2, 0xf9, 0x4e, 0x01, 0xe4, 0x78, 0x24, 0x66, 0xde, 0xf8, 0xd3, 0xa7, 0x34, 0xff, 0xf4, 0x09, - 0x4d, 0x3a, 0xc8, 0xeb, 0xe8, 0x8e, 0x87, 0xc7, 0x24, 0xff, 0xf4, 0x29, 0x7d, 0xe8, 0xf3, 0xd3, - 0xa7, 0xb4, 0xfd, 0xe9, 0x13, 0x1e, 0x79, 0x64, 0xfd, 0xa7, 0xdb, 0x3e, 0x08, 0xea, 0x37, 0xe3, - 0x35, 0xf8, 0x89, 0x2f, 0xbe, 0xbd, 0x5b, 0x23, 0x4f, 0x2d, 0xa6, 0x5e, 0x27, 0xc6, 0xe4, 0xcd, - 0x7e, 0x6e, 0xe8, 0x75, 0xd6, 0x98, 0xfc, 0xb8, 0x93, 0xbd, 0x4c, 0x63, 0x53, 0xf9, 0xcb, 0xfd, - 0x5c, 0x5b, 0xf9, 0x23, 0xf3, 0x7e, 0x45, 0xa3, 0xe0, 0x8b, 0x51, 0xee, 0xdf, 0xc1, 0x84, 0xff, - 0xc1, 0x3c, 0x34, 0xf6, 0xbb, 0x57, 0x61, 0x77, 0xfe, 0x55, 0xf7, 0xbb, 0xc9, 0xb6, 0x57, 0x60, - 0x8f, 0xbc, 0xde, 0xcb, 0xec, 0x43, 0xe6, 0x37, 0x4d, 0x80, 0x1f, 0x3b, 0xff, 0x30, 0xff, 0x79, - 0x5f, 0x7a, 0x98, 0x7c, 0x77, 0xac, 0xc4, 0x95, 0xfd, 0xb0, 0x5b, 0xf6, 0xda, 0xfc, 0x67, 0x4a, - 0xbe, 0x3e, 0x56, 0xe2, 0xca, 0x7e, 0x67, 0xef, 0x42, 0xbd, 0xa4, 0x71, 0xb2, 0x20, 0xdf, 0xdb, - 0xa4, 0x4a, 0x32, 0x39, 0x23, 0xbf, 0xd8, 0x8f, 0x79, 0x9c, 0x24, 0xaa, 0x0e, 0x6d, 0xf8, 0xcb, - 0xde, 0x5e, 0x62, 0xea, 0xac, 0x84, 0x44, 0x36, 0x11, 0xde, 0x19, 0x59, 0xb5, 0xb3, 0x9f, 0xfc, - 0xb5, 0x29, 0xbe, 0xba, 0xbd, 0x6b, 0x5d, 0xa9, 0xca, 0xde, 0x0b, 0x0f, 0x13, 0xc5, 0xd6, 0xa1, - 0x4a, 0xf9, 0x77, 0x71, 0x12, 0xc2, 0x96, 0x5d, 0x39, 0xc0, 0x47, 0xf2, 0xac, 0xe7, 0xfb, 0x6d, - 0x15, 0xa8, 0x1a, 0xd4, 0x7f, 0x37, 0x9c, 0x67, 0xa6, 0xd5, 0x5b, 0xd8, 0xe6, 0x49, 0xef, 0xb2, - 0xd1, 0xdd, 0xdf, 0x77, 0x0e, 0xd1, 0x75, 0xf2, 0xc1, 0x38, 0x86, 0x51, 0xef, 0x12, 0xd3, 0x75, - 0x08, 0x6c, 0xa2, 0x34, 0xea, 0x13, 0xcf, 0xf7, 0x70, 0x01, 0x43, 0xfa, 0x99, 0x35, 0x42, 0x45, - 0x2a, 0x20, 0x71, 0xe3, 0xa4, 0xfd, 0x4b, 0xb6, 0x5d, 0x06, 0x3e, 0x49, 0x03, 0x9f, 0x6c, 0x02, - 0x9f, 0x84, 0x41, 0xaf, 0x20, 0xa5, 0xd8, 0x4a, 0xb9, 0xae, 0x64, 0x56, 0x22, 0x5f, 0x2f, 0x41, - 0x15, 0x67, 0xd2, 0x7e, 0x0b, 0x29, 0xb4, 0x08, 0xe3, 0x9f, 0x8d, 0x86, 0x38, 0xad, 0x24, 0xf2, - 0x97, 0xb6, 0x5f, 0xcd, 0xe2, 0x5a, 0x2e, 0x55, 0x11, 0x21, 0x00, 0x90, 0xed, 0x1d, 0x6e, 0x1c, - 0x1e, 0x58, 0xe0, 0xb3, 0x06, 0x5d, 0x35, 0x89, 0xe7, 0x9c, 0xbc, 0x2a, 0xbe, 0x3c, 0xb3, 0xae, - 0x7e, 0x8d, 0x47, 0xa6, 0xbf, 0x25, 0xbf, 0xb3, 0x28, 0x60, 0x3a, 0x38, 0xfb, 0x15, 0x28, 0x79, - 0xb4, 0x57, 0x43, 0x2d, 0xa6, 0x8d, 0x1a, 0x40, 0xbe, 0x75, 0x8d, 0x52, 0xea, 0x2f, 0xd3, 0xb8, - 0xac, 0x53, 0x0b, 0x96, 0x32, 0xec, 0xe7, 0xb4, 0x1e, 0x99, 0x15, 0x0a, 0x40, 0x6d, 0x56, 0x0e, - 0x79, 0x6f, 0xe5, 0x26, 0x8c, 0xc5, 0xec, 0x24, 0x4a, 0xe2, 0x44, 0x9d, 0xd8, 0xcd, 0x1f, 0x0f, - 0xf5, 0x89, 0x90, 0xa9, 0x0e, 0x65, 0x04, 0xad, 0x62, 0x37, 0xd0, 0x74, 0x03, 0x47, 0x92, 0xf0, - 0x13, 0x78, 0x0a, 0x34, 0x04, 0xdd, 0x6a, 0x79, 0x8b, 0x32, 0x31, 0xf5, 0xac, 0x0b, 0xda, 0x8d, - 0x98, 0xe9, 0xc0, 0x5b, 0x96, 0x65, 0x69, 0x99, 0xd8, 0x34, 0x2a, 0x2d, 0xd3, 0xcd, 0xf1, 0x4a, - 0xf1, 0x4e, 0xa5, 0x18, 0x2a, 0xdd, 0xf0, 0x78, 0x23, 0xa4, 0xab, 0x60, 0x67, 0x6c, 0xb3, 0x98, - 0x76, 0x09, 0x5c, 0x14, 0xc4, 0x2c, 0x0f, 0x2c, 0xb2, 0xe4, 0xf1, 0xc1, 0x46, 0x60, 0x37, 0x01, - 0x68, 0x3a, 0xd6, 0x93, 0x7a, 0xbd, 0xc7, 0x7a, 0x42, 0x60, 0x43, 0xd8, 0x16, 0xd6, 0x29, 0x4f, - 0x14, 0x6c, 0x68, 0xa0, 0x94, 0xee, 0x2c, 0xb5, 0xa3, 0x35, 0x8b, 0x83, 0x7d, 0xea, 0x81, 0xfa, - 0x51, 0x9c, 0x48, 0xde, 0xac, 0x5f, 0xaa, 0xf2, 0xfc, 0x16, 0xa8, 0x15, 0x36, 0x4a, 0xa8, 0x96, - 0x49, 0xd8, 0xdd, 0x0e, 0xe0, 0x56, 0xb4, 0xe9, 0x02, 0x52, 0x48, 0x0c, 0x5d, 0x7d, 0x4c, 0x7e, - 0x5a, 0x4c, 0x77, 0xc8, 0xad, 0x0c, 0x41, 0x5a, 0x9e, 0x5d, 0xfa, 0x04, 0xec, 0x80, 0x14, 0x98, - 0x90, 0x80, 0x1e, 0xba, 0x31, 0x29, 0xce, 0x7e, 0x81, 0xdd, 0x3e, 0x63, 0xb2, 0xcb, 0x49, 0xc2, - 0x54, 0x1b, 0xf5, 0xba, 0x02, 0x93, 0xd8, 0xa6, 0xb2, 0xb6, 0xc0, 0x24, 0xb5, 0x69, 0xf8, 0xc4, - 0xf0, 0x1d, 0x31, 0xfe, 0xe2, 0x92, 0x84, 0x6c, 0x9c, 0x12, 0x45, 0x14, 0x89, 0x49, 0x42, 0x92, - 0x09, 0x1c, 0x3c, 0xce, 0xd9, 0x38, 0x31, 0x8e, 0x17, 0x93, 0x0d, 0x59, 0x8e, 0x0f, 0xb6, 0x2a, - 0xf8, 0x0b, 0xea, 0x0f, 0x06, 0xed, 0xb1, 0xab, 0x0e, 0x75, 0x4c, 0x13, 0x9f, 0xf4, 0x07, 0x03, - 0x4c, 0x16, 0xae, 0x3c, 0x2c, 0x33, 0xa6, 0x2e, 0x63, 0xee, 0x32, 0x0a, 0x98, 0xa1, 0x5a, 0x4c, - 0x3f, 0x26, 0x6f, 0xd2, 0xcd, 0xd1, 0x19, 0xaa, 0xb3, 0xfe, 0x60, 0x60, 0xa6, 0xb8, 0x30, 0x29, - 0x98, 0xe2, 0xd4, 0xa4, 0x38, 0xab, 0x64, 0x99, 0x0d, 0x0d, 0x22, 0x19, 0xab, 0xc4, 0x9c, 0xcb, - 0x49, 0x18, 0xef, 0x66, 0x24, 0x66, 0x3e, 0x49, 0x19, 0x87, 0x00, 0x02, 0xc6, 0x18, 0x1f, 0xf9, - 0x41, 0x72, 0xc6, 0x87, 0xe9, 0xad, 0x80, 0x5d, 0x92, 0xe3, 0x6d, 0x14, 0xa6, 0xfc, 0x24, 0x0b, - 0x62, 0xe6, 0x8e, 0xe7, 0x87, 0x26, 0x43, 0x06, 0x31, 0x43, 0xa2, 0xab, 0xf0, 0x59, 0xd2, 0x41, - 0xe2, 0x5a, 0x8d, 0x2e, 0x03, 0x1f, 0x37, 0x2b, 0x08, 0xa8, 0xa0, 0xba, 0x12, 0x2a, 0xf4, 0x9b, - 0x05, 0x0a, 0x0a, 0x64, 0x57, 0x40, 0xc1, 0x85, 0xdb, 0x9c, 0xb7, 0xcb, 0xe0, 0xd2, 0x6f, 0xc7, - 0x2f, 0xce, 0x2f, 0x41, 0x44, 0xfd, 0x05, 0x81, 0xcc, 0x8c, 0x88, 0x4f, 0x7a, 0xbe, 0x8f, 0xc9, - 0xc6, 0x65, 0xa4, 0x2e, 0xa3, 0xa8, 0x16, 0xfe, 0x4d, 0x1a, 0x1f, 0x45, 0x8b, 0x5d, 0x6f, 0x51, - 0xad, 0xb7, 0x62, 0xa8, 0xdf, 0x95, 0xb8, 0x2d, 0x08, 0x67, 0xea, 0x9a, 0xf5, 0x46, 0x2a, 0xe8, - 0x77, 0x15, 0xc9, 0x18, 0xbf, 0xee, 0xf1, 0xee, 0xd5, 0xc8, 0x0f, 0x64, 0x5b, 0x9c, 0x95, 0x02, - 0x6c, 0xbb, 0x0c, 0x34, 0x5d, 0x56, 0xe3, 0xc8, 0xca, 0x71, 0xc4, 0xc1, 0x5f, 0xd0, 0xc0, 0x6f, - 0xab, 0xdd, 0x61, 0xc4, 0x0f, 0xad, 0x4e, 0xbf, 0x0d, 0x51, 0x04, 0x86, 0xfc, 0xda, 0x48, 0x5e, - 0xb3, 0x9e, 0xef, 0x8f, 0x64, 0xd0, 0xf7, 0x7d, 0xc0, 0x89, 0x1d, 0x95, 0xec, 0x88, 0x72, 0x00, - 0xfd, 0xb6, 0x38, 0x43, 0xb2, 0x23, 0xf0, 0xf1, 0x41, 0xa8, 0x26, 0x32, 0x4c, 0xbd, 0xb3, 0x7e, - 0x73, 0x1c, 0x96, 0xbd, 0x1f, 0x60, 0x05, 0x6b, 0x64, 0x33, 0x0d, 0xbd, 0x96, 0x42, 0x5a, 0x31, - 0x7e, 0x7d, 0x79, 0x39, 0x42, 0x92, 0x59, 0x0a, 0xea, 0xf6, 0x06, 0x03, 0xda, 0x1f, 0x5c, 0xbc, - 0x1a, 0x0c, 0x2e, 0xfb, 0x2f, 0xfd, 0xab, 0xde, 0xcb, 0xab, 0x2e, 0xbd, 0xb8, 0x18, 0x5c, 0x5d, - 0x5e, 0x0d, 0xfc, 0x8b, 0xcb, 0xab, 0xc1, 0xcb, 0xab, 0xde, 0xf9, 0x79, 0x1b, 0x09, 0xc6, 0xbb, - 0x7d, 0xdc, 0xe9, 0xf9, 0x17, 0xf4, 0xe2, 0xaa, 0xdf, 0xbb, 0xec, 0x5d, 0x5d, 0x9d, 0x5f, 0x9d, - 0xbf, 0x7a, 0xf5, 0xaa, 0xfd, 0x3b, 0x12, 0x98, 0xf0, 0xeb, 0xbe, 0x3f, 0xf2, 0x03, 0xfa, 0xaa, - 0xff, 0xf2, 0xc2, 0xbf, 0xba, 0xf4, 0x2f, 0x2f, 0x7c, 0xff, 0xe5, 0xf9, 0xd5, 0xa0, 0x8d, 0x14, - 0xe3, 0xdd, 0x9e, 0x8f, 0xbb, 0xfd, 0xc1, 0x05, 0x7d, 0x79, 0x79, 0x75, 0x3e, 0xe8, 0xbd, 0xba, - 0xe8, 0xf5, 0xfd, 0x2b, 0xbf, 0xdf, 0xe9, 0xf5, 0x06, 0xf4, 0xf2, 0xe5, 0xd5, 0xd5, 0xc5, 0x85, - 0xdf, 0xf3, 0x2f, 0x2f, 0x7b, 0x17, 0x2f, 0xdb, 0xbf, 0x23, 0x85, 0xe1, 0x40, 0x84, 0x9d, 0x0f, - 0x7a, 0xf4, 0xea, 0xe5, 0xe5, 0x95, 0x3f, 0xb8, 0xbc, 0x7c, 0xe5, 0x0f, 0x2e, 0xaf, 0xce, 0x3b, - 0xb4, 0xd7, 0xbb, 0xe8, 0xfb, 0x97, 0x17, 0x83, 0xf3, 0x97, 0xaf, 0x2e, 0x7a, 0x97, 0x83, 0x36, - 0x9c, 0xe4, 0x76, 0x07, 0x03, 0xdc, 0xbd, 0xf0, 0x69, 0x7f, 0x70, 0x7e, 0x79, 0x79, 0xee, 0x5f, - 0x9d, 0x9f, 0xf7, 0x7b, 0x7d, 0x80, 0x03, 0xfb, 0x38, 0x3b, 0xef, 0x0f, 0xe8, 0xc5, 0xc5, 0xd5, - 0x45, 0xaf, 0x3f, 0x78, 0xd9, 0xeb, 0x5d, 0xbd, 0xbc, 0xe8, 0x50, 0xff, 0xe5, 0xd5, 0xc5, 0xf9, - 0xc5, 0xe0, 0x12, 0xea, 0x5f, 0xf6, 0xcf, 0x2f, 0xfa, 0x76, 0x6e, 0x03, 0x18, 0xe2, 0x2b, 0xea, - 0xbf, 0x1a, 0xf4, 0xaf, 0x2e, 0xcf, 0x07, 0xfe, 0xcb, 0xab, 0xc1, 0x4b, 0x3b, 0x35, 0xc3, 0xa2, - 0x86, 0xa9, 0x8d, 0xf0, 0x68, 0x30, 0xf1, 0x2f, 0x50, 0xdc, 0xe0, 0xe1, 0x5f, 0x90, 0xc2, 0x07, - 0x2c, 0xfc, 0x57, 0x2b, 0x89, 0x8f, 0x5a, 0x75, 0x86, 0x4a, 0x94, 0xe5, 0x5e, 0xc2, 0x59, 0x9f, - 0x9f, 0x93, 0x8c, 0x5d, 0xf0, 0x8b, 0x21, 0xbd, 0xb8, 0xce, 0xba, 0x7c, 0x68, 0xd7, 0x31, 0x61, - 0x3b, 0xeb, 0x8c, 0x24, 0xa3, 0x83, 0x36, 0xca, 0x3a, 0x60, 0x19, 0x25, 0x74, 0x7a, 0x96, 0x50, - 0xf5, 0x5f, 0x4c, 0x9d, 0x89, 0x51, 0xc6, 0x64, 0xc0, 0x99, 0xac, 0xfc, 0x24, 0x05, 0xd9, 0x17, - 0xf3, 0xb2, 0xd5, 0x5a, 0xa0, 0x86, 0x15, 0x68, 0xb4, 0x1d, 0x93, 0x07, 0x4a, 0x0f, 0x8a, 0xc9, - 0x78, 0x0b, 0x31, 0x83, 0xde, 0x32, 0xdd, 0x78, 0x64, 0xc1, 0x75, 0xd0, 0x10, 0xc5, 0x76, 0xdf, - 0xb7, 0x5a, 0xc0, 0x3e, 0xb1, 0x6a, 0x9a, 0x92, 0x4d, 0xa0, 0xe9, 0xa6, 0x28, 0x48, 0xda, 0x6c, - 0x56, 0x33, 0xa7, 0x6d, 0x07, 0x71, 0x48, 0x76, 0x7b, 0x91, 0x64, 0x5f, 0xf5, 0x28, 0xb5, 0xac, - 0xed, 0x32, 0x38, 0xed, 0x91, 0x0d, 0xfc, 0x93, 0xc2, 0x3f, 0x61, 0x70, 0xda, 0x2b, 0x2a, 0x7b, - 0x56, 0x59, 0xf7, 0x9c, 0x18, 0xab, 0x09, 0x83, 0x10, 0x8b, 0x53, 0x26, 0xc7, 0x6a, 0x32, 0x74, - 0xca, 0x8e, 0x26, 0x48, 0xd0, 0x65, 0x9e, 0x0b, 0x9a, 0xc2, 0x3f, 0x1b, 0xf8, 0x07, 0x7c, 0x88, - 0x3b, 0x1d, 0x59, 0x23, 0x56, 0x38, 0x2f, 0x75, 0xd9, 0xb2, 0x28, 0x48, 0x35, 0xf9, 0xf0, 0x60, - 0xf6, 0x0e, 0xa7, 0x3b, 0x9a, 0xd0, 0xc1, 0x54, 0xeb, 0x9d, 0xbb, 0x06, 0x96, 0xf1, 0x87, 0x60, - 0x59, 0x30, 0x74, 0xf9, 0x08, 0x1c, 0x40, 0x70, 0x51, 0xc1, 0x4a, 0x43, 0x9d, 0xa9, 0xd0, 0x58, - 0x8b, 0x8f, 0x83, 0x4c, 0x1f, 0x03, 0x99, 0x36, 0x41, 0x5a, 0x95, 0xe6, 0x71, 0x68, 0x9b, 0xc7, - 0xa0, 0x6d, 0x9a, 0xd0, 0xc2, 0x78, 0xbd, 0x0c, 0x9f, 0x80, 0x16, 0x3e, 0x02, 0xad, 0xc6, 0xee, - 0x32, 0xdd, 0x90, 0x6d, 0x18, 0xe8, 0x02, 0x57, 0xc0, 0x9d, 0x96, 0xf3, 0x00, 0xf4, 0x1d, 0x6e, - 0x43, 0xa5, 0x9e, 0xf5, 0xd0, 0x1a, 0x81, 0x0a, 0xb6, 0xcb, 0x54, 0xba, 0xee, 0x48, 0xf1, 0xd9, - 0xa3, 0x73, 0x50, 0x8b, 0x29, 0x55, 0x8f, 0x00, 0xae, 0x67, 0xa1, 0x16, 0x53, 0x90, 0x1c, 0xcd, - 0x59, 0x2c, 0x14, 0xe7, 0xf2, 0x49, 0xf0, 0x8b, 0xe7, 0x83, 0x5f, 0xec, 0x80, 0x9f, 0x3e, 0xb5, - 0x9c, 0x00, 0x7d, 0xfa, 0x7c, 0xe8, 0xd3, 0x1d, 0xe8, 0x60, 0x5f, 0x1e, 0x17, 0x0b, 0xb5, 0x46, - 0x86, 0x1c, 0x77, 0x10, 0xa3, 0xa7, 0x58, 0x1d, 0xc5, 0x4a, 0xb8, 0x5a, 0x3f, 0xfa, 0x1e, 0x04, - 0xe9, 0x22, 0xf8, 0x1e, 0xe4, 0xe7, 0x34, 0xf8, 0x1e, 0x81, 0x6f, 0xec, 0x09, 0xaa, 0xa8, 0x15, - 0x22, 0x30, 0x59, 0xb6, 0x61, 0x50, 0xc5, 0x5e, 0x6b, 0x1a, 0x8e, 0x7a, 0x81, 0xa6, 0xe1, 0xee, - 0x40, 0x9f, 0xc1, 0xc2, 0x66, 0x86, 0x61, 0x60, 0xd2, 0x86, 0x74, 0x8b, 0xc7, 0xe8, 0xa5, 0x29, - 0x20, 0xe2, 0xc7, 0xd1, 0xf0, 0x26, 0x8d, 0x77, 0xd0, 0xb0, 0xb4, 0xea, 0x80, 0x41, 0x43, 0x5c, - 0xcb, 0x4e, 0x83, 0x86, 0xd4, 0xa2, 0x21, 0x7e, 0x2e, 0x1a, 0x4a, 0xcd, 0xe3, 0x39, 0x68, 0x30, - 0xc6, 0xfc, 0x93, 0x68, 0x58, 0xa6, 0xf1, 0x33, 0xd1, 0x60, 0xec, 0x8d, 0x26, 0x92, 0xad, 0x55, - 0xf5, 0xd8, 0x56, 0xa1, 0x16, 0xe5, 0xba, 0x43, 0x7d, 0xf0, 0x5f, 0x50, 0xd5, 0xf1, 0xc8, 0x09, - 0x24, 0x16, 0x65, 0x62, 0xda, 0xf1, 0xb0, 0xf7, 0xc0, 0xce, 0x51, 0x9e, 0x14, 0x80, 0xd7, 0x73, - 0x8e, 0x90, 0x64, 0xbf, 0x51, 0x7e, 0xc7, 0x23, 0xf0, 0x11, 0x8d, 0x90, 0x60, 0x7f, 0x45, 0x10, - 0xae, 0x64, 0xf7, 0x60, 0x65, 0xbe, 0xfa, 0xee, 0x8b, 0x9b, 0xaf, 0x73, 0xfb, 0x65, 0x74, 0x8a, - 0x37, 0x55, 0x4b, 0x13, 0x0a, 0xf8, 0xcc, 0xa6, 0x24, 0x33, 0x5f, 0x17, 0x13, 0xd2, 0xc3, 0x98, - 0x9c, 0xca, 0x87, 0xad, 0x44, 0xb5, 0x98, 0x9e, 0x38, 0x73, 0x17, 0x0f, 0x2b, 0xba, 0xd9, 0xaa, - 0x40, 0x90, 0x45, 0xa0, 0xc8, 0x34, 0xe0, 0x24, 0x0c, 0xb2, 0x62, 0x87, 0x4a, 0x9f, 0x85, 0xc1, - 0xb0, 0x81, 0xc2, 0xf0, 0x61, 0x1c, 0xda, 0x44, 0x78, 0x1c, 0x99, 0xfb, 0xc6, 0x72, 0x4d, 0x24, - 0xa5, 0x89, 0xfd, 0xcc, 0x65, 0xfc, 0xc2, 0xeb, 0xfc, 0x1d, 0x69, 0xaa, 0xb0, 0xf9, 0x59, 0xd8, - 0x9f, 0x63, 0x92, 0x76, 0x77, 0xf9, 0xfa, 0x83, 0x81, 0x5b, 0xc0, 0x6f, 0x76, 0x16, 0xb0, 0xf7, - 0xb2, 0xfd, 0xdf, 0x66, 0x21, 0x60, 0x11, 0xdc, 0x47, 0x7f, 0x02, 0x6b, 0xe0, 0x3e, 0xce, 0x27, - 0x76, 0xf5, 0xbe, 0xfb, 0xd3, 0xcd, 0x80, 0x68, 0xec, 0xc7, 0x85, 0x83, 0xf1, 0xc3, 0x0e, 0x8c, - 0x1a, 0x40, 0xdd, 0xba, 0xd9, 0xe3, 0xd7, 0xbb, 0xf4, 0xf2, 0x48, 0x75, 0x92, 0xb1, 0xb2, 0x9b, - 0x47, 0x29, 0x64, 0xc9, 0xef, 0x9e, 0x41, 0x21, 0x60, 0xc8, 0x15, 0xcd, 0xf5, 0x79, 0xf5, 0xe7, - 0xa8, 0xe4, 0x81, 0x15, 0xea, 0xfc, 0x1d, 0xfd, 0x62, 0xec, 0x4c, 0x4d, 0x43, 0xfc, 0x20, 0x8b, - 0xd7, 0x0e, 0x97, 0xa6, 0x18, 0x79, 0x7a, 0x00, 0xcb, 0xb4, 0x94, 0x6c, 0x50, 0xdf, 0x10, 0xe9, - 0xb2, 0x24, 0xc9, 0xb4, 0xe3, 0xbd, 0xb0, 0xa9, 0xb8, 0xe3, 0xbd, 0x78, 0x3e, 0xab, 0xff, 0x78, - 0x8c, 0xd5, 0xcf, 0x2f, 0xfd, 0x06, 0xbf, 0x1a, 0xe3, 0xa8, 0xe2, 0x57, 0xf8, 0x32, 0x4b, 0xf7, - 0xe5, 0x51, 0x56, 0x7f, 0xaa, 0xe9, 0xf3, 0x59, 0x7d, 0x99, 0xc6, 0x7b, 0x0b, 0x09, 0xb2, 0x71, - 0xbb, 0x0c, 0x04, 0x49, 0x03, 0x45, 0xe2, 0x7d, 0x56, 0x07, 0x49, 0xfc, 0x2c, 0x1c, 0x86, 0x0d, - 0x24, 0x86, 0x8f, 0x61, 0xf1, 0x69, 0x66, 0x6f, 0x78, 0xbd, 0x8a, 0x62, 0x82, 0x49, 0x5c, 0x20, - 0x5c, 0xfb, 0x42, 0xff, 0xd9, 0x40, 0x3b, 0xd3, 0xf4, 0x56, 0xcc, 0xf4, 0xd2, 0x6c, 0x50, 0x69, - 0x2c, 0x66, 0x5c, 0x7d, 0x10, 0x7f, 0x70, 0xb0, 0x1d, 0xe9, 0x34, 0x51, 0x33, 0xae, 0xfe, 0x61, - 0x8a, 0x21, 0xb0, 0x75, 0x19, 0xca, 0x59, 0xcc, 0x7f, 0x0a, 0x67, 0x22, 0x4b, 0x49, 0x62, 0x2e, - 0x7c, 0xcd, 0x66, 0x70, 0xbe, 0x10, 0xd7, 0x6d, 0x97, 0xe1, 0x9a, 0x93, 0x94, 0x79, 0xcb, 0x44, - 0x89, 0x3f, 0x12, 0xa9, 0xc3, 0xd8, 0x33, 0x3b, 0x54, 0x1c, 0xde, 0x27, 0x99, 0xfe, 0x46, 0x28, - 0x6e, 0xc6, 0x50, 0xdb, 0xa4, 0xee, 0x54, 0x52, 0x32, 0x85, 0xc1, 0x56, 0x6e, 0x27, 0x9d, 0x7e, - 0x3b, 0x23, 0x5e, 0x24, 0x54, 0x64, 0xe3, 0x6a, 0xe3, 0xd1, 0xd6, 0x76, 0x6c, 0x5c, 0xa0, 0x41, - 0xd5, 0x6b, 0x67, 0x6f, 0x40, 0xe5, 0x87, 0x5c, 0xf0, 0x40, 0x74, 0xfb, 0xed, 0xa4, 0x0b, 0x80, - 0xcc, 0xe4, 0x02, 0x41, 0x96, 0x5c, 0x2c, 0x96, 0x3a, 0x10, 0x24, 0xba, 0x0b, 0xc4, 0x59, 0x9f, - 0x44, 0xf7, 0xe6, 0x47, 0x99, 0xb6, 0x90, 0xec, 0xf2, 0xb3, 0x7e, 0x11, 0xec, 0x74, 0xa5, 0xce, - 0xfa, 0x7b, 0x50, 0x55, 0xd9, 0x00, 0x8a, 0xee, 0x02, 0x9f, 0xdc, 0x07, 0xbe, 0xeb, 0x22, 0x1d, - 0xa9, 0xba, 0x9b, 0x74, 0x24, 0x02, 0xd5, 0x38, 0xf4, 0xfb, 0x57, 0xd3, 0x95, 0x0c, 0xe8, 0x27, - 0x8a, 0x09, 0x87, 0x78, 0xb8, 0x94, 0x61, 0x9b, 0x91, 0x0c, 0x92, 0x75, 0x87, 0x24, 0xa9, 0xbe, - 0xcd, 0x80, 0xe0, 0xe4, 0xe1, 0x09, 0xbc, 0x92, 0x94, 0xc5, 0x23, 0x75, 0xd6, 0x0f, 0x38, 0xcc, - 0x91, 0x25, 0x9d, 0x63, 0x47, 0x71, 0xd2, 0xb8, 0xeb, 0xc0, 0x19, 0x61, 0x84, 0xbb, 0xf3, 0xfb, - 0x94, 0x4b, 0x68, 0x02, 0x21, 0x8d, 0x0b, 0xc8, 0xa8, 0xc3, 0x41, 0xb9, 0x52, 0xe0, 0x79, 0xa2, - 0x83, 0x81, 0xf1, 0xe8, 0x38, 0x5d, 0xb6, 0x2e, 0x5b, 0x34, 0xca, 0x8c, 0x22, 0x5a, 0x17, 0x4d, - 0x1b, 0x45, 0xd6, 0x4a, 0x28, 0xcb, 0xc0, 0xcb, 0x21, 0x68, 0x68, 0x8b, 0x9c, 0x8e, 0x1f, 0xd8, - 0xeb, 0x6c, 0x1a, 0x9c, 0x56, 0x1f, 0xf9, 0x6a, 0xcd, 0x15, 0x58, 0x3e, 0xdc, 0xd0, 0xdf, 0x2a, - 0xbc, 0x6b, 0x64, 0x19, 0x3f, 0x1e, 0x92, 0x4e, 0x95, 0xef, 0x72, 0x7c, 0x96, 0xb5, 0x1b, 0xde, - 0x8e, 0xca, 0x17, 0xe6, 0x93, 0xca, 0x09, 0x96, 0x58, 0x29, 0x61, 0x3b, 0x5c, 0x36, 0x46, 0x29, - 0xe8, 0xf2, 0x8c, 0x9d, 0xd3, 0x4b, 0x5b, 0xd2, 0x30, 0xb6, 0xea, 0x0a, 0xa9, 0x2d, 0xb3, 0x56, - 0x53, 0xe0, 0xee, 0xf9, 0xd5, 0xc5, 0x9b, 0xa2, 0x30, 0x28, 0x36, 0xbe, 0xff, 0xac, 0x1c, 0x44, - 0xdc, 0x6a, 0xa1, 0x88, 0x75, 0x7b, 0xed, 0xa8, 0x93, 0x75, 0xfa, 0xed, 0x04, 0x93, 0xed, 0x5d, - 0x10, 0x8f, 0xd2, 0x20, 0x22, 0xf7, 0x41, 0x3c, 0x8a, 0x82, 0xb4, 0xb0, 0x4e, 0x75, 0x4d, 0xa4, - 0x66, 0xfd, 0xb6, 0x19, 0xe9, 0x8f, 0x6f, 0x89, 0xd0, 0xec, 0xd8, 0x95, 0x28, 0xa4, 0x5f, 0xc8, - 0x8e, 0xc4, 0x2f, 0x64, 0x41, 0xd4, 0xf1, 0x1a, 0x76, 0xda, 0xe9, 0xef, 0x4a, 0x23, 0xdd, 0xd6, - 0x1d, 0xd9, 0x96, 0xb8, 0xa8, 0x19, 0xdf, 0x38, 0xfd, 0xeb, 0x33, 0x06, 0x43, 0x7f, 0x67, 0xfd, - 0x6e, 0xc5, 0x52, 0xdd, 0x5d, 0x96, 0xea, 0xee, 0x88, 0x80, 0xc6, 0x85, 0x2e, 0xdd, 0xf4, 0xbc, - 0x39, 0x28, 0xa5, 0x6e, 0x6b, 0xb9, 0xa1, 0x92, 0x2a, 0x96, 0x5d, 0xe4, 0x2e, 0x28, 0x60, 0x42, - 0x09, 0x2c, 0x28, 0x1b, 0x3c, 0x92, 0xe8, 0x1d, 0x8f, 0x34, 0x40, 0x5e, 0x72, 0x1e, 0x7f, 0x25, - 0x17, 0xb1, 0x15, 0x47, 0xe6, 0xf3, 0x40, 0x82, 0x40, 0xd4, 0x76, 0x14, 0x27, 0xd1, 0xcd, 0xad, - 0x48, 0x8d, 0xbc, 0xe0, 0x23, 0xc9, 0x54, 0xc7, 0x44, 0xf3, 0xef, 0xe5, 0x9e, 0x5f, 0xfa, 0x5d, - 0x28, 0x81, 0x26, 0xa1, 0xd4, 0xe2, 0x48, 0xb3, 0xde, 0x2b, 0xbf, 0x2b, 0x83, 0x23, 0xa5, 0x10, - 0x04, 0xc5, 0xc0, 0xb7, 0x49, 0x84, 0x46, 0xd2, 0x6c, 0x27, 0xf5, 0xd0, 0xe3, 0xbd, 0xa1, 0x1b, - 0x04, 0x81, 0xe3, 0x91, 0x46, 0x77, 0x24, 0x83, 0x9f, 0x7b, 0xf0, 0xbc, 0x9a, 0x63, 0x22, 0x70, - 0x5c, 0x81, 0xdc, 0xcd, 0xba, 0xc2, 0x1c, 0x3e, 0xc6, 0xcc, 0x4c, 0xdc, 0xac, 0x5b, 0xa8, 0x43, - 0xd9, 0x47, 0x5d, 0x41, 0xc0, 0x73, 0x89, 0xce, 0x2f, 0xfd, 0x33, 0xa9, 0x31, 0x38, 0xa6, 0x2b, - 0x0a, 0x56, 0xda, 0xc4, 0x65, 0x93, 0xa4, 0xe1, 0x34, 0xac, 0xcf, 0xbe, 0x50, 0x0c, 0x46, 0x45, - 0xe3, 0xbb, 0xe7, 0xfb, 0x67, 0x49, 0x3b, 0x6d, 0xc6, 0x1f, 0xa4, 0x87, 0x8b, 0x67, 0x76, 0x81, - 0x69, 0x72, 0xf7, 0xc6, 0x48, 0xa1, 0xdd, 0x85, 0x94, 0xa5, 0x48, 0x73, 0x37, 0x0f, 0x47, 0x22, - 0x90, 0xe5, 0xaa, 0x3e, 0x24, 0x8a, 0x1b, 0xbd, 0x45, 0x7b, 0x98, 0x49, 0x2b, 0xcc, 0xdc, 0xba, - 0x6d, 0x45, 0x95, 0xc2, 0x2f, 0x61, 0x8a, 0x5a, 0xc0, 0xc4, 0x78, 0x8b, 0x13, 0x7c, 0x86, 0x38, - 0xc8, 0x71, 0x0c, 0x6c, 0x4d, 0x52, 0xf0, 0x3d, 0x43, 0x5e, 0x56, 0xe5, 0x95, 0x23, 0x75, 0x53, - 0xde, 0x63, 0xf6, 0xd8, 0x32, 0x3b, 0xd9, 0x1c, 0x2d, 0xed, 0xf9, 0x7e, 0x37, 0xb5, 0x35, 0x1a, - 0xc3, 0x0d, 0x75, 0x7d, 0xaf, 0xb6, 0x8a, 0xa2, 0x60, 0xfe, 0x90, 0xd7, 0x11, 0x2c, 0xbc, 0x0c, - 0xb6, 0xc8, 0x4c, 0x9c, 0x04, 0xbd, 0xeb, 0x4a, 0x18, 0x3a, 0x24, 0xef, 0xbb, 0xe6, 0xf6, 0x67, - 0xcd, 0x82, 0x59, 0x3b, 0xeb, 0x24, 0xed, 0x04, 0x5f, 0xef, 0xe2, 0xa7, 0x8c, 0x13, 0xe4, 0xcd, - 0x30, 0xbd, 0xc6, 0xbd, 0x99, 0x06, 0x97, 0x6e, 0xa7, 0xc9, 0xdd, 0x07, 0xf1, 0x87, 0x90, 0x8b, - 0xc0, 0xb3, 0x0c, 0xd4, 0x9d, 0x26, 0x77, 0x1e, 0xb1, 0xe9, 0x60, 0x87, 0xab, 0xe0, 0x7e, 0xcc, - 0x49, 0x9a, 0x80, 0x8e, 0x62, 0xac, 0x02, 0x53, 0xf2, 0x1a, 0x8e, 0xaf, 0x1a, 0x33, 0x5c, 0xea, - 0xfd, 0xa0, 0x9a, 0x8e, 0xd7, 0x5d, 0x00, 0xde, 0x21, 0x8a, 0xd0, 0xeb, 0x48, 0xab, 0x72, 0x08, - 0xba, 0x0a, 0xd7, 0xe8, 0x88, 0x2f, 0x6f, 0xec, 0xd7, 0xd7, 0xc0, 0xc7, 0xbd, 0x49, 0xc7, 0x3b, - 0x31, 0x6d, 0x5e, 0x78, 0x05, 0xa6, 0x9f, 0x13, 0x21, 0x91, 0x47, 0x3c, 0x6c, 0x34, 0x93, 0xfa, - 0xe6, 0x40, 0x63, 0x3e, 0x87, 0x67, 0x82, 0x23, 0x1d, 0x68, 0x73, 0xb3, 0xc7, 0x08, 0xc2, 0x99, - 0x66, 0x63, 0x6f, 0x95, 0x64, 0xa9, 0xb9, 0x9e, 0xe0, 0x11, 0x4f, 0x27, 0x59, 0xb4, 0x74, 0x69, - 0x93, 0x9f, 0xad, 0xcb, 0x5c, 0x2e, 0x67, 0xde, 0x84, 0x2c, 0x1a, 0x82, 0x50, 0x36, 0x4e, 0x42, - 0x4d, 0xa7, 0xd2, 0x45, 0x29, 0x82, 0xd3, 0xaf, 0x0a, 0xd1, 0x10, 0x33, 0x66, 0xd7, 0x48, 0x85, - 0x72, 0x96, 0xac, 0x10, 0xdc, 0x1f, 0xae, 0xcf, 0x5b, 0xcf, 0x2f, 0x31, 0x84, 0xd8, 0xdb, 0x71, - 0xa2, 0x41, 0x1d, 0x7a, 0x66, 0x22, 0xdb, 0x7e, 0xfb, 0xcd, 0x38, 0x50, 0x7f, 0xfb, 0x8d, 0x49, - 0x4c, 0x50, 0xd3, 0x9f, 0x5a, 0xc6, 0xf2, 0xd8, 0xb0, 0x4c, 0x64, 0x2e, 0xc0, 0x57, 0x85, 0x18, - 0xef, 0x44, 0xf5, 0x6b, 0x7c, 0x18, 0x17, 0xf2, 0x80, 0xdf, 0xd4, 0xd2, 0x8d, 0xb9, 0x07, 0x63, - 0xe3, 0x3f, 0xcc, 0x89, 0x19, 0x11, 0x6c, 0x9b, 0xc8, 0x77, 0x80, 0x8f, 0x6f, 0x92, 0x5b, 0x19, - 0x48, 0x92, 0x48, 0x83, 0x93, 0xd4, 0x28, 0x2e, 0xb0, 0x3f, 0x3c, 0xad, 0x2a, 0x94, 0xe1, 0x7f, - 0x66, 0x67, 0x55, 0x0b, 0x21, 0x47, 0xa5, 0x0a, 0xf0, 0xce, 0x7c, 0x06, 0x65, 0x3e, 0xc9, 0xd8, - 0x36, 0xd9, 0x70, 0x35, 0x8f, 0x93, 0xdb, 0xc0, 0xdb, 0x88, 0x54, 0x4c, 0x63, 0xee, 0x91, 0x99, - 0x48, 0xd7, 0x71, 0x78, 0x1f, 0xa8, 0x91, 0x27, 0x64, 0x2c, 0x24, 0xef, 0x4e, 0x41, 0x64, 0x7a, - 0xe0, 0x8a, 0x82, 0xdf, 0xea, 0xf6, 0xb8, 0x5f, 0x1e, 0x9d, 0x9b, 0x88, 0x53, 0x35, 0xf2, 0x2c, - 0xd8, 0x1f, 0xf8, 0x5c, 0x7b, 0x81, 0xfb, 0xf8, 0x98, 0xac, 0xbd, 0x09, 0xe3, 0x98, 0x2c, 0xd1, - 0x7b, 0x1b, 0xee, 0x56, 0x5f, 0x24, 0x47, 0xe5, 0xba, 0x11, 0x41, 0x32, 0x7b, 0x0a, 0xd9, 0x0c, - 0x66, 0xaa, 0x10, 0xf4, 0x00, 0x0e, 0x89, 0x0b, 0x3e, 0xb2, 0xc1, 0x96, 0x89, 0x7c, 0x2b, 0xd7, - 0x99, 0x06, 0x7d, 0x17, 0x32, 0x21, 0x74, 0x0d, 0xa2, 0x51, 0xbe, 0x06, 0x79, 0x29, 0xe4, 0xe2, - 0x75, 0x0c, 0x8c, 0xf0, 0x13, 0x8f, 0x34, 0xc2, 0x43, 0xe8, 0xc7, 0x5c, 0x69, 0xf9, 0xc6, 0x6e, - 0xf7, 0x08, 0x0f, 0x4b, 0xf5, 0xc4, 0x52, 0x60, 0x3a, 0x82, 0x51, 0x82, 0xae, 0x36, 0xfb, 0x68, - 0x33, 0xe0, 0x9a, 0x2e, 0x28, 0x72, 0x9c, 0x46, 0x06, 0xd2, 0x3f, 0xbb, 0x20, 0x39, 0xe6, 0x20, - 0xde, 0xca, 0xac, 0x7f, 0x75, 0x15, 0xd5, 0xc9, 0xba, 0xd6, 0xbb, 0x74, 0xad, 0x71, 0x19, 0x12, - 0x9f, 0x25, 0xb7, 0xd2, 0x0b, 0xcc, 0x77, 0xbd, 0xa8, 0x5e, 0x70, 0xda, 0x83, 0x68, 0x5c, 0x73, - 0xdb, 0x0b, 0x2e, 0x6f, 0xcf, 0x34, 0x44, 0x29, 0x7d, 0x1b, 0x46, 0xcb, 0x1d, 0x3e, 0xad, 0xe2, - 0x83, 0x0f, 0x6e, 0x5c, 0x01, 0xdf, 0x6f, 0xd7, 0x10, 0x6b, 0xb6, 0xe1, 0xe0, 0x57, 0xc7, 0x45, - 0xf3, 0xf4, 0xae, 0xc1, 0x75, 0x8d, 0xae, 0xed, 0xb7, 0xed, 0xb4, 0x77, 0x58, 0x3d, 0x5b, 0x37, - 0x2b, 0x03, 0x43, 0xba, 0xba, 0x7d, 0x4c, 0x9e, 0x1a, 0xdf, 0xb1, 0x1b, 0x5e, 0x47, 0x86, 0x08, - 0xc7, 0xd7, 0x05, 0x7a, 0xdb, 0x30, 0x5f, 0xa6, 0x3b, 0x3b, 0x98, 0xf5, 0x33, 0x66, 0x2a, 0x06, - 0x7d, 0x16, 0x68, 0xba, 0xa4, 0xba, 0x25, 0x32, 0x11, 0xe4, 0x64, 0x5b, 0xdd, 0xe4, 0x0b, 0xbc, - 0xb7, 0x2a, 0x79, 0x63, 0xe8, 0xe5, 0xa4, 0x4a, 0x75, 0xbb, 0x20, 0x2c, 0x0d, 0x79, 0x1a, 0x61, - 0x06, 0x11, 0xc6, 0xe9, 0x57, 0x91, 0x16, 0x1b, 0x3e, 0xf2, 0x1a, 0xb5, 0xca, 0x4c, 0x2f, 0xf0, - 0x3c, 0x4c, 0xcc, 0x1d, 0xbf, 0x60, 0xeb, 0x75, 0x6f, 0xf9, 0xf4, 0x46, 0xe8, 0xae, 0x0e, 0xd7, - 0xdd, 0xa5, 0x58, 0x2c, 0x63, 0xd8, 0xca, 0xba, 0x26, 0x66, 0xc0, 0xb3, 0x5e, 0x1e, 0xe4, 0x93, - 0x13, 0xf7, 0x3f, 0x1e, 0x7a, 0x44, 0xab, 0x50, 0xa6, 0x70, 0x49, 0x2d, 0xf0, 0x4c, 0x32, 0x06, - 0x61, 0xe1, 0x75, 0x40, 0x46, 0xd2, 0x3b, 0x6c, 0x85, 0xaf, 0xf9, 0xb8, 0x37, 0x52, 0x94, 0xdc, - 0x8a, 0x38, 0xb6, 0x47, 0x17, 0xae, 0x81, 0xb9, 0xe0, 0x46, 0x74, 0xb2, 0x0e, 0x36, 0x1a, 0x81, - 0x3e, 0x02, 0xd4, 0x55, 0xa6, 0xed, 0x9e, 0xbd, 0xd1, 0xa8, 0xdf, 0x96, 0xb8, 0xdc, 0xb9, 0xcb, - 0xcf, 0x75, 0x92, 0x0a, 0x40, 0x60, 0xe0, 0x85, 0xd3, 0x34, 0x89, 0x33, 0xcd, 0x3d, 0x72, 0xc8, - 0xd6, 0x45, 0x01, 0xc7, 0x42, 0x4b, 0x04, 0xaf, 0x8f, 0x78, 0x64, 0x27, 0x40, 0x11, 0x6d, 0xcd, - 0x0d, 0xb3, 0x37, 0xf0, 0xaa, 0xc4, 0x8e, 0xc9, 0xa9, 0x99, 0xd6, 0x79, 0x5e, 0xad, 0xec, 0x82, - 0x6b, 0x17, 0x96, 0x9e, 0x7e, 0x7d, 0xff, 0xd1, 0xde, 0xcf, 0x43, 0x1e, 0x70, 0x9a, 0x87, 0xdd, - 0x1d, 0xd3, 0x5b, 0x21, 0x67, 0xc9, 0x2d, 0x95, 0xe1, 0x46, 0x2c, 0x42, 0x08, 0x08, 0xcb, 0x52, - 0xae, 0xbe, 0x5a, 0xc0, 0x8d, 0x7b, 0xc1, 0xce, 0x7e, 0x45, 0x68, 0x74, 0x1a, 0x2d, 0x55, 0xb2, - 0xe2, 0x79, 0x28, 0x67, 0x2a, 0x11, 0x33, 0x4c, 0x71, 0x3b, 0x0d, 0xe7, 0xa1, 0x12, 0x67, 0xa2, - 0xbc, 0x12, 0x0a, 0x8f, 0x9f, 0x88, 0x1f, 0x97, 0x89, 0xe4, 0xb9, 0xf8, 0x31, 0x99, 0xe5, 0xe2, - 0xc7, 0x70, 0xd6, 0x28, 0xe5, 0x65, 0x2f, 0x10, 0xdc, 0xdf, 0x50, 0x19, 0x91, 0xc8, 0x73, 0x85, - 0x5b, 0x2d, 0xff, 0x5a, 0x97, 0xf7, 0x76, 0x47, 0x2e, 0xd6, 0x2e, 0x4a, 0xe2, 0x8e, 0x77, 0x76, - 0xe6, 0x75, 0x38, 0x5d, 0x26, 0xa9, 0xee, 0x70, 0xba, 0x0e, 0xf5, 0x52, 0x86, 0x2b, 0xde, 0x81, - 0xf0, 0xc6, 0x50, 0x45, 0xcb, 0x8e, 0x0e, 0x20, 0x92, 0xb9, 0x94, 0x42, 0x10, 0x79, 0x48, 0x4e, - 0x2d, 0xc6, 0x9c, 0xcd, 0x4a, 0xb6, 0xd1, 0x5d, 0xa0, 0x40, 0xbd, 0xe5, 0x44, 0x05, 0x92, 0xcc, - 0x45, 0x1c, 0x07, 0x9e, 0x4c, 0x24, 0xec, 0x61, 0xa9, 0x56, 0xc9, 0x0d, 0xef, 0x9a, 0x85, 0xf2, - 0x82, 0x3e, 0xb1, 0xdf, 0x81, 0xf7, 0x85, 0xef, 0xfb, 0x5e, 0xf1, 0x04, 0xa8, 0x6e, 0xdf, 0x02, - 0xd3, 0x14, 0x7e, 0x1e, 0x01, 0x36, 0x9f, 0xcf, 0xbd, 0xa2, 0x79, 0x7b, 0x6f, 0xad, 0x11, 0x2f, - 0xfd, 0x0d, 0x9c, 0x86, 0x86, 0x92, 0xdf, 0x02, 0xcd, 0x93, 0x8c, 0x55, 0xb1, 0xdd, 0x10, 0x1c, - 0x74, 0xcd, 0xa9, 0xa1, 0xde, 0xb4, 0xc6, 0x8c, 0xfd, 0x1e, 0xeb, 0x49, 0xe0, 0xd2, 0x44, 0xb2, - 0x7f, 0xc2, 0x0b, 0x20, 0x60, 0x40, 0x5a, 0x35, 0x0e, 0x1e, 0x5c, 0x70, 0x6a, 0x1c, 0xbc, 0xba, - 0xe0, 0xd4, 0xb8, 0x94, 0xfd, 0x0b, 0x71, 0x92, 0x41, 0x24, 0xc5, 0x83, 0x66, 0xe8, 0x9f, 0xb3, - 0x42, 0xc7, 0x63, 0x9f, 0x18, 0x67, 0xb2, 0x4f, 0xbc, 0x8e, 0x32, 0x1e, 0x50, 0xf8, 0x35, 0x4e, - 0xe4, 0x09, 0x19, 0x83, 0x9e, 0x68, 0x8a, 0xe1, 0x80, 0xfb, 0xb0, 0xc2, 0xe4, 0x88, 0xed, 0x5a, - 0x41, 0x84, 0x6a, 0xe0, 0x5a, 0xf5, 0x8f, 0x43, 0x2c, 0x8b, 0x4b, 0xc8, 0x3b, 0x10, 0x9b, 0x16, - 0xef, 0x01, 0xc0, 0x72, 0x1c, 0xfe, 0x71, 0x80, 0x65, 0x31, 0xf8, 0x9b, 0x2b, 0x80, 0x3b, 0x76, - 0x72, 0x09, 0x31, 0x3c, 0x68, 0xe3, 0x06, 0xf2, 0x14, 0xe8, 0x83, 0xf1, 0x96, 0xb6, 0x76, 0xad, - 0xe2, 0x8e, 0x27, 0xd6, 0xc2, 0xde, 0x35, 0xba, 0x93, 0x03, 0xa3, 0x9b, 0xc4, 0x2c, 0xe9, 0x66, - 0x24, 0x65, 0x19, 0x04, 0x8f, 0x0c, 0xd3, 0xeb, 0x64, 0x98, 0x76, 0x58, 0x7c, 0xf6, 0x8a, 0x44, - 0x1d, 0xd6, 0x73, 0x97, 0x3a, 0xd9, 0xcf, 0x3b, 0xe7, 0x6b, 0x29, 0x26, 0x73, 0x16, 0x52, 0xb8, - 0x80, 0x18, 0xd2, 0x05, 0xd9, 0xb0, 0x90, 0x4e, 0x87, 0xdc, 0xc6, 0xcd, 0x8e, 0x7b, 0x7d, 0x3a, - 0x68, 0x47, 0xe5, 0xb8, 0xe7, 0x66, 0xb4, 0x4b, 0xf3, 0xef, 0xc6, 0x8c, 0xb8, 0x8e, 0xe5, 0x3c, - 0xb0, 0xda, 0x0d, 0x5e, 0xbe, 0x98, 0xfb, 0xbe, 0x99, 0xfc, 0x25, 0xbd, 0xbc, 0xbc, 0x84, 0xef, - 0xb9, 0xf9, 0x3e, 0x3f, 0xa7, 0xe7, 0xe7, 0xe7, 0xc4, 0xfb, 0xc2, 0xb7, 0xdf, 0x03, 0xdf, 0xa4, - 0xe7, 0x90, 0xbe, 0x2c, 0xeb, 0xfa, 0xbe, 0xf9, 0x7e, 0x55, 0xd6, 0x9d, 0xdb, 0x6f, 0x83, 0x48, - 0x0b, 0x78, 0x72, 0xe8, 0x11, 0x30, 0x6a, 0x2a, 0xfb, 0xb9, 0x3e, 0xee, 0x01, 0xd7, 0x9f, 0x39, - 0x0a, 0x87, 0x38, 0x3b, 0xf0, 0x04, 0x60, 0xb2, 0x38, 0x5a, 0x0e, 0x70, 0x5d, 0x8d, 0x61, 0x63, - 0x0a, 0xd6, 0x67, 0x3a, 0xa3, 0x76, 0xda, 0x33, 0xeb, 0xec, 0x83, 0x84, 0xf5, 0x98, 0x96, 0x03, - 0xb2, 0xd5, 0x16, 0xae, 0xda, 0xa2, 0xac, 0xb6, 0x28, 0xab, 0x4d, 0x8e, 0x3a, 0x28, 0x60, 0xb4, - 0xd3, 0xa3, 0xa3, 0x11, 0xe6, 0xe0, 0xbe, 0xe7, 0xfb, 0xbb, 0xa3, 0x31, 0x82, 0x68, 0xb7, 0xcf, - 0xa9, 0xeb, 0x73, 0x5a, 0xf6, 0x39, 0xad, 0xfa, 0x2c, 0x0a, 0xc3, 0xe1, 0xf5, 0x9e, 0xbb, 0xd0, - 0xfb, 0x7b, 0x46, 0x41, 0x38, 0xd9, 0x3a, 0xad, 0x2b, 0x38, 0x1a, 0x7c, 0x76, 0x3c, 0x24, 0x8d, - 0x70, 0xeb, 0x29, 0x03, 0x5d, 0x6a, 0xd7, 0x29, 0xc6, 0x9b, 0x4e, 0xb1, 0xe1, 0xd3, 0x9a, 0xee, - 0xa8, 0xdb, 0x6b, 0x8b, 0x4e, 0xd6, 0x49, 0x02, 0xd9, 0x4d, 0x88, 0xaa, 0xc3, 0xa4, 0x6a, 0xb3, - 0x1a, 0xa4, 0x94, 0x8f, 0x9d, 0x41, 0xbe, 0x67, 0x40, 0x67, 0x6d, 0x85, 0x1f, 0x11, 0x4f, 0x4d, - 0xc7, 0x55, 0x7a, 0xc0, 0x43, 0x25, 0x66, 0xd2, 0x4e, 0x6c, 0x5c, 0x43, 0xe8, 0xc0, 0x8d, 0x95, - 0xe2, 0x63, 0xbe, 0x31, 0x53, 0xfb, 0xd0, 0x51, 0x75, 0x4e, 0x2f, 0xdb, 0xf1, 0xb0, 0x16, 0x8b, - 0x0d, 0xf1, 0x73, 0xc4, 0x2f, 0x07, 0x8e, 0xb7, 0x76, 0x3c, 0xdc, 0x73, 0x56, 0xc5, 0x66, 0xd1, - 0x40, 0x10, 0x03, 0x17, 0x9a, 0x17, 0x4b, 0xa8, 0x80, 0xd5, 0xb1, 0x0a, 0x0e, 0x44, 0xb0, 0x67, - 0x63, 0xde, 0x98, 0xe8, 0x84, 0x29, 0xc2, 0x4b, 0xc5, 0x19, 0x9e, 0xbd, 0xa1, 0x62, 0x86, 0x8b, - 0x02, 0x1f, 0xc4, 0x98, 0xd4, 0x9a, 0xd7, 0x4c, 0x6c, 0xbc, 0x43, 0x42, 0x90, 0xfb, 0xca, 0xd8, - 0x07, 0xd3, 0x87, 0xe7, 0xd4, 0xa9, 0x83, 0xfa, 0xdb, 0x5a, 0x65, 0x51, 0x3c, 0x0e, 0x8d, 0xfa, - 0x55, 0xeb, 0x38, 0xaa, 0xa9, 0xe1, 0x24, 0xd8, 0xd9, 0xc4, 0xd6, 0xc4, 0x86, 0xac, 0x18, 0x93, - 0x69, 0x18, 0xdd, 0x2c, 0xcc, 0x4a, 0x06, 0x5e, 0x94, 0x48, 0x11, 0xd5, 0xa6, 0xee, 0x17, 0x51, - 0x14, 0x9d, 0xf4, 0x07, 0x2f, 0xc8, 0x09, 0xec, 0x96, 0x27, 0xfe, 0xc9, 0xc0, 0x87, 0x34, 0xe4, - 0xfa, 0x27, 0x2f, 0xeb, 0x7c, 0xec, 0x35, 0xa0, 0x80, 0x6b, 0x3c, 0xf0, 0x5e, 0xad, 0xef, 0x4e, - 0x5e, 0x81, 0xc5, 0x0a, 0x81, 0x24, 0x60, 0xb1, 0xd8, 0xe9, 0x1e, 0x9d, 0xdb, 0xf7, 0xae, 0xbf, - 0xe7, 0xcc, 0xb1, 0x56, 0xcb, 0x40, 0xbd, 0xf3, 0xad, 0x66, 0x57, 0xfa, 0x97, 0xbd, 0x9e, 0xef, - 0xbf, 0xf0, 0xca, 0x19, 0xbb, 0xaf, 0xc7, 0xa7, 0xbc, 0xd4, 0xc8, 0x03, 0xbb, 0x2c, 0x54, 0x1e, - 0xd9, 0xe3, 0x11, 0x7e, 0xc0, 0x23, 0x9e, 0x4e, 0x4e, 0x74, 0xb2, 0xf6, 0x02, 0x48, 0x28, 0xe8, - 0xc4, 0x23, 0x11, 0x2e, 0xc8, 0x1c, 0x34, 0x07, 0x3b, 0xcd, 0xa9, 0x26, 0xdb, 0x52, 0x0d, 0x0e, - 0x4e, 0x7d, 0x62, 0x94, 0xe6, 0xc0, 0xdd, 0x20, 0x24, 0x2a, 0xe0, 0xbb, 0x0e, 0xf9, 0x4c, 0xc5, - 0x55, 0xd6, 0x87, 0xcd, 0xc2, 0x3d, 0x4d, 0x56, 0xe6, 0x98, 0x5b, 0xd1, 0xe4, 0x2e, 0x48, 0xe9, - 0x1d, 0xb9, 0x0f, 0x52, 0x7a, 0x0f, 0xfa, 0x4a, 0x43, 0x63, 0xb9, 0x6f, 0x68, 0x2c, 0xa9, 0xb6, - 0xea, 0x86, 0xae, 0xbc, 0x46, 0xba, 0xf6, 0x1a, 0xe9, 0xda, 0x6b, 0x54, 0xea, 0x2a, 0x10, 0xdc, - 0xe8, 0x28, 0x9b, 0xc8, 0x3d, 0x7d, 0x27, 0xaa, 0xf5, 0x1d, 0xb0, 0xd1, 0x1f, 0xd6, 0x77, 0x64, - 0xad, 0xef, 0x84, 0x47, 0x7d, 0xad, 0x63, 0xb7, 0x01, 0xcd, 0xe7, 0x7b, 0xf2, 0x52, 0xd2, 0x65, - 0xc6, 0x3b, 0x1e, 0x78, 0x97, 0x5e, 0x90, 0x81, 0x6f, 0x04, 0x25, 0xa9, 0x77, 0x71, 0x9f, 0x98, - 0xff, 0x6a, 0xc9, 0x6e, 0x45, 0xee, 0x64, 0x52, 0x20, 0xdf, 0xdc, 0xe5, 0x65, 0xf1, 0x81, 0xf7, - 0xc5, 0x71, 0xd6, 0x31, 0x35, 0xca, 0xba, 0xd4, 0x1e, 0x3c, 0x4f, 0x50, 0xe5, 0x71, 0x8d, 0x55, - 0xb7, 0x62, 0x06, 0xbb, 0xb7, 0x32, 0x67, 0x23, 0x11, 0x04, 0xf6, 0x55, 0xce, 0x6a, 0xf0, 0x4c, - 0x77, 0x12, 0x1b, 0x48, 0xd9, 0x4e, 0xc1, 0x3f, 0xdd, 0x41, 0x51, 0x37, 0xb1, 0xf1, 0x94, 0xed, - 0x08, 0x5b, 0xa9, 0x81, 0x8b, 0x7f, 0x5f, 0xd8, 0x8b, 0x39, 0x82, 0x70, 0x85, 0x4a, 0xec, 0x87, - 0xda, 0xca, 0x21, 0x32, 0x2f, 0xaf, 0x80, 0x31, 0x35, 0x32, 0xb1, 0xe9, 0x96, 0xc6, 0x8c, 0xef, - 0x0a, 0x29, 0x1c, 0xa0, 0x74, 0x5f, 0x40, 0x45, 0x26, 0x2e, 0x22, 0x72, 0x00, 0xf0, 0xa1, 0x78, - 0x72, 0x11, 0x5e, 0xe6, 0xb9, 0x8b, 0x56, 0xeb, 0x49, 0x00, 0x20, 0x0a, 0xff, 0x13, 0x02, 0xee, - 0x6b, 0x70, 0xd6, 0x3d, 0xc4, 0xf9, 0xc7, 0x25, 0x59, 0xd6, 0xb4, 0xd4, 0x2a, 0xb1, 0xf7, 0xb8, - 0xac, 0x79, 0x46, 0x37, 0xcf, 0x92, 0x1f, 0x49, 0xc9, 0xf0, 0x64, 0xfb, 0x90, 0x1c, 0xd1, 0xc9, - 0xc9, 0x34, 0xd1, 0x3a, 0x59, 0x79, 0x24, 0x84, 0x33, 0x71, 0xab, 0xb1, 0xed, 0xd5, 0x70, 0xf2, - 0x23, 0x1c, 0xfb, 0x13, 0x60, 0x6a, 0x4c, 0x62, 0xb0, 0x58, 0x34, 0xdc, 0xca, 0x3f, 0x24, 0x6a, - 0x7d, 0xca, 0x58, 0x54, 0xe0, 0x87, 0x68, 0x7e, 0x5f, 0xee, 0xf4, 0x9c, 0xdc, 0x71, 0x46, 0x7b, - 0x69, 0x11, 0x55, 0x47, 0x9e, 0xff, 0xae, 0x20, 0x9a, 0x8f, 0x1d, 0xc4, 0x89, 0x91, 0x48, 0x8d, - 0xcf, 0xfb, 0xe2, 0x31, 0xf9, 0x17, 0x35, 0xc7, 0x11, 0xed, 0x8d, 0xc3, 0x4a, 0x9e, 0x37, 0x8d, - 0xd1, 0xe4, 0xf9, 0xbf, 0x39, 0xba, 0x68, 0x77, 0x74, 0x51, 0x63, 0x74, 0x80, 0xe3, 0xe9, 0xee, - 0xe3, 0x93, 0x6c, 0xdb, 0x34, 0x3b, 0xcb, 0xa3, 0x4a, 0x15, 0xbc, 0x32, 0xfd, 0x19, 0x07, 0x9b, - 0xed, 0x68, 0xeb, 0xca, 0x8a, 0x82, 0xac, 0xf7, 0x40, 0x1c, 0x92, 0x52, 0xe3, 0x90, 0x37, 0xf0, - 0xa6, 0xb0, 0xda, 0xb5, 0x96, 0x50, 0x45, 0x14, 0xee, 0x2a, 0x40, 0x41, 0xbf, 0xef, 0xfb, 0x64, - 0x57, 0xe7, 0x09, 0x7a, 0x3d, 0x7e, 0x5e, 0x34, 0x5c, 0x3a, 0xb7, 0x95, 0xb0, 0x37, 0x87, 0x27, - 0x1c, 0x57, 0x82, 0xbe, 0x12, 0xe9, 0x09, 0x43, 0x7c, 0xe7, 0x0c, 0xa9, 0x94, 0xf0, 0xb8, 0x16, - 0xfc, 0x70, 0xfa, 0x69, 0xa4, 0x1c, 0xbc, 0x43, 0xf6, 0x27, 0x44, 0x68, 0x69, 0x89, 0x3e, 0x72, - 0x6e, 0x03, 0x67, 0x12, 0xbd, 0x57, 0x7e, 0xc7, 0x1c, 0xd6, 0x80, 0x02, 0x7d, 0xea, 0x63, 0xdc, - 0x46, 0x52, 0x9f, 0x99, 0xc8, 0x82, 0x94, 0x09, 0x27, 0x39, 0x13, 0x12, 0xb1, 0xdd, 0xa3, 0xa7, - 0xfd, 0x93, 0xab, 0x51, 0xb7, 0x17, 0xf4, 0x6a, 0xa1, 0xcb, 0x3b, 0xa9, 0x3d, 0xf7, 0x8b, 0x92, - 0x14, 0xc5, 0xb8, 0x0d, 0x47, 0x83, 0x59, 0x99, 0x97, 0xc2, 0x41, 0x06, 0x6e, 0x47, 0x95, 0xf0, - 0x25, 0x21, 0xfb, 0x9f, 0xd3, 0x18, 0xbc, 0x81, 0xcd, 0x3a, 0x76, 0xc4, 0x50, 0xfc, 0x0f, 0x88, - 0x79, 0x31, 0x47, 0xa7, 0xc7, 0x35, 0xfe, 0xe3, 0x98, 0xde, 0x3f, 0x4c, 0x3c, 0x51, 0x1a, 0xc1, - 0x69, 0x59, 0xd6, 0x15, 0xf8, 0x3a, 0x29, 0xb5, 0x56, 0x77, 0x7c, 0x72, 0xda, 0x1b, 0xee, 0x6d, - 0x23, 0x51, 0x63, 0x1b, 0x49, 0x8e, 0x6d, 0x23, 0xc9, 0xfe, 0x2e, 0x60, 0xa8, 0x85, 0xc5, 0xcf, - 0xde, 0x46, 0x9e, 0x02, 0xf0, 0x9f, 0xda, 0x46, 0xfe, 0x01, 0x04, 0xf4, 0x67, 0x37, 0x12, 0xf5, - 0x6f, 0x6c, 0x24, 0xa6, 0xa3, 0x37, 0xc0, 0xc5, 0x0f, 0xf4, 0x15, 0x92, 0x6d, 0xc3, 0x85, 0xa9, - 0x12, 0xb8, 0xbd, 0xf9, 0x0b, 0xf2, 0x3a, 0x88, 0x37, 0x8e, 0x6b, 0x3b, 0x57, 0x3e, 0xee, 0x78, - 0x33, 0xbe, 0xd8, 0x51, 0x9e, 0xf7, 0x4f, 0x64, 0xf7, 0xd9, 0x62, 0x5f, 0x43, 0x57, 0x7c, 0x46, - 0x4e, 0xee, 0x79, 0x1c, 0x27, 0xb7, 0xe4, 0x24, 0x16, 0x2b, 0x4e, 0x4e, 0xc2, 0xdf, 0xb3, 0x90, - 0x9c, 0x80, 0xbd, 0x43, 0x4e, 0x56, 0x21, 0xb8, 0x0b, 0x43, 0x72, 0xa2, 0xf8, 0x0c, 0x7b, 0xc1, - 0xd1, 0xd6, 0x55, 0x1d, 0xdb, 0xc4, 0x36, 0xb7, 0xa0, 0x4a, 0xc0, 0xa6, 0x75, 0xf1, 0x14, 0x4a, - 0x3e, 0x34, 0xe2, 0xaf, 0x1f, 0xc6, 0x4c, 0x73, 0xae, 0x30, 0x8e, 0x30, 0xae, 0xc7, 0x63, 0x3d, - 0x7a, 0x27, 0x51, 0x9c, 0xa4, 0x3c, 0xd5, 0xdd, 0x54, 0xcc, 0xb8, 0x35, 0x31, 0xc8, 0x89, 0x41, - 0xa8, 0x13, 0x66, 0x76, 0x28, 0x0e, 0x37, 0x3f, 0xc0, 0x52, 0x4a, 0x9e, 0xa6, 0xc6, 0x27, 0xf8, - 0xe0, 0xe0, 0xaa, 0x6a, 0xcf, 0x1d, 0x9b, 0x51, 0x38, 0x49, 0xb2, 0x86, 0x97, 0xa3, 0xef, 0x83, - 0x5e, 0x37, 0xb5, 0x4a, 0xde, 0x93, 0x58, 0xf8, 0xda, 0x88, 0x87, 0x47, 0x7a, 0xa9, 0x8c, 0x85, - 0xec, 0x89, 0xfd, 0x3e, 0xfe, 0xff, 0xbf, 0xdf, 0x47, 0xbb, 0xfb, 0x7d, 0xf4, 0xdc, 0xfd, 0x3e, - 0x6e, 0x8e, 0x23, 0xfe, 0x4f, 0xed, 0xf7, 0xd1, 0x38, 0xde, 0x1d, 0x5d, 0xbc, 0xb7, 0xdf, 0x83, - 0xec, 0xbb, 0x69, 0x1c, 0x79, 0x89, 0xfd, 0xb3, 0xcf, 0xfa, 0x00, 0x6c, 0x28, 0x8e, 0x1c, 0x83, - 0xda, 0x6d, 0x15, 0x1c, 0x7f, 0xee, 0xda, 0x5e, 0x43, 0xae, 0xf5, 0x6c, 0x9e, 0x39, 0xfa, 0x4a, - 0x59, 0x19, 0x2c, 0x6c, 0xe7, 0xf6, 0xed, 0x6e, 0xe6, 0x8c, 0xcf, 0xb9, 0x52, 0x7c, 0xb6, 0x97, - 0x2d, 0x66, 0xf0, 0xf6, 0xf1, 0x8c, 0x20, 0x38, 0xfb, 0xdb, 0x35, 0xb0, 0xca, 0xef, 0x60, 0xec, - 0x52, 0x13, 0x7c, 0xf4, 0xa0, 0xa8, 0x7a, 0xf2, 0x23, 0x9c, 0xcd, 0xac, 0x08, 0x37, 0xfb, 0x5f, - 0x79, 0x7d, 0xb5, 0x29, 0xdb, 0x7d, 0xdc, 0x78, 0x34, 0xe0, 0x50, 0x6d, 0xd1, 0x64, 0x6b, 0x3a, - 0x0a, 0xea, 0x89, 0x13, 0x37, 0x86, 0x06, 0x2a, 0x88, 0xb5, 0x88, 0x83, 0xd2, 0x7d, 0x54, 0x54, - 0xae, 0x47, 0xb1, 0x77, 0xf4, 0x2b, 0x1e, 0x3f, 0xfa, 0x15, 0xe6, 0x19, 0xd1, 0xe7, 0x1c, 0xfd, - 0x96, 0x33, 0xdb, 0x77, 0x8f, 0x57, 0x6f, 0x8b, 0x9b, 0xa8, 0x93, 0xc6, 0x18, 0xcb, 0x07, 0xd0, - 0x87, 0x4e, 0x6f, 0xe1, 0xb7, 0x27, 0x3f, 0x23, 0x5d, 0xdd, 0xa5, 0x81, 0x3a, 0xf6, 0xb0, 0xa8, - 0x71, 0x56, 0xec, 0x82, 0x14, 0x1d, 0x80, 0x74, 0x6d, 0x5e, 0x66, 0x94, 0xc4, 0x87, 0x30, 0x92, - 0x66, 0xc9, 0xe1, 0x1a, 0x34, 0xc2, 0x8a, 0x1c, 0x6f, 0x30, 0x59, 0x34, 0x51, 0x5d, 0x5f, 0x26, - 0xb6, 0x77, 0xfc, 0xb7, 0x87, 0x58, 0x2d, 0xeb, 0x57, 0x74, 0xb2, 0x12, 0x1a, 0x79, 0x76, 0x39, - 0xe0, 0xaa, 0xa8, 0x47, 0xc4, 0xde, 0x81, 0xae, 0x7b, 0x35, 0x7e, 0x0f, 0x2f, 0x3b, 0x87, 0xe2, - 0xbb, 0x73, 0xd1, 0xa4, 0x87, 0x21, 0x2c, 0x41, 0xba, 0x4b, 0xa4, 0xe8, 0xff, 0xd1, 0xbc, 0xdc, - 0x13, 0xe4, 0x8c, 0x35, 0x06, 0x55, 0x9e, 0x73, 0x3f, 0x46, 0xa5, 0xbc, 0x81, 0x02, 0xe5, 0xe2, - 0x1c, 0xe4, 0x1e, 0x12, 0x76, 0x9b, 0x1e, 0x3e, 0x41, 0x61, 0x5a, 0x37, 0x91, 0x01, 0xd7, 0x75, - 0x9f, 0x9a, 0x40, 0x63, 0xfc, 0xc5, 0x91, 0xb1, 0x54, 0x7d, 0x7a, 0x0d, 0xfc, 0x1d, 0x8e, 0xeb, - 0xb5, 0x15, 0x1c, 0x0f, 0xbd, 0xf1, 0x31, 0xdc, 0xa3, 0x5e, 0xff, 0xa9, 0xd5, 0x68, 0xac, 0x45, - 0xb9, 0x7e, 0xc5, 0xa1, 0x8c, 0x7a, 0xac, 0xa1, 0x78, 0x86, 0x88, 0x90, 0x0f, 0x4c, 0x38, 0x8e, - 0x9b, 0xb3, 0x4d, 0xf7, 0xa6, 0x9b, 0xc8, 0x07, 0xe7, 0x59, 0x06, 0x10, 0x58, 0x21, 0x39, 0x3c, - 0x78, 0x21, 0x78, 0xa4, 0x83, 0xb1, 0x7e, 0x40, 0xb4, 0x21, 0x35, 0xd6, 0x93, 0x3c, 0x37, 0x3f, - 0xf0, 0x12, 0x23, 0xae, 0x5e, 0x23, 0x11, 0x7b, 0x02, 0x75, 0xac, 0x27, 0xe6, 0x69, 0xe6, 0x83, - 0xdc, 0xa3, 0x70, 0xa5, 0x7b, 0xa9, 0xc5, 0xc6, 0x4f, 0xe0, 0xe2, 0x28, 0x3c, 0xe8, 0xb0, 0xd8, - 0x9f, 0xe7, 0x7c, 0xde, 0x9c, 0x68, 0x1d, 0x83, 0x07, 0x0b, 0xfa, 0xa7, 0xa6, 0x66, 0xb9, 0x54, - 0x39, 0xb4, 0x8c, 0xf5, 0xc4, 0xfe, 0x29, 0x88, 0x52, 0xec, 0x54, 0x4f, 0x28, 0x08, 0x4c, 0x7a, - 0x07, 0xc3, 0x80, 0xc5, 0x39, 0x7e, 0x5d, 0xb2, 0x0c, 0xe4, 0x30, 0x0f, 0xb8, 0xef, 0x3f, 0x80, - 0xd3, 0xed, 0x0d, 0xfd, 0x6b, 0x05, 0xcf, 0x49, 0x9b, 0xab, 0x81, 0x55, 0xf1, 0x58, 0x75, 0x7a, - 0x93, 0x32, 0x62, 0x63, 0x7f, 0x07, 0x1b, 0x9e, 0x9e, 0xee, 0xbf, 0x84, 0x63, 0x9e, 0x0d, 0xe0, - 0x76, 0x69, 0xe0, 0x07, 0x14, 0x7c, 0xd4, 0x58, 0x64, 0x53, 0x32, 0x7e, 0x7c, 0xbb, 0xd2, 0xe5, - 0x12, 0x58, 0x35, 0xdb, 0x82, 0xe9, 0xed, 0xcd, 0xb3, 0x29, 0x0c, 0x1f, 0xbc, 0x1e, 0xfa, 0x7f, - 0x37, 0xd5, 0xdd, 0x65, 0x1f, 0xba, 0x6d, 0x04, 0x1b, 0x14, 0x57, 0x43, 0x04, 0x3a, 0x8a, 0x12, - 0x19, 0x85, 0x1a, 0x09, 0x8c, 0x09, 0x6a, 0xce, 0xbd, 0x26, 0x4b, 0x71, 0x28, 0x03, 0xde, 0x9b, - 0x57, 0xc7, 0xd3, 0x43, 0xb9, 0x54, 0x49, 0x1c, 0x7d, 0x20, 0xd5, 0x53, 0xf1, 0x07, 0x3f, 0xda, - 0xc0, 0x01, 0x43, 0x65, 0xe8, 0x68, 0x71, 0xd8, 0xf4, 0xc8, 0x8b, 0x03, 0xcf, 0x91, 0x27, 0xa6, - 0x25, 0x6a, 0x8a, 0x84, 0x47, 0xe4, 0xf9, 0x3e, 0xe7, 0x9b, 0x07, 0xc3, 0x0e, 0x07, 0xcc, 0xe3, - 0xf2, 0x8f, 0x57, 0xec, 0x6e, 0x69, 0xe6, 0x7d, 0x2c, 0x2b, 0x4b, 0x0e, 0x40, 0x35, 0x36, 0xe6, - 0x3d, 0x79, 0xf2, 0x4c, 0x31, 0xdd, 0xd0, 0xce, 0xca, 0x67, 0x1e, 0x8e, 0x2a, 0x6c, 0x66, 0x24, - 0xa6, 0x24, 0xb0, 0x61, 0x49, 0x9e, 0x35, 0x4b, 0x0f, 0x65, 0x5f, 0xb3, 0xf8, 0x90, 0x09, 0x8d, - 0x05, 0xbb, 0x1f, 0x53, 0x05, 0xe3, 0x35, 0xd7, 0xcd, 0x46, 0x07, 0x9d, 0xd9, 0x08, 0xa5, 0x86, - 0x20, 0x25, 0x12, 0x07, 0xbd, 0xe3, 0x75, 0xed, 0x86, 0xb7, 0x5b, 0xb5, 0xcf, 0x58, 0xf5, 0x60, - 0x53, 0xb3, 0x2e, 0x44, 0x14, 0xed, 0x56, 0xdd, 0x27, 0x8d, 0xbd, 0xd8, 0xb9, 0xea, 0xd5, 0x3f, - 0x2b, 0x30, 0x64, 0x75, 0xd0, 0x51, 0x7a, 0x14, 0x76, 0x65, 0x19, 0xbc, 0xec, 0x8d, 0x24, 0x1b, - 0x6f, 0xab, 0x57, 0x84, 0x82, 0x5b, 0x5d, 0x90, 0xc6, 0xe7, 0x5a, 0x17, 0x13, 0xc2, 0x69, 0x6d, - 0xa2, 0x45, 0xf7, 0x26, 0xb2, 0x0f, 0x18, 0x63, 0xa7, 0x1a, 0xb1, 0x2f, 0xf1, 0xa7, 0xc1, 0xb6, - 0xe9, 0x12, 0xb3, 0x87, 0x7a, 0x45, 0x81, 0xf7, 0x0d, 0x2b, 0x63, 0x54, 0x19, 0xba, 0xf8, 0x51, - 0x44, 0x37, 0x60, 0x54, 0x89, 0x59, 0x00, 0x0e, 0x83, 0x32, 0xb4, 0xa8, 0x8c, 0xae, 0xe3, 0xd4, - 0xa5, 0x8a, 0x82, 0xc8, 0x3d, 0x9b, 0xa9, 0xb1, 0x23, 0xd5, 0xef, 0x20, 0x99, 0x73, 0x12, 0x37, - 0x98, 0xda, 0x87, 0x23, 0x8e, 0xb9, 0x70, 0x14, 0xd9, 0x42, 0x2c, 0x8f, 0xfb, 0x2b, 0x1a, 0xa5, - 0x3f, 0x27, 0xdb, 0x23, 0x01, 0xab, 0x4b, 0x82, 0x5b, 0xda, 0x98, 0xa8, 0x41, 0xe6, 0x0c, 0x21, - 0x69, 0x0c, 0x11, 0x5c, 0xc6, 0x67, 0xdd, 0x3c, 0xe9, 0x3d, 0xb4, 0xfc, 0x7d, 0xee, 0xfb, 0xa5, - 0x93, 0x02, 0x92, 0x96, 0x1c, 0xed, 0x31, 0x4a, 0xa9, 0x95, 0x8f, 0x27, 0xc4, 0x45, 0x16, 0x07, - 0x97, 0x64, 0xef, 0xa0, 0x2a, 0xf0, 0x36, 0x5c, 0x69, 0x11, 0x85, 0x71, 0xe9, 0xcc, 0x7a, 0xdd, - 0x84, 0xd0, 0xf0, 0x10, 0x06, 0x3e, 0x69, 0x1a, 0x5e, 0xc1, 0x2b, 0x72, 0x68, 0x9d, 0x59, 0x4f, - 0x68, 0x65, 0x8c, 0x35, 0x3f, 0x7f, 0xdc, 0x75, 0x8f, 0x92, 0x5d, 0x8b, 0x1c, 0xec, 0xc1, 0xda, - 0xe1, 0x11, 0xb8, 0x8f, 0xc6, 0x28, 0x77, 0x43, 0xc8, 0x49, 0x7d, 0xb5, 0xc6, 0xf6, 0xb1, 0x13, - 0x68, 0xd9, 0xeb, 0x93, 0x2a, 0xfc, 0xda, 0xfe, 0x69, 0x19, 0xb2, 0xad, 0x51, 0x51, 0x52, 0x82, - 0x0b, 0xab, 0x04, 0x42, 0xb1, 0x7f, 0x0d, 0xc3, 0xda, 0x2b, 0x9e, 0xc3, 0xba, 0x47, 0x6c, 0x24, - 0xa5, 0x05, 0x60, 0x4d, 0x84, 0x95, 0x26, 0x77, 0x9a, 0x7c, 0xd6, 0xe4, 0x9d, 0x26, 0xef, 0x35, - 0x43, 0x6f, 0x9b, 0x56, 0x0b, 0x5a, 0x69, 0x76, 0xd3, 0xb4, 0x47, 0xf6, 0x48, 0xe4, 0xad, 0x26, - 0x2b, 0x8d, 0xc9, 0x5b, 0x4d, 0xdf, 0xb2, 0x95, 0x26, 0x6f, 0x75, 0xc3, 0x61, 0xfb, 0x16, 0xe2, - 0xd0, 0xdd, 0x76, 0x2f, 0x88, 0x62, 0x0f, 0xbc, 0x4a, 0x6a, 0x28, 0xbe, 0xd1, 0x8c, 0x57, 0x97, - 0x9e, 0x64, 0xf3, 0x21, 0x1d, 0x57, 0x7d, 0x24, 0xeb, 0xd7, 0x4d, 0x7f, 0xcf, 0xb8, 0xba, 0xff, - 0xc0, 0x63, 0x6e, 0x1e, 0xfa, 0x83, 0x97, 0xbd, 0x77, 0xfe, 0x96, 0x86, 0x30, 0x81, 0x9b, 0xe6, - 0xaf, 0x53, 0x58, 0x41, 0xdd, 0x78, 0xf5, 0xeb, 0x81, 0x68, 0x02, 0x92, 0x0d, 0x57, 0x54, 0xc0, - 0x3b, 0x8b, 0xc2, 0xbe, 0xf5, 0xc4, 0x99, 0xf9, 0x1b, 0x32, 0x8c, 0x25, 0xf6, 0xdd, 0xf6, 0xc0, - 0x18, 0x6e, 0x32, 0xcf, 0x25, 0x95, 0x44, 0xb3, 0x2a, 0x10, 0x15, 0x74, 0x1d, 0x92, 0xc1, 0x7e, - 0x0c, 0x7f, 0x99, 0x04, 0x1e, 0xf1, 0x96, 0x4c, 0x07, 0x10, 0x45, 0x26, 0x31, 0x24, 0x09, 0x87, - 0x3f, 0x54, 0x72, 0x47, 0x1a, 0x8f, 0x95, 0xef, 0xff, 0x15, 0x19, 0xf8, 0x6b, 0x06, 0x6a, 0x34, - 0x16, 0x93, 0x80, 0xdb, 0xae, 0x76, 0x1e, 0x51, 0x95, 0xcd, 0x47, 0x54, 0x49, 0x46, 0xc0, 0xe5, - 0x61, 0xfe, 0xf6, 0x09, 0xfc, 0x95, 0x99, 0x0c, 0x14, 0x39, 0xb4, 0x44, 0xab, 0x23, 0x4e, 0xd8, - 0xed, 0x7e, 0x24, 0x5e, 0xa9, 0x10, 0x9b, 0x1b, 0x7c, 0x70, 0x75, 0x40, 0x61, 0xe2, 0xc5, 0x49, - 0x08, 0xac, 0x04, 0x2f, 0x88, 0x36, 0x82, 0x2f, 0xc3, 0xd9, 0xbd, 0xd9, 0x74, 0x46, 0x1c, 0x35, - 0x1e, 0x95, 0x3d, 0x08, 0x1a, 0xf5, 0xbe, 0x79, 0xff, 0xce, 0x3c, 0x62, 0x2c, 0xf5, 0x0f, 0x49, - 0x38, 0x83, 0xfb, 0xf1, 0x80, 0x76, 0x87, 0x6b, 0xf4, 0x59, 0xb3, 0x3b, 0xf8, 0x3f, 0xcf, 0xb7, - 0x05, 0xa6, 0x1b, 0xae, 0x52, 0x91, 0x48, 0xe6, 0x0d, 0xe8, 0x80, 0xf6, 0x3d, 0xf2, 0x59, 0x53, - 0x6b, 0xbf, 0xfc, 0x5c, 0x25, 0xad, 0xb4, 0x63, 0xef, 0x35, 0x41, 0xef, 0x34, 0xfb, 0xac, 0x69, - 0x26, 0xf2, 0x1c, 0x99, 0x5f, 0xf3, 0x07, 0x00, 0xe8, 0x92, 0x2d, 0xc9, 0x3b, 0xa8, 0xec, 0xc4, - 0xd9, 0xd7, 0xf0, 0xb6, 0xe4, 0x02, 0x28, 0x98, 0x5a, 0xc6, 0x65, 0x53, 0xf3, 0x61, 0x8f, 0xd7, - 0xd9, 0xda, 0x7c, 0x18, 0xef, 0x14, 0xbb, 0x35, 0xe9, 0xaf, 0x93, 0x3b, 0x76, 0x0f, 0x74, 0x5f, - 0xe0, 0xe1, 0xff, 0x01, 0xdb, 0x7f, 0xac, 0xfd, 0xf1, 0x6d, 0x00, 0x00 -}; - diff --git a/wled00/json.cpp b/wled00/json.cpp index 1c25433bde..dded3ea75e 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -796,10 +796,11 @@ void serializeInfo(JsonObject root) int qrssi = WiFi.RSSI(); wifi_info[F("rssi")] = qrssi; wifi_info[F("signal")] = getSignalQuality(qrssi); + constexpr int WIFI_5GHZ_MIN_CHANNEL = 36; int wifiChannel = WiFi.channel(); wifi_info[F("channel")] = wifiChannel; if (wifiChannel > 0) { - wifi_info[F("band")] = (wifiChannel >= 36) ? F("5GHz") : F("2.4GHz"); + wifi_info[F("band")] = (wifiChannel >= WIFI_5GHZ_MIN_CHANNEL) ? F("5GHz") : F("2.4GHz"); } wifi_info[F("ap")] = apActive; @@ -815,7 +816,7 @@ void serializeInfo(JsonObject root) wifi_info[F("txPower")] = (int) WiFi.getTxPower(); wifi_info[F("sleep")] = (bool) WiFi.getSleep(); #endif - #if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(CONFIG_IDF_TARGET_ESP32) root[F("arch")] = "esp32"; #else root[F("arch")] = ESP.getChipModel(); diff --git a/wled00/ota_update.cpp b/wled00/ota_update.cpp index e91e5a98c0..6748e6e7b1 100644 --- a/wled00/ota_update.cpp +++ b/wled00/ota_update.cpp @@ -410,6 +410,7 @@ bool verifyBootloaderImage(const uint8_t* &buffer, size_t &len, String* bootload // 0x000C = ESP32-C2 // 0x000D = ESP32-C6 // 0x0010 = ESP32-H2 + // 0x0017 = ESP32-C5 #if defined(CONFIG_IDF_TARGET_ESP32) if (chipId != 0x0000) { diff --git a/wled00/wled.cpp b/wled00/wled.cpp index a2d97b077f..ebbbdec72f 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -874,7 +874,7 @@ void WLED::handleConnection() DEBUG_PRINT(F("Connected! IP address: ")); DEBUG_PRINTLN(WLEDNetwork.localIP()); #if defined(CONFIG_IDF_TARGET_ESP32C5) - { int32_t ch = WiFi.channel(); DEBUG_PRINTF_P(PSTR("WiFi channel: %d (%s)\n"), ch, (ch >= 36) ? "5GHz" : "2.4GHz"); } + { constexpr int kFirst5GHzChannel = 36; int32_t ch = WiFi.channel(); DEBUG_PRINTF_P(PSTR("WiFi channel: %d (%s)\n"), ch, (ch >= kFirst5GHzChannel) ? "5GHz" : "2.4GHz"); } #endif if (improvActive) { if (improvError == 3) sendImprovStateResponse(0x00, true); diff --git a/wled00/wled.h b/wled00/wled.h index 02002d9fe8..e53781b575 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -154,7 +154,9 @@ #endif #ifdef WLED_ENABLE_DMX - #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) + #if defined(CONFIG_IDF_TARGET_ESP32C5) + #error "DMX output is not supported on ESP32-C5 (esp_dmx library excluded)" + #elif defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) #include "src/dependencies/dmx/ESPDMX.h" #else //ESP32 #include "src/dependencies/dmx/SparkFunDMX.h" @@ -469,7 +471,9 @@ 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 - #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) + #if defined(CONFIG_IDF_TARGET_ESP32C5) + #error "DMX output is not supported on ESP32-C5 (esp_dmx library excluded)" + #elif defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) WLED_GLOBAL DMXESPSerial dmx; #else //ESP32 WLED_GLOBAL SparkFunDMX dmx; From d2e6a568baf3a70393f457a830e09de8cee08a52 Mon Sep 17 00:00:00 2001 From: Jonny Davey Date: Sat, 7 Feb 2026 21:52:22 +0000 Subject: [PATCH 30/83] Use NeoPixelBus fork with ESP32-C5 bit-bang and I2S fixes Replace upstream NeoPixelBus with jonny190/NeoPixelBus fork (d4bbe3f) which adds C5 to the I2S exclusion guard and fixes the bit-bang LED output method (cycle counter CSR 0xC00, GPIO register types). Spell out C5 lib_deps explicitly to avoid pulling both the upstream and fork NeoPixelBus, which causes duplicate compilation errors. Upstream PR: https://github.com/netmindz/NeoPixelBus/pull/1 --- platformio.ini | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 9e7b612584..1c7a992b59 100644 --- a/platformio.ini +++ b/platformio.ini @@ -474,9 +474,17 @@ build_flags = -g ;; ARDUINO_USB_CDC_ON_BOOT ${esp32_idf_V5.build_flags} lib_deps = - ${esp32_idf_V5.lib_deps} + ;; NB: we spell out deps explicitly (instead of ${esp32_idf_V5.lib_deps}) to replace + ;; the upstream NeoPixelBus with a C5-patched fork; using both causes duplicate compilation. + ${esp32_all_variants.lib_deps} + fastled/FastLED @ 3.10.1 + https://github.com/jonny190/NeoPixelBus.git#d4bbe3f899a9d7c39ff4569827b2cf4665b3b64d ;; C5 support: I2S exclusion + bit-bang CSR/GPIO fixes on top of netmindz CORE3 + https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.2 + marvinroger/AsyncMqttClient @ 0.9.0 + https://github.com/blazoncek/QuickESPNow.git#optional-debug lib_ignore = ${esp32_idf_V5.lib_ignore} esp_dmx ;; esp_dmx library doesn't support C5 UART registers yet +extra_scripts = ${scripts_defaults.extra_scripts} [env:esp32c5dev] ;; ESP32-C5 "devkit C" with 4MB flash, no PSRAM - EXPERIMENTAL From 1a025f563639959ec039b19cd81542ea796fdeca Mon Sep 17 00:00:00 2001 From: Jonny Davey Date: Sun, 8 Feb 2026 11:20:29 +0000 Subject: [PATCH 31/83] Fix MAC address on ESP32-C5 and update NeoPixelBus fork - Fix WiFi.macAddress() returning all zeros on ESP32-C5 by falling back to esp_read_mac() when WiFi netif is not yet created - Update NeoPixelBus fork to latest with channel ctor overload fix - Enable WLED_DEBUG, remove WLED_DISABLE_WEBSOCKETS for C5 build --- platformio.ini | 4 ++-- wled00/wled.cpp | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 1c7a992b59..a2e2c4e079 100644 --- a/platformio.ini +++ b/platformio.ini @@ -478,7 +478,7 @@ lib_deps = ;; the upstream NeoPixelBus with a C5-patched fork; using both causes duplicate compilation. ${esp32_all_variants.lib_deps} fastled/FastLED @ 3.10.1 - https://github.com/jonny190/NeoPixelBus.git#d4bbe3f899a9d7c39ff4569827b2cf4665b3b64d ;; C5 support: I2S exclusion + bit-bang CSR/GPIO fixes on top of netmindz CORE3 + https://github.com/jonny190/NeoPixelBus.git#103cfb585ef8efcdd6645ebb9938bf7012d093fd ;; C5 support: I2S exclusion, bit-bang CSR/GPIO, channel ctor overload https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.2 marvinroger/AsyncMqttClient @ 0.9.0 https://github.com/blazoncek/QuickESPNow.git#optional-debug @@ -502,7 +502,7 @@ build_flags = ${common.build_flags} ${esp32c5.build_flags} -D WLED_RELEASE_NAME= -D WLED_DISABLE_INFRARED ;; library not compatible with -C5 -D WLED_DISABLE_ESPNOW ;; not yet tested -D WLED_DISABLE_ALEXA ;; compile errors - -D WLED_DISABLE_WEBSOCKETS ;; not yet tested + -D WLED_DEBUG upload_speed = 460800 lib_deps = ${esp32c5.lib_deps} lib_ignore = ${esp32c5.lib_ignore} diff --git a/wled00/wled.cpp b/wled00/wled.cpp index ebbbdec72f..c5a5594b79 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -1,6 +1,9 @@ #define WLED_DEFINE_GLOBAL_VARS //only in one source file, wled.cpp! #include "wled.h" #include "wled_ethernet.h" +#ifdef ARDUINO_ARCH_ESP32 +#include "esp_mac.h" +#endif #include "ota_update.h" #ifdef WLED_ENABLE_AOTA #define NO_OTA_PORT @@ -442,6 +445,18 @@ void WLED::setup() escapedMac = WiFi.macAddress(); escapedMac.replace(":", ""); escapedMac.toLowerCase(); +#ifdef ARDUINO_ARCH_ESP32 + // WiFi.macAddress() may return all zeros if the WiFi netif is not yet created + // (e.g. on ESP32-C5 where WiFi.mode() hasn't been called yet). Fall back to + // reading the base MAC directly from eFuse. + if (escapedMac == "000000000000") { + uint8_t mac[6] = {0}; + esp_read_mac(mac, ESP_MAC_WIFI_STA); + char buf[13]; + sprintf(buf, "%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + escapedMac = buf; + } +#endif WLED_SET_AP_SSID(); // otherwise it is empty on first boot until config is saved multiWiFi.push_back(WiFiConfig(CLIENT_SSID,CLIENT_PASS)); // initialise vector with default WiFi From 6cefd14176077893f55ec911af7b37dab8974193 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 8 Feb 2026 16:43:39 +0100 Subject: [PATCH 32/83] fix C5 build error adjustment needed due to modified lib_deps hierarchy in V5 --- platformio.ini | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/platformio.ini b/platformio.ini index e109ce7149..c670b1eec7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -484,12 +484,14 @@ build_flags = -g lib_deps = ;; NB: we spell out deps explicitly (instead of ${esp32_idf_V5.lib_deps}) to replace ;; the upstream NeoPixelBus with a C5-patched fork; using both causes duplicate compilation. - ${esp32_all_variants.lib_deps} - fastled/FastLED @ 3.10.1 + ;; TODO: remove the temporarily Override below once NeoPixelBus has official support for -C5 + ;; ${esp32_all_variants.lib_deps} + esp32async/AsyncTCP @ 3.4.6 + bitbank2/AnimatedGIF@^1.4.7 + https://github.com/Aircoookie/GifDecoder.git#bc3af189b6b1e06946569f6b4287f0b79a860f8e https://github.com/jonny190/NeoPixelBus.git#103cfb585ef8efcdd6645ebb9938bf7012d093fd ;; C5 support: I2S exclusion, bit-bang CSR/GPIO, channel ctor overload - https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.2 - marvinroger/AsyncMqttClient @ 0.9.0 - https://github.com/blazoncek/QuickESPNow.git#optional-debug + https://github.com/netmindz/esp_dmx/#esp-idf-v5-fixes + ${env.lib_deps} lib_ignore = ${esp32_idf_V5.lib_ignore} esp_dmx ;; esp_dmx library doesn't support C5 UART registers yet extra_scripts = ${scripts_defaults.extra_scripts} From 16262ee4243fb413b4dbcd3fab46d809ee5a02b0 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 8 Feb 2026 16:50:37 +0100 Subject: [PATCH 33/83] platformio.ini: moving [esp32c5] upwards so its between the generic sections for S3 and C6 --- platformio.ini | 66 +++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/platformio.ini b/platformio.ini index c670b1eec7..b092e03b79 100644 --- a/platformio.ini +++ b/platformio.ini @@ -389,6 +389,39 @@ board_build.partitions = ${esp32.default_partitions} ;; default partioning for board_build.flash_mode = qio +[esp32c5] +;; generic definitions for all ESP32-C5 boards +;; NOTE: ESP32-C5 requires pioarduino platform (Tasmota framework doesn't include C5 Arduino libs yet) +platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.36/platform-espressif32.zip +platform_packages = +build_unflags = ${esp32_idf_V5.build_unflags} + -D WLED_ENABLE_DMX_INPUT ;; esp_dmx library doesn't support C5 UART registers yet +build_flags = -g + -Wshadow=compatible-local + -DARDUINO_ARCH_ESP32 + -DARDUINO_ARCH_ESP32C5 + -DCONFIG_IDF_TARGET_ESP32C5=1 + -D CONFIG_ASYNC_TCP_USE_WDT=0 + -DCO + ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: + ;; ARDUINO_USB_MODE + ;; ARDUINO_USB_CDC_ON_BOOT + ${esp32_idf_V5.build_flags} +lib_deps = + ;; NB: we spell out deps explicitly (instead of ${esp32_idf_V5.lib_deps}) to replace + ;; the upstream NeoPixelBus with a C5-patched fork; using both causes duplicate compilation. + ;; TODO: remove the temporarily Override below once NeoPixelBus has official support for -C5 + ;; ${esp32_all_variants.lib_deps} + esp32async/AsyncTCP @ 3.4.6 + bitbank2/AnimatedGIF@^1.4.7 + https://github.com/Aircoookie/GifDecoder.git#bc3af189b6b1e06946569f6b4287f0b79a860f8e + https://github.com/jonny190/NeoPixelBus.git#103cfb585ef8efcdd6645ebb9938bf7012d093fd ;; C5 support: I2S exclusion, bit-bang CSR/GPIO, channel ctor overload + https://github.com/netmindz/esp_dmx/#esp-idf-v5-fixes + ${env.lib_deps} +lib_ignore = ${esp32_idf_V5.lib_ignore} + esp_dmx ;; esp_dmx library doesn't support C5 UART registers yet +extra_scripts = ${scripts_defaults.extra_scripts} + [esp32c6] ;; generic definitions for all ESP32-C6 boards platform = ${esp32_idf_V5.platform} @@ -463,39 +496,6 @@ build_unflags = ${env:esp32c6dev_8MB.build_unflags} -D WLED_RELEASE_NAME=\"ESP32 build_flags = ${env:esp32c6dev_8MB.build_flags} -D WLED_RELEASE_NAME=\"ESP32-C6_4MB\" -[esp32c5] -;; generic definitions for all ESP32-C5 boards -;; NOTE: ESP32-C5 requires pioarduino platform (Tasmota framework doesn't include C5 Arduino libs yet) -platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.36/platform-espressif32.zip -platform_packages = -build_unflags = ${esp32_idf_V5.build_unflags} - -D WLED_ENABLE_DMX_INPUT ;; esp_dmx library doesn't support C5 UART registers yet -build_flags = -g - -Wshadow=compatible-local - -DARDUINO_ARCH_ESP32 - -DARDUINO_ARCH_ESP32C5 - -DCONFIG_IDF_TARGET_ESP32C5=1 - -D CONFIG_ASYNC_TCP_USE_WDT=0 - -DCO - ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: - ;; ARDUINO_USB_MODE - ;; ARDUINO_USB_CDC_ON_BOOT - ${esp32_idf_V5.build_flags} -lib_deps = - ;; NB: we spell out deps explicitly (instead of ${esp32_idf_V5.lib_deps}) to replace - ;; the upstream NeoPixelBus with a C5-patched fork; using both causes duplicate compilation. - ;; TODO: remove the temporarily Override below once NeoPixelBus has official support for -C5 - ;; ${esp32_all_variants.lib_deps} - esp32async/AsyncTCP @ 3.4.6 - bitbank2/AnimatedGIF@^1.4.7 - https://github.com/Aircoookie/GifDecoder.git#bc3af189b6b1e06946569f6b4287f0b79a860f8e - https://github.com/jonny190/NeoPixelBus.git#103cfb585ef8efcdd6645ebb9938bf7012d093fd ;; C5 support: I2S exclusion, bit-bang CSR/GPIO, channel ctor overload - https://github.com/netmindz/esp_dmx/#esp-idf-v5-fixes - ${env.lib_deps} -lib_ignore = ${esp32_idf_V5.lib_ignore} - esp_dmx ;; esp_dmx library doesn't support C5 UART registers yet -extra_scripts = ${scripts_defaults.extra_scripts} - [env:esp32c5dev] ;; ESP32-C5 "devkit C" with 4MB flash, no PSRAM - EXPERIMENTAL extends = esp32c5 From b2e0c243b7f8d52dcbe06fd63ea415fb65dae769 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 8 Feb 2026 17:07:59 +0100 Subject: [PATCH 34/83] simplify and correct some long ifdef chains * C5: allow BOARD_HAS_PSRAM * assign MIN_FRAME_DELAY based on number of CPU cores --- wled00/FX.h | 10 ++++++---- wled00/util.cpp | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 5c6d85e0b6..fe73e4bc53 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -70,10 +70,12 @@ extern byte realtimeMode; // used in getMappedPixelIndex() #define WLED_FPS 42 #define FRAMETIME_FIXED (1000/WLED_FPS) #define FRAMETIME strip.getFrameTime() -#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32S2) - #define MIN_FRAME_DELAY 2 // minimum wait between repaints, to keep other functions like WiFi alive -#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) - #define MIN_FRAME_DELAY 3 // S2/C3/C5 are slower than normal esp32, and only have one core +#if defined(ARDUINO_ARCH_ESP32) + #if (SOC_CPU_CORES_NUM < 2) + #define MIN_FRAME_DELAY 3 // S2/C3/C6/C5 are slower than normal esp32, and only have one core + #else + #define MIN_FRAME_DELAY 2 // classic esp32/S3/P4: minimum wait between repaints, to keep other functions like WiFi alive + #endif #else #define MIN_FRAME_DELAY 8 // 8266 legacy MIN_SHOW_DELAY #endif diff --git a/wled00/util.cpp b/wled00/util.cpp index 93c852b682..5ba533824e 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -637,8 +637,8 @@ int32_t hw_random(int32_t lowerlimit, int32_t upperlimit) { // PSRAM compile time checks to provide info for misconfigured env #if defined(BOARD_HAS_PSRAM) - #if defined(IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(ESP8266) - #error "ESP32-C3/C5 and ESP8266 with PSRAM is not supported, please remove BOARD_HAS_PSRAM definition" +#if defined(IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(ESP8266) + #error "ESP32-C3/C6 and ESP8266 with PSRAM is not supported, please remove BOARD_HAS_PSRAM definition" #else #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) // PSRAM fix only needed for classic esp32 // BOARD_HAS_PSRAM also means that compiler flag "-mfix-esp32-psram-cache-issue" has to be used for old "rev.1" esp32 From a1a190510afee49553bf544d2c695fff574cf6fb Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 8 Feb 2026 17:33:18 +0100 Subject: [PATCH 35/83] simplify C5 buildenv * removed flags that are inherited as-is from [esp32c5] * slightly restructured buildenv --- platformio.ini | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/platformio.ini b/platformio.ini index b092e03b79..4ec2cccd5c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -499,11 +499,11 @@ build_flags = ${env:esp32c6dev_8MB.build_flags} -D WLED_RELEASE_NAME=\"ESP32 [env:esp32c5dev] ;; ESP32-C5 "devkit C" with 4MB flash, no PSRAM - EXPERIMENTAL extends = esp32c5 -platform = ${esp32c5.platform} -platform_packages = ${esp32c5.platform_packages} board = esp32-c5-devkitc-1 +board_build.f_flash = 80000000L +board_build.flash_mode = qio +board_build.arduino.memory_type = qio_qspi ;; flash config only, this board has no PSRAM -build_unflags = ${esp32c5.build_unflags} build_flags = ${common.build_flags} ${esp32c5.build_flags} -D WLED_RELEASE_NAME=\"ESP32-C5\" -Wno-volatile -Wno-deprecated-declarations -D WLED_WATCHDOG_TIMEOUT=0 @@ -513,16 +513,14 @@ build_flags = ${common.build_flags} ${esp32c5.build_flags} -D WLED_RELEASE_NAME= -D WLED_DISABLE_ESPNOW ;; not yet tested -D WLED_DISABLE_ALEXA ;; compile errors -D WLED_DEBUG -upload_speed = 460800 -lib_deps = ${esp32c5.lib_deps} lib_ignore = ${esp32c5.lib_ignore} IRremoteESP8266 QuickEspNow board_build.partitions = ${esp32.big_partitions} +upload_speed = 460800 board_build.f_flash = 80000000L board_build.flash_mode = qio -board_build.arduino.memory_type = qio_qspi ;; flash config only, this board has no PSRAM monitor_filters = esp32_exception_decoder From a3a3547fa5fb415809548ba4e6489ae89eef378f Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 8 Feb 2026 17:42:55 +0100 Subject: [PATCH 36/83] adding [env:esp32c5dev_8MB_qspi] experimental buildenv for C5 with PSRAM and 8MB flash --- platformio.ini | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/platformio.ini b/platformio.ini index 4ec2cccd5c..cf258187de 100644 --- a/platformio.ini +++ b/platformio.ini @@ -519,8 +519,34 @@ lib_ignore = ${esp32c5.lib_ignore} board_build.partitions = ${esp32.big_partitions} upload_speed = 460800 +monitor_filters = esp32_exception_decoder + +[env:esp32c5dev_8MB_qspi] +;; ESP32-C5 with 8MB flash and PSRAM - EXPERIMENTAL +extends = esp32c5 +board = esp32-c5-devkitc-1 board_build.f_flash = 80000000L board_build.flash_mode = qio +board_build.arduino.memory_type = qio_qspi ;; this board has PSRAM + +build_flags = ${common.build_flags} ${esp32c5.build_flags} -D WLED_RELEASE_NAME=\"ESP32-C5_8MB_qspi\" + -Wno-volatile -Wno-deprecated-declarations + -D BOARD_HAS_PSRAM + -D WLED_WATCHDOG_TIMEOUT=0 + -DARDUINO_USB_MODE=1 ;; this flag is mandatory for ESP32-C5 + -DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip + -D WLED_DISABLE_INFRARED ;; library not compatible with -C5 + -D WLED_DISABLE_ESPNOW ;; not yet tested + ;; -D WLED_DISABLE_ALEXA ;; compile errors + ;; -D WLED_DEBUG +lib_ignore = ${esp32c5.lib_ignore} + IRremoteESP8266 + QuickEspNow + +board_build.partitions = ${esp32.large_partitions} +board_upload.flash_size = 8MB +board_upload.maximum_size = 8388608 +upload_speed = 460800 monitor_filters = esp32_exception_decoder From b860a1ad28a30b456f1c7808a8323b0ed822aece Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 8 Feb 2026 17:43:27 +0100 Subject: [PATCH 37/83] fix incorrect PSRAM warning on C5 and C6 --- wled00/util.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/util.cpp b/wled00/util.cpp index 5ba533824e..eb5caa878a 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -640,14 +640,14 @@ int32_t hw_random(int32_t lowerlimit, int32_t upperlimit) { #if defined(IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(ESP8266) #error "ESP32-C3/C6 and ESP8266 with PSRAM is not supported, please remove BOARD_HAS_PSRAM definition" #else - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) // PSRAM fix only needed for classic esp32 + #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_IDF_TARGET_ESP32) // PSRAM fix only needed for classic esp32 // BOARD_HAS_PSRAM also means that compiler flag "-mfix-esp32-psram-cache-issue" has to be used for old "rev.1" esp32 #warning "BOARD_HAS_PSRAM defined, make sure to use -mfix-esp32-psram-cache-issue to prevent issues on rev.1 ESP32 boards \ see https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/external-ram.html#esp32-rev-v1-0" #endif #endif #else - #if !defined(IDF_TARGET_ESP32C3) && !defined(ESP8266) + #if !defined(IDF_TARGET_ESP32C3) && !defined(IDF_TARGET_ESP32C6) && !defined(ESP8266) #pragma message("BOARD_HAS_PSRAM not defined, not using PSRAM.") #endif #endif From 20dd750b9bfe908cb6aef5642f5bd0452e42719c Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 8 Feb 2026 17:49:06 +0100 Subject: [PATCH 38/83] alexa build error was already solved in V5 branch --- platformio.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index cf258187de..a18f38b2bb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -511,7 +511,6 @@ build_flags = ${common.build_flags} ${esp32c5.build_flags} -D WLED_RELEASE_NAME= -DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip -D WLED_DISABLE_INFRARED ;; library not compatible with -C5 -D WLED_DISABLE_ESPNOW ;; not yet tested - -D WLED_DISABLE_ALEXA ;; compile errors -D WLED_DEBUG lib_ignore = ${esp32c5.lib_ignore} IRremoteESP8266 @@ -537,7 +536,6 @@ build_flags = ${common.build_flags} ${esp32c5.build_flags} -D WLED_RELEASE_NAME= -DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip -D WLED_DISABLE_INFRARED ;; library not compatible with -C5 -D WLED_DISABLE_ESPNOW ;; not yet tested - ;; -D WLED_DISABLE_ALEXA ;; compile errors ;; -D WLED_DEBUG lib_ignore = ${esp32c5.lib_ignore} IRremoteESP8266 From e9b1a53149ffa69464cf8084f12466cc412eb3ce Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 8 Feb 2026 18:17:03 +0100 Subject: [PATCH 39/83] PSRAM guard bugfix accidentally used IDF_TARGET_.. instead of CONFIG_IDF_TARGET_.. --- wled00/util.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/util.cpp b/wled00/util.cpp index eb5caa878a..4608b4cab7 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -637,7 +637,7 @@ int32_t hw_random(int32_t lowerlimit, int32_t upperlimit) { // PSRAM compile time checks to provide info for misconfigured env #if defined(BOARD_HAS_PSRAM) -#if defined(IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(ESP8266) +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(ESP8266) #error "ESP32-C3/C6 and ESP8266 with PSRAM is not supported, please remove BOARD_HAS_PSRAM definition" #else #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_IDF_TARGET_ESP32) // PSRAM fix only needed for classic esp32 @@ -647,7 +647,7 @@ int32_t hw_random(int32_t lowerlimit, int32_t upperlimit) { #endif #endif #else - #if !defined(IDF_TARGET_ESP32C3) && !defined(IDF_TARGET_ESP32C6) && !defined(ESP8266) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(ESP8266) #pragma message("BOARD_HAS_PSRAM not defined, not using PSRAM.") #endif #endif From 8b98a7ac9e4d0212eb91fe98f88dbfb9ef1807a9 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 8 Feb 2026 18:20:54 +0100 Subject: [PATCH 40/83] future support: adding C61 and P4 to esp32RMTInvertIdle() guard --- wled00/bus_manager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index fb4b22417b..c6e228c7d4 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -1264,8 +1264,8 @@ void BusManager::removeAll() { // If enabled, RMT idle level is set to HIGH when off // to prevent leakage current when using an N-channel MOSFET to toggle LED power void BusManager::esp32RMTInvertIdle() { -#if defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) - // ESP32-C5/C6 use shared RMT method - idle level inversion not supported +#if defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32P4) + // ESP32-C5/C6/P4 use shared RMT method - idle level inversion not supported return; #else bool idle_out; From 0920f0fdcff98a25377d790436325b5f19cfcd43 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 8 Feb 2026 19:00:28 +0100 Subject: [PATCH 41/83] extend some chip type guards for C6 and P4 --- wled00/bus_wrapper.h | 3 ++- wled00/const.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index e0b101d356..a48ca75d19 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -504,7 +504,8 @@ class PolyBus { } #endif - #if defined(ARDUINO_ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5)) + // ToDO: simplify long ifdef guard + #if defined(ARDUINO_ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32C61)) // 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 > 0) channel--; // accommodate I2S1 which is used as 1st bus on classic ESP32 #endif diff --git a/wled00/const.h b/wled00/const.h index 207c828591..9927101c05 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -642,7 +642,7 @@ static_assert(WLED_MAX_BUSSES <= 32, "WLED_MAX_BUSSES exceeds hard limit"); #endif // Defaults pins, type and counts to configure LED output -#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) +#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32P4) #ifdef WLED_ENABLE_DMX #define DEFAULT_LED_PIN 1 #warning "Compiling with DMX. The default LED pin has been changed to pin 1." From b30951e674ba3b147e23f502ccca1a357b4e2158 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 8 Feb 2026 19:11:16 +0100 Subject: [PATCH 42/83] C6 buildenv cleanup * re-enable alexa * remove duplicate WLED_DISABLE_ESPNOW --- platformio.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index a18f38b2bb..43eb6cecb1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -471,8 +471,6 @@ build_flags = ${common.build_flags} ${esp32c6.build_flags} -D WLED_RELEASE_NAME= ;;-DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB -DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip -D WLED_DISABLE_INFRARED ;; library not not compatible with -C6 - -D WLED_DISABLE_ESPNOW ;; not sure if this will work - -D WLED_DISABLE_ALEXA ;; compile errors -D WLED_DISABLE_WEBSOCKETS ;; not sure if this will work (hacks needed in asyncWebserver) -D WLED_DISABLE_ESPNOW ;; ToDO: temporarily disabled, until we find a solution for esp-now build errors with -C6 upload_speed = 460800 From 6b9f90c1dc4b51d4f03bb2fd5f99ee2c2e75beac Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 8 Feb 2026 19:15:10 +0100 Subject: [PATCH 43/83] remove outdated patched libs for C6 --- platformio.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/platformio.ini b/platformio.ini index 43eb6cecb1..abae44ae6f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -443,9 +443,6 @@ build_flags = -g ;; ARDUINO_USB_CDC_ON_BOOT ${esp32_idf_V5.build_flags} lib_deps = - ;;https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 - ; https://github.com/softhack007/AsyncTCP.git#ESP32-C6 ;; patched version needed for -C6 ;; softhack007 use default V5 libraries - ; makuna/NeoPixelBus @ 2.8.0 ;; latest version neeeded for -C6 ;; softhack007 use default V5 libraries ${esp32_idf_V5.lib_deps} lib_ignore = ${esp32_idf_V5.lib_ignore} From 3c246818814ebffd171919c53f160d367ea396f6 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 8 Feb 2026 20:20:28 +0100 Subject: [PATCH 44/83] ifdef guards alignment * Add ESP32-C6 to the fast-path division guards * exclude C6 and P4 from from digitalCount tracking (I2S memory calculation) --- wled00/FX_fcn.cpp | 4 ++-- wled00/bus_manager.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 3e9b4c7860..14ad4a12cf 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1340,7 +1340,7 @@ static uint8_t _add (uint8_t a, uint8_t b) { unsigned t = a + b; return t static uint8_t _subtract (uint8_t a, uint8_t b) { return b > a ? (b - a) : 0; } static uint8_t _difference(uint8_t a, uint8_t b) { return b > a ? (b - a) : (a - b); } static uint8_t _average (uint8_t a, uint8_t b) { return (a + b) >> 1; } -#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) +#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) static uint8_t _multiply (uint8_t a, uint8_t b) { return ((a * b) + 255) >> 8; } // faster than division on C3/C5 but slightly less accurate #else static uint8_t _multiply (uint8_t a, uint8_t b) { return (a * b) / 255; } // origianl uses a & b in range [0,1] @@ -1351,7 +1351,7 @@ static uint8_t _darken (uint8_t a, uint8_t b) { return a < b ? a : b; } static uint8_t _screen (uint8_t a, uint8_t b) { return 255 - _multiply(~a,~b); } // 255 - (255-a)*(255-b)/255 static uint8_t _overlay (uint8_t a, uint8_t b) { return b < 128 ? 2 * _multiply(a,b) : (255 - 2 * _multiply(~a,~b)); } static uint8_t _hardlight (uint8_t a, uint8_t b) { return a < 128 ? 2 * _multiply(a,b) : (255 - 2 * _multiply(~a,~b)); } -#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) +#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) static uint8_t _softlight (uint8_t a, uint8_t b) { return (((b * b * (255 - 2 * a))) + ((2 * a * b + 256) << 8)) >> 16; } // Pegtop's formula (1 - 2a)b^2 #else static uint8_t _softlight (uint8_t a, uint8_t b) { return (b * b * (255 - 2 * a) + 255 * 2 * a * b) / (255 * 255); } // Pegtop's formula (1 - 2a)b^2 + 2ab diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index c6e228c7d4..69c6bac361 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -1158,12 +1158,12 @@ size_t BusManager::memUsage() { // front buffers are always allocated per bus unsigned size = 0; unsigned maxI2S = 0; - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(ESP8266) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C61) && !defined(CONFIG_IDF_TARGET_ESP32P4) && !defined(ESP8266) unsigned digitalCount = 0; #endif for (const auto &bus : busses) { size += bus->getBusSize(); - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(ESP8266) + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C61) && !defined(CONFIG_IDF_TARGET_ESP32P4) && !defined(ESP8266) if (bus->isDigital() && !bus->is2Pin()) { digitalCount++; if ((PolyBus::isParallelI2S1Output() && digitalCount <= 8) || (!PolyBus::isParallelI2S1Output() && digitalCount == 1)) { From 9232bd4d762f57cd71d239afb3f5cfbe40cb5edd Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 8 Feb 2026 20:26:10 +0100 Subject: [PATCH 45/83] correct straping pin comments in pinManager --- wled00/pin_manager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index cf7d492527..8dd1be6c6d 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -233,14 +233,14 @@ bool PinManager::isPinOk(byte gpio, bool output) // JTAG: GPIO39-42 are usually used for inline debugging // GPIO46 is input only and pulled down #elif defined(CONFIG_IDF_TARGET_ESP32C5) - // strapping pins: 2, 7, 27, 28 + // strapping pins: (2), 7, 25, 26, 27, 28 (GPIO2 is not a strapping pin; it's used only for external JTAG when GPIO7 selects it) // GPIO 0-15 directly usable, 16-22 are for SPI flash if (gpio > 15 && gpio < 23) return false; // 16-22 SPI FLASH #if ARDUINO_USB_CDC_ON_BOOT == 1 || ARDUINO_USB_DFU_ON_BOOT == 1 if (gpio == 13 || gpio == 14) return false; // 13-14 USB-JTAG #endif #elif defined(CONFIG_IDF_TARGET_ESP32C6) - // strapping pins: 8, 9, 15 + // strapping pins: 4, 5, 8, 9, 15 (GPIO4/MTMS and GPIO5/MTDI are also strapping pins) // GPIO 0-23 directly usable, 24-30 are for SPI flash if (gpio > 23 && gpio < 31) return false; // 24-30 SPI FLASH #if ARDUINO_USB_CDC_ON_BOOT == 1 || ARDUINO_USB_DFU_ON_BOOT == 1 From be49f34a000ded8a4864064884e9b6222aa982de Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 9 Feb 2026 00:08:03 +0100 Subject: [PATCH 46/83] add include guard for esp_mac.h --- wled00/util.cpp | 8 ++++---- wled00/wled.cpp | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/wled00/util.cpp b/wled00/util.cpp index 4608b4cab7..93b926737e 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -13,10 +13,10 @@ #endif #include "mbedtls/sha1.h" // for SHA1 on ESP32 #include "esp_efuse.h" - #include "esp_chip_info.h" - #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) - #include // V5 requirement - #endif +#include "esp_chip_info.h" +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + #include // V5 requirement +#endif #endif diff --git a/wled00/wled.cpp b/wled00/wled.cpp index e66e0d1ce0..3a61300cdc 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -2,8 +2,12 @@ #include "wled.h" #include "wled_ethernet.h" #ifdef ARDUINO_ARCH_ESP32 +#include "esp_efuse.h" +#include "esp_chip_info.h" +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) #include "esp_mac.h" #endif +#endif #include "ota_update.h" #ifdef WLED_ENABLE_AOTA #define NO_OTA_PORT From 1800a32cafe7c56b3c2fe73d3284b25be970c462 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 9 Feb 2026 00:11:34 +0100 Subject: [PATCH 47/83] align index.js with chip types from nodestruct.h with some "future support" for P4 and C61 --- wled00/data/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index ea60e5c6f0..14bee01585 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -1064,8 +1064,11 @@ function btype(b) case 34: return "ESP32-S3"; case 5: case 35: return "ESP32-C3"; - case 36: return "ESP32-C6"; + case 39: return "ESP32-C6"; + case 40: return "ESP32-C61"; case 41: return "ESP32-C5"; + case 42: + case 43: return "ESP32-P4"; case 1: case 82: return "ESP8266"; } From 9d6329678368e4d57499863f0888f72a04f102e2 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 9 Feb 2026 00:16:42 +0100 Subject: [PATCH 48/83] fix debug delay condition in wled.cpp simplify and correct the condition. it was never correct to assume that all C3/S2 need a delay, because boards with UART-to-USB chip don't need any wait. --- wled00/wled.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 3a61300cdc..89135d6f38 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -386,7 +386,7 @@ void WLED::setup() Serial.setTimeout(50); // this causes troubles on new MCUs that have a "virtual" USB Serial (HWCDC) #else #endif - #if defined(WLED_DEBUG) && defined(ARDUINO_ARCH_ESP32) && (defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || ARDUINO_USB_CDC_ON_BOOT) + #if defined(WLED_DEBUG) && defined(ARDUINO_ARCH_ESP32) && ARDUINO_USB_CDC_ON_BOOT delay(2500); // allow CDC USB serial to initialise #endif #if !defined(WLED_DEBUG) && defined(ARDUINO_ARCH_ESP32) && !defined(WLED_DEBUG_HOST) && ARDUINO_USB_CDC_ON_BOOT From 7370c100aabeb43ea582dba71a5afa5bbec239a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20M=C3=B6hle?= <91616163+softhack007@users.noreply.github.com> Date: Mon, 9 Feb 2026 11:14:58 +0100 Subject: [PATCH 49/83] remove dead (and dangerous) mutex macros in bus_manager.cpp (#5364) these macros are * not used any more * dangerous because they don't time out * dangerous because they use an internal mutex of the ledc driver (not part of the LEDC API) --- wled00/bus_manager.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 69c6bac361..024c08b433 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -9,14 +9,6 @@ #include "src/dependencies/network/Network.h" // for isConnected() (& WiFi) #include "driver/ledc.h" #include "soc/ledc_struct.h" - #if !(defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)) - #define LEDC_MUTEX_LOCK() do {} while (xSemaphoreTake(_ledc_sys_lock, portMAX_DELAY) != pdPASS) - #define LEDC_MUTEX_UNLOCK() xSemaphoreGive(_ledc_sys_lock) - extern SemaphoreHandle_t _ledc_sys_lock; - #else - #define LEDC_MUTEX_LOCK() - #define LEDC_MUTEX_UNLOCK() - #endif #endif #ifdef ESP8266 #include "core_esp8266_waveform.h" From 8159768e81631010a084a4c56e149ac186671d13 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 9 Feb 2026 12:19:32 +0100 Subject: [PATCH 50/83] ToDO: research how to set PWM duty cycle and hpoint for dithering latest esp-idf 5.5.x, including C5 --- wled00/bus_manager.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 024c08b433..66973a9f8e 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -551,6 +551,12 @@ void BusPwm::show() { // directly write to LEDC struct as there is no HAL exposed function for dithering // duty has 20 bit resolution with 4 fractional bits (24 bits in total) #if defined(CONFIG_IDF_TARGET_ESP32C5) + // TODO: this may not work as intended. + // the .duty_init.duty member seems to only affect fade operations, and its necessary to also trigger an update with + // LEDC.channel_group[gr].channel[ch].conf0.para_up = 1; + // --> research latest (V5.5.x) esp-idf documentation on how to properly set the duty cycle registers by API calls. + // possible alternative: esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint) + // https://docs.espressif.com/projects/esp-idf/en/v5.5.2/esp32c5/api-reference/peripherals/ledc.html#_CPPv424ledc_set_duty_and_update11ledc_mode_t14ledc_channel_t8uint32_t8uint32_t LEDC.channel_group[gr].channel[ch].duty_init.duty = duty << ((!dithering)*4); // C5 LEDC struct uses duty_init #else LEDC.channel_group[gr].channel[ch].duty.duty = duty << ((!dithering)*4); // lowest 4 bits are used for dithering, shift by 4 bits if not using dithering From d8616e69bf5fdf342c983b82551cae17b6afd3b0 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 9 Feb 2026 16:57:20 +0100 Subject: [PATCH 51/83] C5/C6 minor updates * testing code to fake missing DeviceID (commented out) * remove WLED_DISABLE_WEBSOCKETS * use correct board.json for C5 "N8R4" (8MB with PSRAM) --- platformio.ini | 5 ++--- wled00/json.cpp | 5 +++++ wled00/wled.cpp | 6 +++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/platformio.ini b/platformio.ini index abae44ae6f..f86ab620f8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -468,7 +468,6 @@ build_flags = ${common.build_flags} ${esp32c6.build_flags} -D WLED_RELEASE_NAME= ;;-DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB -DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip -D WLED_DISABLE_INFRARED ;; library not not compatible with -C6 - -D WLED_DISABLE_WEBSOCKETS ;; not sure if this will work (hacks needed in asyncWebserver) -D WLED_DISABLE_ESPNOW ;; ToDO: temporarily disabled, until we find a solution for esp-now build errors with -C6 upload_speed = 460800 lib_deps = ${esp32c6.lib_deps} @@ -518,7 +517,7 @@ monitor_filters = esp32_exception_decoder [env:esp32c5dev_8MB_qspi] ;; ESP32-C5 with 8MB flash and PSRAM - EXPERIMENTAL extends = esp32c5 -board = esp32-c5-devkitc-1 +board = esp32-c5-devkitc1-n8r4 board_build.f_flash = 80000000L board_build.flash_mode = qio board_build.arduino.memory_type = qio_qspi ;; this board has PSRAM @@ -531,7 +530,7 @@ build_flags = ${common.build_flags} ${esp32c5.build_flags} -D WLED_RELEASE_NAME= -DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip -D WLED_DISABLE_INFRARED ;; library not compatible with -C5 -D WLED_DISABLE_ESPNOW ;; not yet tested - ;; -D WLED_DEBUG + -D WLED_DEBUG lib_ignore = ${esp32c5.lib_ignore} IRremoteESP8266 QuickEspNow diff --git a/wled00/json.cpp b/wled00/json.cpp index 27a4b0730f..390ffd3a89 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -702,6 +702,11 @@ void serializeInfo(JsonObject root) root[F("repo")] = repoString; #if !defined(ARDUINO_ARCH_ESP32) || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)) // ToDO: find a solution to make this work in V5 root[F("deviceId")] = getDeviceId(); +#else + //#if defined(ARDUINO_ARCH_ESP32) && !defined(WLED_DISABLE_OTA) + // fake 38char fingerprint from bootloaderSHA1. WARNING: only for testing, not suitable for production! + //root[F("deviceId")] = String("0000") + getBootloaderSHA256Hex().substring(4, 34) + String("0000"); + //#endif #endif JsonObject leds = root.createNestedObject(F("leds")); diff --git a/wled00/wled.cpp b/wled00/wled.cpp index add94d634c..ad1f4738c8 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -54,7 +54,11 @@ void WLED::loop() unsigned long loopMillis = millis(); size_t loopDelay = loopMillis - lastRun; if (lastRun == 0) loopDelay=0; // startup - don't have valid data from last run. - if (loopDelay > 2) DEBUG_PRINTF_P(PSTR("Loop delayed more than %ums.\n"), loopDelay); + #if defined(ESP8266) || (SOC_CPU_CORES_NUM < 2) + if (loopDelay > 4) DEBUG_PRINTF_P(PSTR("Loop delayed more than %ums.\n"), loopDelay); // be a bit more relaxed on single-core MCUs + #else + if (loopDelay > 2) DEBUG_PRINTF_P(PSTR("Loop delayed more than %ums.\n"), loopDelay); + #endif static unsigned long maxLoopMillis = 0; static size_t avgLoopMillis = 0; static unsigned long maxUsermodMillis = 0; From 5b46b9cb21ba6e1149c75e029f0fffdda287036a Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 9 Feb 2026 17:02:52 +0100 Subject: [PATCH 52/83] experimental: enable 5Ghz WiFi on C5 does not always work --- wled00/wled.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index ad1f4738c8..5b540b838e 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -527,6 +527,15 @@ void WLED::setup() if (strcmp(multiWiFi[0].clientSSID, DEFAULT_CLIENT_SSID) == 0 && !configBackupExists()) showWelcomePage = true; + #if defined(CONFIG_IDF_TARGET_ESP32C5) + // EXPERIMENTAL: enable 5Ghz WiFi + // see https://docs.espressif.com/projects/esp-idf/en/v5.5.2/esp32c5/api-reference/network/esp_wifi.html#_CPPv425esp_wifi_set_country_codePKcb + // First use ESP-IDF APIs for advanced configuration + esp_wifi_set_band_mode(WIFI_BAND_MODE_AUTO); // 5GHz + 2.4Ghz; use WIFI_BAND_MODE_5G_ONLY for 5Ghz only + esp_wifi_set_country_code("01", true); // Set country "01" = world safe mode; other options: "EU", "US" + // Then hand over to Arduino WiFi class for connection + #endif + #ifndef ESP8266 WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); #endif From 576e82bcbd0ed08a392235aec828f8cb645cc1df Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 9 Feb 2026 19:03:33 +0100 Subject: [PATCH 53/83] report errors from 5Ghz wifi config --- wled00/wled.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 5b540b838e..3af5e85f9c 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -531,8 +531,10 @@ void WLED::setup() // EXPERIMENTAL: enable 5Ghz WiFi // see https://docs.espressif.com/projects/esp-idf/en/v5.5.2/esp32c5/api-reference/network/esp_wifi.html#_CPPv425esp_wifi_set_country_codePKcb // First use ESP-IDF APIs for advanced configuration - esp_wifi_set_band_mode(WIFI_BAND_MODE_AUTO); // 5GHz + 2.4Ghz; use WIFI_BAND_MODE_5G_ONLY for 5Ghz only - esp_wifi_set_country_code("01", true); // Set country "01" = world safe mode; other options: "EU", "US" + esp_err_t wifiErr = esp_wifi_set_band_mode(WIFI_BAND_MODE_AUTO); // 5GHz + 2.4Ghz; use WIFI_BAND_MODE_5G_ONLY for 5Ghz only + if (wifiErr != ESP_OK) DEBUG_PRINTF_P(PSTR("esp_wifi_set_band_mode failed: error %d\n"), wifiErr); + wifiErr = esp_wifi_set_country_code("01", true); // Set country "01" = world safe mode; other options: "EU", "US" + if (wifiErr != ESP_OK) DEBUG_PRINTF_P(PSTR("esp_wifi_set_country_code failed: %d\n"), wifiErr); // Then hand over to Arduino WiFi class for connection #endif From e1045293294bec2ca45a71188559131da15bfbaf Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 9 Feb 2026 19:31:36 +0100 Subject: [PATCH 54/83] move 5Ghz init after WiFi.mode(WIFI_STA) * setting the band mode fails if the driver is not initialized yet * added error checking --- wled00/wled.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 3af5e85f9c..bedcc2fc3d 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -527,23 +527,26 @@ void WLED::setup() if (strcmp(multiWiFi[0].clientSSID, DEFAULT_CLIENT_SSID) == 0 && !configBackupExists()) showWelcomePage = true; - #if defined(CONFIG_IDF_TARGET_ESP32C5) - // EXPERIMENTAL: enable 5Ghz WiFi - // see https://docs.espressif.com/projects/esp-idf/en/v5.5.2/esp32c5/api-reference/network/esp_wifi.html#_CPPv425esp_wifi_set_country_codePKcb - // First use ESP-IDF APIs for advanced configuration - esp_err_t wifiErr = esp_wifi_set_band_mode(WIFI_BAND_MODE_AUTO); // 5GHz + 2.4Ghz; use WIFI_BAND_MODE_5G_ONLY for 5Ghz only - if (wifiErr != ESP_OK) DEBUG_PRINTF_P(PSTR("esp_wifi_set_band_mode failed: error %d\n"), wifiErr); - wifiErr = esp_wifi_set_country_code("01", true); // Set country "01" = world safe mode; other options: "EU", "US" - if (wifiErr != ESP_OK) DEBUG_PRINTF_P(PSTR("esp_wifi_set_country_code failed: %d\n"), wifiErr); - // Then hand over to Arduino WiFi class for connection - #endif - #ifndef ESP8266 WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); #endif WiFi.persistent(false); WiFi.onEvent(WiFiEvent); WiFi.mode(WIFI_STA); // enable scanning + + #if defined(CONFIG_IDF_TARGET_ESP32C5) + // EXPERIMENTAL: enable 5Ghz WiFi - must be done _after_ wifi driver was initialized in WiFi.mode() + // see https://docs.espressif.com/projects/esp-idf/en/v5.5.2/esp32c5/api-reference/network/esp_wifi.html#_CPPv425esp_wifi_set_country_codePKcb + // uses ESP-IDF APIs for advanced configuration + bool haveWifiError = false; + esp_err_t wifiErr = esp_wifi_set_band_mode(WIFI_BAND_MODE_AUTO); // 5GHz + 2.4Ghz; use WIFI_BAND_MODE_5G_ONLY for 5Ghz only + if (wifiErr != ESP_OK) { haveWifiError = true; DEBUG_PRINTF_P(PSTR("esp_wifi_set_band_mode failed: error %d\n"), wifiErr);} + wifiErr = esp_wifi_set_country_code("01", true); // Set country "01" = world safe mode; other options: "EU", "US" + if (wifiErr != ESP_OK) {haveWifiError = true; DEBUG_PRINTF_P(PSTR("esp_wifi_set_country_code failed: %d\n"), wifiErr);} + if (!haveWifiError) DEBUG_PRINTLN("Wifi: 5Ghz setup successful.\n"); + // let Arduino WiFi class do the connection + #endif + findWiFi(true); // start scanning for available WiFi-s // all GPIOs are allocated at this point From 6e70d0c45eb12b65d07de087f8b22a5773757db5 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 9 Feb 2026 19:36:43 +0100 Subject: [PATCH 55/83] clarification --- wled00/wled.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index bedcc2fc3d..2f2bdefc9e 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -535,7 +535,7 @@ void WLED::setup() WiFi.mode(WIFI_STA); // enable scanning #if defined(CONFIG_IDF_TARGET_ESP32C5) - // EXPERIMENTAL: enable 5Ghz WiFi - must be done _after_ wifi driver was initialized in WiFi.mode() + // EXPERIMENTAL: enable 5Ghz WiFi - must be done _after_ wifi driver was initialized in WiFi.mode(), but before WiFi.begin() // see https://docs.espressif.com/projects/esp-idf/en/v5.5.2/esp32c5/api-reference/network/esp_wifi.html#_CPPv425esp_wifi_set_country_codePKcb // uses ESP-IDF APIs for advanced configuration bool haveWifiError = false; From b72568f5c88929438d47a7336f01d05abab20fed Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:47:39 +0100 Subject: [PATCH 56/83] ESP32-C5 does not support analog dithering (yet) use official esp-idf API function (no dithering) --- wled00/bus_manager.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 66973a9f8e..1b7adf658a 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -551,19 +551,19 @@ void BusPwm::show() { // directly write to LEDC struct as there is no HAL exposed function for dithering // duty has 20 bit resolution with 4 fractional bits (24 bits in total) #if defined(CONFIG_IDF_TARGET_ESP32C5) - // TODO: this may not work as intended. // the .duty_init.duty member seems to only affect fade operations, and its necessary to also trigger an update with // LEDC.channel_group[gr].channel[ch].conf0.para_up = 1; - // --> research latest (V5.5.x) esp-idf documentation on how to properly set the duty cycle registers by API calls. - // possible alternative: esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint) + // --> research latest (V5.5.x) esp-idf documentation on how to set the duty cycle registers (by API calls?). // https://docs.espressif.com/projects/esp-idf/en/v5.5.2/esp32c5/api-reference/peripherals/ledc.html#_CPPv424ledc_set_duty_and_update11ledc_mode_t14ledc_channel_t8uint32_t8uint32_t - LEDC.channel_group[gr].channel[ch].duty_init.duty = duty << ((!dithering)*4); // C5 LEDC struct uses duty_init + // LEDC.channel_group[gr].channel[ch].duty_init.duty = duty << ((!dithering)*4); // C5 LEDC struct uses duty_init, but requires additional steps to activate + // TODO: find out if / how dithering support can be impemented on P5 + ledc_set_duty_and_update((ledc_mode_t)gr, (ledc_channel_t)ch, duty >> bitShift, hPoint >> bitShift); #else LEDC.channel_group[gr].channel[ch].duty.duty = duty << ((!dithering)*4); // lowest 4 bits are used for dithering, shift by 4 bits if not using dithering - #endif LEDC.channel_group[gr].channel[ch].hpoint.hpoint = hPoint >> bitShift; // hPoint is at _depth resolution (needs shifting if dithering) ledc_update_duty((ledc_mode_t)gr, (ledc_channel_t)ch); - #endif + #endif // ESP32C5 + #endif // 8266 if (!_reversed) hPoint += duty; hPoint += deadTime; // offset to cascade the signals From d3251c57f9e7fb2c28ee8a609534b0b9534f5091 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:50:01 +0100 Subject: [PATCH 57/83] Use Wifi class method to activate 5Ghz Wifi mixing esp-idf and arduino-syle WiFi = problems --- wled00/wled.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 2f2bdefc9e..3afa4d22aa 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -534,18 +534,12 @@ void WLED::setup() WiFi.onEvent(WiFiEvent); WiFi.mode(WIFI_STA); // enable scanning - #if defined(CONFIG_IDF_TARGET_ESP32C5) - // EXPERIMENTAL: enable 5Ghz WiFi - must be done _after_ wifi driver was initialized in WiFi.mode(), but before WiFi.begin() - // see https://docs.espressif.com/projects/esp-idf/en/v5.5.2/esp32c5/api-reference/network/esp_wifi.html#_CPPv425esp_wifi_set_country_codePKcb - // uses ESP-IDF APIs for advanced configuration - bool haveWifiError = false; - esp_err_t wifiErr = esp_wifi_set_band_mode(WIFI_BAND_MODE_AUTO); // 5GHz + 2.4Ghz; use WIFI_BAND_MODE_5G_ONLY for 5Ghz only - if (wifiErr != ESP_OK) { haveWifiError = true; DEBUG_PRINTF_P(PSTR("esp_wifi_set_band_mode failed: error %d\n"), wifiErr);} - wifiErr = esp_wifi_set_country_code("01", true); // Set country "01" = world safe mode; other options: "EU", "US" - if (wifiErr != ESP_OK) {haveWifiError = true; DEBUG_PRINTF_P(PSTR("esp_wifi_set_country_code failed: %d\n"), wifiErr);} - if (!haveWifiError) DEBUG_PRINTLN("Wifi: 5Ghz setup successful.\n"); - // let Arduino WiFi class do the connection - #endif +#if defined(ARDUINO_ARCH_ESP32) && (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)) + // #if SOC_WIFI_SUPPORT_5G + if (!WiFi.setBandMode(WIFI_BAND_MODE_AUTO)) { // WIFI_BAND_MODE_AUTO = 5GHz+2.4GHz; WIFI_BAND_MODE_5G_ONLY, WIFI_BAND_MODE_2G_ONLY + DEBUG_PRINTLN(F("Wifi band configuration failed!\n")); + } +#endif findWiFi(true); // start scanning for available WiFi-s From f02e6b6c02b1d584043c6a3e3d712c3d8a11027c Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:53:04 +0100 Subject: [PATCH 58/83] proper wifi channel & band reporting replace educated guess (ch > 33 -> 5Ghz) with direct info from Wifi Class --- wled00/json.cpp | 10 +++++++--- wled00/wled.cpp | 12 +++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/wled00/json.cpp b/wled00/json.cpp index 390ffd3a89..91d68a01fe 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -802,11 +802,15 @@ void serializeInfo(JsonObject root) int qrssi = WiFi.RSSI(); wifi_info[F("rssi")] = qrssi; wifi_info[F("signal")] = getSignalQuality(qrssi); - constexpr int WIFI_5GHZ_MIN_CHANNEL = 36; int wifiChannel = WiFi.channel(); wifi_info[F("channel")] = wifiChannel; - if (wifiChannel > 0) { - wifi_info[F("band")] = (wifiChannel >= WIFI_5GHZ_MIN_CHANNEL) ? F("5GHz") : F("2.4GHz"); + if ((wifiChannel > 0) && (unsigned(WiFi.status()) < unsigned(WL_CONNECT_FAILED))) { // Wifi Status > 3 are error statuses (disconnected, stopped, signal lost) + #if defined(ARDUINO_ARCH_ESP32) && SOC_WIFI_SUPPORT_5G + auto wifiBand = WiFi.getBand(); + wifi_info[F("band")] = wifiBand == WIFI_BAND_2G ? F("2.4GHz") : (wifiBand == WIFI_BAND_5G ? F("5GHz"): F("(other)")); + #else + wifi_info[F("band")] = F("2.4GHz"); + #endif } wifi_info[F("ap")] = apActive; diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 3afa4d22aa..0049dfb8f4 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -535,7 +535,7 @@ void WLED::setup() WiFi.mode(WIFI_STA); // enable scanning #if defined(ARDUINO_ARCH_ESP32) && (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)) - // #if SOC_WIFI_SUPPORT_5G + // WiFi.setBandMode(WIFI_BAND_MODE_AUTO) can also be used without SOC_WIFI_SUPPORT_5G if (!WiFi.setBandMode(WIFI_BAND_MODE_AUTO)) { // WIFI_BAND_MODE_AUTO = 5GHz+2.4GHz; WIFI_BAND_MODE_5G_ONLY, WIFI_BAND_MODE_2G_ONLY DEBUG_PRINTLN(F("Wifi band configuration failed!\n")); } @@ -981,9 +981,15 @@ void WLED::handleConnection() DEBUG_PRINTLN(); DEBUG_PRINT(F("Connected! IP address: ")); DEBUG_PRINTLN(WLEDNetwork.localIP()); - #if defined(CONFIG_IDF_TARGET_ESP32C5) - { constexpr int kFirst5GHzChannel = 36; int32_t ch = WiFi.channel(); DEBUG_PRINTF_P(PSTR("WiFi channel: %d (%s)\n"), ch, (ch >= kFirst5GHzChannel) ? "5GHz" : "2.4GHz"); } + DEBUG_PRINT(F("Channel: ")); DEBUG_PRINT(WiFi.channel()); + #if defined(ARDUINO_ARCH_ESP32) && SOC_WIFI_SUPPORT_5G + auto wifiBand = WiFi.getBand(); + DEBUG_PRINT(wifiBand == WIFI_BAND_2G ? F(" (2.4GHz)") : (wifiBand == WIFI_BAND_5G ? F(" (5GHz)"): F(" (other)"))); + #else + DEBUG_PRINT(F(" (2.4GHz)")); #endif + DEBUG_PRINTLN(); + if (improvActive) { if (improvError == 3) sendImprovStateResponse(0x00, true); sendImprovStateResponse(0x04); From b128585618a2ee965d82993d0c1b4425eaf3028e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:53:51 +0100 Subject: [PATCH 59/83] fix compiler warning "comparing signed with unsigned is undefined behaviour" --- wled00/json.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/json.cpp b/wled00/json.cpp index 91d68a01fe..d5ad8ca541 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -1007,7 +1007,7 @@ void serializePalettes(JsonObject root, int page) default: if (i >= palettesCount) // custom palettes setPaletteColors(curPalette, customPalettes[i - palettesCount]); - else if (i < DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_COUNT) // palette 6 - 12, fastled palettes + else if (i < int(DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_COUNT)) // palette 6 - 12, fastled palettes setPaletteColors(curPalette, *fastledPalettes[i - DYNAMIC_PALETTE_COUNT]); else { memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[i - (DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_COUNT)])), sizeof(tcp)); From ab65e9fb5ffe78ceddab1cb5df4361f91b29b536 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:11:09 +0100 Subject: [PATCH 60/83] C5: change NeoPixelBus reference to "wled-c5-stable" tag --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index f86ab620f8..1babedb35a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -415,7 +415,7 @@ lib_deps = esp32async/AsyncTCP @ 3.4.6 bitbank2/AnimatedGIF@^1.4.7 https://github.com/Aircoookie/GifDecoder.git#bc3af189b6b1e06946569f6b4287f0b79a860f8e - https://github.com/jonny190/NeoPixelBus.git#103cfb585ef8efcdd6645ebb9938bf7012d093fd ;; C5 support: I2S exclusion, bit-bang CSR/GPIO, channel ctor overload + https://github.com/jonny190/NeoPixelBus.git#wled-c5-stable ;; wled-c5-stable for C5 support: I2S exclusion, bit-bang CSR/GPIO, channel ctor overload https://github.com/netmindz/esp_dmx/#esp-idf-v5-fixes ${env.lib_deps} lib_ignore = ${esp32_idf_V5.lib_ignore} From ed6b82b2f6ebb35ae587e2d458b6416670acdae6 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:30:00 +0100 Subject: [PATCH 61/83] repeat WiFi.setBandMode() in initConnection() lesson learned: repeat Wifi.setBandMode() after each start of STA interface --- wled00/wled.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 0049dfb8f4..ffaac65a9c 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -537,7 +537,7 @@ void WLED::setup() #if defined(ARDUINO_ARCH_ESP32) && (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)) // WiFi.setBandMode(WIFI_BAND_MODE_AUTO) can also be used without SOC_WIFI_SUPPORT_5G if (!WiFi.setBandMode(WIFI_BAND_MODE_AUTO)) { // WIFI_BAND_MODE_AUTO = 5GHz+2.4GHz; WIFI_BAND_MODE_5G_ONLY, WIFI_BAND_MODE_2G_ONLY - DEBUG_PRINTLN(F("Wifi band configuration failed!\n")); + DEBUG_PRINTLN(F("setup(): Wifi band configuration failed!\n")); } #endif @@ -745,6 +745,12 @@ if (multiWiFi.empty()) { // guard: handle empty WiFi list DEBUG_PRINTLN(F("Access point disabled (init).")); WiFi.softAPdisconnect(true); WiFi.mode(WIFI_STA); + #if defined(ARDUINO_ARCH_ESP32) && (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)) + // we need to renew the "band mode" here, otherwise WiFi falls back to 2.4Ghz only + if (!WiFi.setBandMode(WIFI_BAND_MODE_AUTO)) { // WIFI_BAND_MODE_AUTO = 5GHz+2.4GHz; WIFI_BAND_MODE_5G_ONLY, WIFI_BAND_MODE_2G_ONLY + DEBUG_PRINTLN(F("initConnection(): Wifi band configuration failed!\n")); + } + #endif } } From 7014d4f98ba62dc2b7b03a9465337d26bcd3824b Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:20:18 +0100 Subject: [PATCH 62/83] nitpick: fixing another case of "comparing unsigned to integer is undefined behaviour" the new GCC is a bit more picky than older compiler versions --- wled00/ws.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wled00/ws.cpp b/wled00/ws.cpp index 6d74a5a0b8..12f72ea026 100644 --- a/wled00/ws.cpp +++ b/wled00/ws.cpp @@ -80,7 +80,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp }else if (info->opcode == WS_BINARY) { // first byte determines protocol. Note: since e131_packet_t is "packed", the compiler handles alignment issues //DEBUG_PRINTF_P(PSTR("WS binary message: len %u, byte0: %u\n"), len, data[0]); - int offset = 1; // offset to skip protocol byte + constexpr int offset = 1; // offset to skip protocol byte switch (data[0]) { case BINARY_PROTOCOL_E131: handleE131Packet((e131_packet_t*)&data[offset], client->remoteIP(), P_E131); @@ -89,11 +89,11 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp handleE131Packet((e131_packet_t*)&data[offset], client->remoteIP(), P_ARTNET); break; case BINARY_PROTOCOL_DDP: - if (len < 10 + offset) return; // DDP header is 10 bytes (+1 protocol byte) + if (len < size_t(10 + offset)) return; // DDP header is 10 bytes (+1 protocol byte) size_t ddpDataLen = (data[8+offset] << 8) | data[9+offset]; // data length in bytes from DDP header uint8_t flags = data[0+offset]; if ((flags & DDP_TIMECODE_FLAG) ) ddpDataLen += 4; // timecode flag adds 4 bytes to data length - if (len < (10 + offset + ddpDataLen)) return; // not enough data, prevent out of bounds read + if (len < size_t(10 + offset + ddpDataLen)) return; // not enough data, prevent out of bounds read // could be a valid DDP packet, forward to handler handleE131Packet((e131_packet_t*)&data[offset], client->remoteIP(), P_DDP); } From edf0cbed4a06ad560691f393a0fc27e5c23d07a9 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:20:16 +0100 Subject: [PATCH 63/83] adding wled_boards.h to reduce #if defined() .. clutter This should be the central place to define per-board capability flags --- wled00/bus_wrapper.h | 2 + wled00/wled.h | 2 + wled00/wled_boards.h | 152 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 wled00/wled_boards.h diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index a48ca75d19..0ea71edb0a 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -5,6 +5,8 @@ //#define NPB_CONF_4STEP_CADENCE #include "NeoPixelBus.h" +#include "wled_boards.h" // pull in board-specific capability defines + #ifdef ARDUINO_ARCH_ESP32 #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) // --- temporary shim for NeoPixelBus CORE3 / RMT driver_v2 ------------------ diff --git a/wled00/wled.h b/wled00/wled.h index db1b2363f6..b75a8c67af 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -136,6 +136,8 @@ #include "my_config.h" #endif +#include "wled_boards.h" // pull in board-specific capability defines + #include #include #include diff --git a/wled00/wled_boards.h b/wled00/wled_boards.h new file mode 100644 index 0000000000..b27fb9e1f6 --- /dev/null +++ b/wled00/wled_boards.h @@ -0,0 +1,152 @@ +/* + WLED board capabilities: uses CONFIG_IDF_TARGET_... to extract board capability flags. + You can still use CONFIG_IDF_TARGET_ in the sourc code; this file provides shortcuts for repeating capability checks. +*/ +#pragma once + +#ifndef WLED_BOARDS_H +#define WLED_BOARDS_H +#include "NodeStruct.h" // to get generic NODE_TYPE_IDs + +/* + * Structure: the Below part uses isolated "#if defined()" instead of a chain of if ... elif ... else + * so that the constant WLED_BOARD will be set exactly once unless there are conflicting build_flags. + * In case that several blocks are active, This causes a compiler error to easily spot the problem + * "error: redefinition of 'constexpr const unsigned int WLED_BOARD'" + */ + +/* TODO: add + WLED_HAVE_TOUCH (for button.cpp) + WLED_HAVE_I2S0_LEDS (for bus_wrapper.h) + WLED_HAVE_I2S1_LEDS (for bus_wrapper.h) + (find a name) // On ESP32-C3/C5/C6 only the first 2 RMT channels are usable for transmitting (bus_wrapper.h) + (find a name) // ESP32, S3, P4 can use SparkFunDMX (wled.h, dmx_output.cpp) + WLED_ALLOW_LOLIN_WIFI_FIX // (wled.h) + */ + + +#if defined(ESP8266) +// Capabilities of good-old 8266 + // has no FPU + // bitshift with rounding is faster than integer division + // no byte-accessible fast RTC memory (newer esp32 variants only) + // no parallel I2S LEDs driver +constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP8266; + +#else + // sanity check for esp32 + #if defined(ARDUINO_ARCH_ESP32) || defined(ESP32) + #error "ARDUINO_ARCH_ESP32 or ESP32 is defined together with ESP8266. Please fix your buildenv." + #endif +#endif + +#if CONFIG_IDF_TARGET_ESP32 +// Capabilities of classic ESP32 and classic PICO-D4/D2/D3 + #define WLED_HAVE_FAST_FLOAT 1 // has an FPU for fast floating point (single precision) + #define WLED_HAVE_FAST_int_DIVIDE 1 // integer division is fast (no need to use bitshifts with rounding instead of integer division + // no byte-accessible fast RTC memory (newer esp32 variants only) + #define WLED_HAVE_IRAM_32BIT_HEAP // only classic ESP32 has "32bit accessible only" aka IRAM type heap + + #define WLED_HAS_PARALLEL_I2S 1 // classic esp32 has I2S parallel leds driver (NeoPixelBus) + + constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP32; + // sanity checks + #if (SOC_CPU_CORES_NUM < 2) + #error "ESP32 single-core is not supported." + #endif +#endif + +#if CONFIG_IDF_TARGET_ESP32S3 +// Capabilities of ESP32-S3 + #define WLED_HAVE_FAST_FLOAT 1 // has an FPU for fast floating point (single precision) + #define WLED_HAVE_FAST_int_DIVIDE 1 // integer division is fast (no need to use bitshifts with rounding instead of integer division + #define WLED_HAVE_RTC_MEMORY_HEAP // has byte-accessible fast RTC memory that can be used as heap + // no 4byte-accessible IRAM heap + + #define WLED_HAS_PARALLEL_I2S 1 // esp32-S3 supports I2S parallel leds driver (NeoPixelBus) + + constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP32S3; + // sanity checks + #if (SOC_CPU_CORES_NUM < 2) + #error "ESP32-S3 single-core is not supported." + #endif +#endif + +#if CONFIG_IDF_TARGET_ESP32S2 +// Capabilities of ESP32-S2 + // has no FPU + #define WLED_HAVE_FAST_int_DIVIDE 1 // integer division is fast (no need to use bitshifts with rounding instead of integer division + #define WLED_HAVE_RTC_MEMORY_HEAP // has byte-accessible fast RTC memory that can be used as heap + // no 4byte-accessible IRAM heap + + #define WLED_HAS_PARALLEL_I2S 1 // esp32-S3 supports I2S parallel leds driver (NeoPixelBus) + + constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP32S3; +#endif + +#if CONFIG_IDF_TARGET_ESP32C3 +// Capabilities of ESP32-C3 + // has no FPU + // bitshift with rounding is faster than integer division + #define WLED_HAVE_RTC_MEMORY_HEAP // has byte-accessible fast RTC memory that can be used as heap + // no 4byte-accessible IRAM heap + // no parallel I2S LEDs driver + + constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP32C3; +#endif + +#if CONFIG_IDF_TARGET_ESP32C5 +// Capabilities of ESP32-C5 + // has no FPU + // bitshift with rounding is faster than integer division + #define WLED_HAVE_RTC_MEMORY_HEAP // has byte-accessible fast RTC memory that can be used as heap + // no 4byte-accessible IRAM heap + // no parallel I2S LEDs driver + + constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP32C5; +#endif + +#if CONFIG_IDF_TARGET_ESP32C6 +// Capabilities of ESP32-C6 + // has no FPU + // bitshift with rounding is faster than integer division + #define WLED_HAVE_RTC_MEMORY_HEAP // has byte-accessible fast RTC memory that can be used as heap + // no 4byte-accessible IRAM heap + // no parallel I2S LEDs driver + + constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP32C6; +#endif + +#if CONFIG_IDF_TARGET_ESP32C61 +// Capabilities of ESP32-C61 + // has no FPU + // bitshift with rounding is faster than integer division + #define WLED_HAVE_RTC_MEMORY_HEAP // has byte-accessible fast RTC memory that can be used as heap + // no 4byte-accessible IRAM heap + // no parallel I2S LEDs driver + + constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP32C61; +#endif + +#if CONFIG_IDF_TARGET_ESP32P4 +// Capabilities of ESP32-P4 + #define WLED_HAVE_FAST_FLOAT 1 // has an FPU for fast floating point (single precision) + // TBC: is bitshift with rounding is faster than integer division ? + #define WLED_HAVE_FAST_int_DIVIDE 1 // integer division is fast (no need to use bitshifts with rounding instead of integer division + #define WLED_HAVE_RTC_MEMORY_HEAP // TBC: does it have byte-accessible fast RTC memory that can be used as heap ? + // no 4byte-accessible IRAM heap + // no parallel I2S LEDs driver + + constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP32P4; + + // sanity checks + #if (SOC_CPU_CORES_NUM < 2) + #error "ESP32-P4 single-core is not supported." + #endif +#endif + + +// sanity check: the constexpr assignment below will fail when WLED_BOARD is not set by the previous blocks +constexpr unsigned wled_boards_sanity_check = 0 + WLED_BOARD; + +#endif // WLED_BOARDS_H \ No newline at end of file From d823ab4a9423864edeea1b39a9e3447db60c52a0 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:21:37 +0100 Subject: [PATCH 64/83] replace some very long if defined() chains with flags from wled_boards.h proof of concept. --- wled00/FX_fcn.cpp | 4 ++-- wled00/FXparticleSystem.cpp | 14 +++++++------- wled00/bus_wrapper.h | 24 ++++++++++++------------ 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 14ad4a12cf..3a70e60d48 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1340,7 +1340,7 @@ static uint8_t _add (uint8_t a, uint8_t b) { unsigned t = a + b; return t static uint8_t _subtract (uint8_t a, uint8_t b) { return b > a ? (b - a) : 0; } static uint8_t _difference(uint8_t a, uint8_t b) { return b > a ? (b - a) : (a - b); } static uint8_t _average (uint8_t a, uint8_t b) { return (a + b) >> 1; } -#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) +#if !defined(WLED_HAVE_FAST_int_DIVIDE) static uint8_t _multiply (uint8_t a, uint8_t b) { return ((a * b) + 255) >> 8; } // faster than division on C3/C5 but slightly less accurate #else static uint8_t _multiply (uint8_t a, uint8_t b) { return (a * b) / 255; } // origianl uses a & b in range [0,1] @@ -1351,7 +1351,7 @@ static uint8_t _darken (uint8_t a, uint8_t b) { return a < b ? a : b; } static uint8_t _screen (uint8_t a, uint8_t b) { return 255 - _multiply(~a,~b); } // 255 - (255-a)*(255-b)/255 static uint8_t _overlay (uint8_t a, uint8_t b) { return b < 128 ? 2 * _multiply(a,b) : (255 - 2 * _multiply(~a,~b)); } static uint8_t _hardlight (uint8_t a, uint8_t b) { return a < 128 ? 2 * _multiply(a,b) : (255 - 2 * _multiply(~a,~b)); } -#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) +#if !defined(WLED_HAVE_FAST_int_DIVIDE) static uint8_t _softlight (uint8_t a, uint8_t b) { return (((b * b * (255 - 2 * a))) + ((2 * a * b + 256) << 8)) >> 16; } // Pegtop's formula (1 - 2a)b^2 #else static uint8_t _softlight (uint8_t a, uint8_t b) { return (b * b * (255 - 2 * a) + 255 * 2 * a * b) / (255 * 255); } // Pegtop's formula (1 - 2a)b^2 + 2ab diff --git a/wled00/FXparticleSystem.cpp b/wled00/FXparticleSystem.cpp index 1304a27c7f..da8db8ddba 100644 --- a/wled00/FXparticleSystem.cpp +++ b/wled00/FXparticleSystem.cpp @@ -500,7 +500,7 @@ void ParticleSystem2D::applyGravity(PSparticle &part) { // note: a coefficient smaller than 0 will speed them up (this is a feature, not a bug), coefficient larger than 255 inverts the speed, so don't do that void ParticleSystem2D::applyFriction(PSparticle &part, const int32_t coefficient) { // note: not checking if particle is dead can be done by caller (or can be omitted) - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) + #if !defined(WLED_HAVE_FAST_int_DIVIDE) // use bitshifts with rounding instead of division (2x faster) int32_t friction = 256 - coefficient; part.vx = ((int32_t)part.vx * friction + (((int32_t)part.vx >> 31) & 0xFF)) >> 8; // note: (v>>31) & 0xFF)) extracts the sign and adds 255 if negative for correct rounding using shifts part.vy = ((int32_t)part.vy * friction + (((int32_t)part.vy >> 31) & 0xFF)) >> 8; @@ -514,7 +514,7 @@ void ParticleSystem2D::applyFriction(PSparticle &part, const int32_t coefficient // apply friction to all particles // note: not checking if particle is dead is faster as most are usually alive and if few are alive, rendering is fast anyways void ParticleSystem2D::applyFriction(const int32_t coefficient) { - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) + #if !defined(WLED_HAVE_FAST_int_DIVIDE) // use bitshifts with rounding instead of division (2x faster) int32_t friction = 256 - coefficient; for (uint32_t i = 0; i < usedParticles; i++) { particles[i].vx = ((int32_t)particles[i].vx * friction + (((int32_t)particles[i].vx >> 31) & 0xFF)) >> 8; // note: (v>>31) & 0xFF)) extracts the sign and adds 255 if negative for correct rounding using shifts @@ -929,7 +929,7 @@ void WLED_O2_ATTR ParticleSystem2D::collideParticles(PSparticle &particle1, PSpa int32_t surfacehardness = max(collisionHardness, (int32_t)PS_P_MINSURFACEHARDNESS >> 1); // if particles are soft, the impulse must stay above a limit or collisions slip through at higher speeds, 170 seems to be a good value int32_t impulse = (((((-dotProduct) << 15) / distanceSquared) * surfacehardness) >> 8); // note: inverting before bitshift corrects for asymmetry in right-shifts (is slightly faster) - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) + #if !defined(WLED_HAVE_FAST_int_DIVIDE) // use bitshifts with rounding instead of division (2x faster) int32_t ximpulse = (impulse * dx + ((dx >> 31) & 0x7FFF)) >> 15; // note: extracting sign bit and adding rounding value to correct for asymmetry in right shifts int32_t yimpulse = (impulse * dy + ((dy >> 31) & 0x7FFF)) >> 15; #else @@ -957,7 +957,7 @@ void WLED_O2_ATTR ParticleSystem2D::collideParticles(PSparticle &particle1, PSpa if (collisionHardness < PS_P_MINSURFACEHARDNESS && (SEGMENT.call & 0x07) == 0) { // if particles are soft, they become 'sticky' i.e. apply some friction (they do pile more nicely and stop sloshing around) const uint32_t coeff = collisionHardness + (255 - PS_P_MINSURFACEHARDNESS); // Note: could call applyFriction, but this is faster and speed is key here - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) + #if !defined(WLED_HAVE_FAST_int_DIVIDE) // use bitshifts with rounding instead of division (2x faster) particle1.vx = ((int32_t)particle1.vx * coeff + (((int32_t)particle1.vx >> 31) & 0xFF)) >> 8; // note: (v>>31) & 0xFF)) extracts the sign and adds 255 if negative for correct rounding using shifts particle1.vy = ((int32_t)particle1.vy * coeff + (((int32_t)particle1.vy >> 31) & 0xFF)) >> 8; particle2.vx = ((int32_t)particle2.vx * coeff + (((int32_t)particle2.vx >> 31) & 0xFF)) >> 8; @@ -1406,7 +1406,7 @@ void ParticleSystem1D::applyGravity(PSparticle1D &part, PSparticleFlags1D &partF // slow down particle by friction, the higher the speed, the higher the friction. a high friction coefficient slows them more (255 means instant stop) // note: a coefficient smaller than 0 will speed them up (this is a feature, not a bug), coefficient larger than 255 inverts the speed, so don't do that void ParticleSystem1D::applyFriction(int32_t coefficient) { - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) + #if !defined(WLED_HAVE_FAST_int_DIVIDE) // use bitshifts with rounding instead of division (2x faster) int32_t friction = 256 - coefficient; for (uint32_t i = 0; i < usedParticles; i++) { if (particles[i].ttl) @@ -1699,7 +1699,7 @@ void WLED_O2_ATTR ParticleSystem1D::collideParticles(uint32_t partIdx1, uint32_t } int32_t surfacehardness = max(collisionHardness, (int32_t)PS_P_MINSURFACEHARDNESS_1D); // if particles are soft, the impulse must stay above a limit or collisions slip through // Calculate new velocities after collision note: not using dot product like in 2D as impulse is purely speed depnedent - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) + #if !defined(WLED_HAVE_FAST_int_DIVIDE) // use bitshifts with rounding instead of division (2x faster) int32_t impulse = (dv * surfacehardness + ((dv >> 31) & 0xFF)) >> 8; // note: (v>>31) & 0xFF)) extracts the sign and adds 255 if negative for correct rounding using shifts #else // division is faster on ESP32, S2 and S3 int32_t impulse = (dv * surfacehardness) / 255; @@ -1720,7 +1720,7 @@ void WLED_O2_ATTR ParticleSystem1D::collideParticles(uint32_t partIdx1, uint32_t if (collisionHardness < PS_P_MINSURFACEHARDNESS_1D && (SEGMENT.call & 0x07) == 0) { // if particles are soft, they become 'sticky' i.e. apply some friction const uint32_t coeff = collisionHardness + (250 - PS_P_MINSURFACEHARDNESS_1D); - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(ESP8266) // use bitshifts with rounding instead of division (2x faster) + #if !defined(WLED_HAVE_FAST_int_DIVIDE) // use bitshifts with rounding instead of division (2x faster) particles[partIdx1].vx = ((int32_t)particles[partIdx1].vx * coeff + (((int32_t)particles[partIdx1].vx >> 31) & 0xFF)) >> 8; // note: (v>>31) & 0xFF)) extracts the sign and adds 255 if negative for correct rounding using shifts particles[partIdx2].vx = ((int32_t)particles[partIdx2].vx * coeff + (((int32_t)particles[partIdx2].vx >> 31) & 0xFF)) >> 8; #else // division is faster on ESP32, S2 and S3 diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index 0ea71edb0a..cf7a59a0d0 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -467,7 +467,7 @@ 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 - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(WLED_HAS_PARALLEL_I2S) 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; @@ -499,7 +499,7 @@ class PolyBus { static void* create(uint8_t busType, uint8_t* pins, uint16_t len, uint8_t channel) { // NOTE: "channel" is only used on ESP32 (and its variants) for RMT channel allocation - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_HAS_PARALLEL_I2S) if (_useParallelI2S && (channel >= 8)) { // Parallel I2S channels are to be used first, so subtract 8 to get the RMT channel number channel -= 8; @@ -507,7 +507,7 @@ class PolyBus { #endif // ToDO: simplify long ifdef guard - #if defined(ARDUINO_ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32C61)) + #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_IDF_TARGET_ESP32) // 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 > 0) channel--; // accommodate I2S1 which is used as 1st bus on classic ESP32 #endif @@ -580,7 +580,7 @@ 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 - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(WLED_HAS_PARALLEL_I2S) 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; @@ -679,7 +679,7 @@ 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 - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(WLED_HAS_PARALLEL_I2S) 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; @@ -775,7 +775,7 @@ 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 - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(WLED_HAS_PARALLEL_I2S) case I_32_I2_NEO_3: if (_useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; case I_32_I2_NEO_4: if (_useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; case I_32_I2_400_3: if (_useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; @@ -897,7 +897,7 @@ class PolyBus { case I_32_RN_TM1914_3: (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_RN_SM16825_5: (static_cast(busPtr))->SetPixelColor(pix, Rgbww80Color(col.R*257, col.G*257, col.B*257, cctWW*257, cctCW*257)); break; // I2S1 bus or paralell buses - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(WLED_HAS_PARALLEL_I2S) case I_32_I2_NEO_3: if (_useParallelI2S) (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); else (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_I2_NEO_4: if (_useParallelI2S) (static_cast(busPtr))->SetPixelColor(pix, col); else (static_cast(busPtr))->SetPixelColor(pix, col); break; case I_32_I2_400_3: if (_useParallelI2S) (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); else (static_cast(busPtr))->SetPixelColor(pix, RgbColor(col)); break; @@ -994,7 +994,7 @@ class PolyBus { case I_32_RN_TM1914_3: col = (static_cast(busPtr))->GetPixelColor(pix); break; case I_32_RN_SM16825_5: { Rgbww80Color c = (static_cast(busPtr))->GetPixelColor(pix); col = RGBW32(c.R/257,c.G/257,c.B/257,max(c.WW,c.CW)/257); } break; // will not return original W // I2S1 bus or paralell buses - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(WLED_HAS_PARALLEL_I2S) case I_32_I2_NEO_3: col = (_useParallelI2S) ? (static_cast(busPtr))->GetPixelColor(pix) : (static_cast(busPtr))->GetPixelColor(pix); break; case I_32_I2_NEO_4: col = (_useParallelI2S) ? (static_cast(busPtr))->GetPixelColor(pix) : (static_cast(busPtr))->GetPixelColor(pix); break; case I_32_I2_400_3: col = (_useParallelI2S) ? (static_cast(busPtr))->GetPixelColor(pix) : (static_cast(busPtr))->GetPixelColor(pix); break; @@ -1109,7 +1109,7 @@ class PolyBus { case I_32_RN_TM1914_3: delete (static_cast(busPtr)); break; case I_32_RN_SM16825_5: delete (static_cast(busPtr)); break; // I2S1 bus or paralell buses - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(WLED_HAS_PARALLEL_I2S) case I_32_I2_NEO_3: if (_useParallelI2S) delete (static_cast(busPtr)); else delete (static_cast(busPtr)); break; case I_32_I2_NEO_4: if (_useParallelI2S) delete (static_cast(busPtr)); else delete (static_cast(busPtr)); break; case I_32_I2_400_3: if (_useParallelI2S) delete (static_cast(busPtr)); else delete (static_cast(busPtr)); break; @@ -1206,7 +1206,7 @@ class PolyBus { case I_32_RN_TM1914_3: size = (static_cast(busPtr))->PixelsSize()*2; break; case I_32_RN_SM16825_5: size = (static_cast(busPtr))->PixelsSize()*2; break; // I2S1 bus or paralell buses (front + DMA; DMA = front * cadence, aligned to 4 bytes) - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(WLED_HAS_PARALLEL_I2S) case I_32_I2_NEO_3: size = (_useParallelI2S) ? (static_cast(busPtr))->PixelsSize()*4 : (static_cast(busPtr))->PixelsSize()*4; break; case I_32_I2_NEO_4: size = (_useParallelI2S) ? (static_cast(busPtr))->PixelsSize()*4 : (static_cast(busPtr))->PixelsSize()*4; break; case I_32_I2_400_3: size = (_useParallelI2S) ? (static_cast(busPtr))->PixelsSize()*4 : (static_cast(busPtr))->PixelsSize()*4; break; @@ -1285,7 +1285,7 @@ class PolyBus { case I_32_RN_2805_5 : size = (size + 2*count)*2; break; // 5 channels case I_32_RN_SM16825_5: size = (size + 2*count)*2*2; break; // 16bit, 5 channels // I2S1 bus or paralell I2S1 buses (1x front, does not include DMA buffer which is front*cadence, a bit(?) more for LCD) - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(WLED_HAS_PARALLEL_I2S) || defined(CONFIG_IDF_TARGET_ESP32) case I_32_I2_NEO_3 : // fallthrough case I_32_I2_400_3 : // fallthrough case I_32_I2_TM2_3 : // fallthrough @@ -1372,7 +1372,7 @@ class PolyBus { if (num > 4) return I_NONE; if (num > 3) offset = 1; // only one I2S0 (use last to allow Audioreactive) } - #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) + #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) ||defined(CONFIG_IDF_TARGET_ESP32P4) // On ESP32-C3/C5/C6 only the first 2 RMT channels are usable for transmitting if (num > 1) return I_NONE; //if (num > 1) offset = 1; // I2S not supported yet (only 1 I2S) From cd911ae0db96c219441dc15a248cd6376d03f5e1 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:24:40 +0100 Subject: [PATCH 65/83] oopsie --- wled00/wled_boards.h | 1 - 1 file changed, 1 deletion(-) diff --git a/wled00/wled_boards.h b/wled00/wled_boards.h index b27fb9e1f6..c83c2e74c6 100644 --- a/wled00/wled_boards.h +++ b/wled00/wled_boards.h @@ -33,7 +33,6 @@ // no parallel I2S LEDs driver constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP8266; -#else // sanity check for esp32 #if defined(ARDUINO_ARCH_ESP32) || defined(ESP32) #error "ARDUINO_ARCH_ESP32 or ESP32 is defined together with ESP8266. Please fix your buildenv." From 4f9c48fd39e7ea4a43a1190aab81cb53c20e5df6 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:36:06 +0100 Subject: [PATCH 66/83] consistency fix --- wled00/wled_boards.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wled00/wled_boards.h b/wled00/wled_boards.h index c83c2e74c6..e9b834343f 100644 --- a/wled00/wled_boards.h +++ b/wled00/wled_boards.h @@ -44,7 +44,7 @@ constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP8266; #define WLED_HAVE_FAST_FLOAT 1 // has an FPU for fast floating point (single precision) #define WLED_HAVE_FAST_int_DIVIDE 1 // integer division is fast (no need to use bitshifts with rounding instead of integer division // no byte-accessible fast RTC memory (newer esp32 variants only) - #define WLED_HAVE_IRAM_32BIT_HEAP // only classic ESP32 has "32bit accessible only" aka IRAM type heap + #define WLED_HAVE_IRAM_32BIT_HEAP 1 // only classic ESP32 has "32bit accessible only" aka IRAM type heap #define WLED_HAS_PARALLEL_I2S 1 // classic esp32 has I2S parallel leds driver (NeoPixelBus) @@ -59,7 +59,7 @@ constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP8266; // Capabilities of ESP32-S3 #define WLED_HAVE_FAST_FLOAT 1 // has an FPU for fast floating point (single precision) #define WLED_HAVE_FAST_int_DIVIDE 1 // integer division is fast (no need to use bitshifts with rounding instead of integer division - #define WLED_HAVE_RTC_MEMORY_HEAP // has byte-accessible fast RTC memory that can be used as heap + #define WLED_HAVE_RTC_MEMORY_HEAP 1 // has byte-accessible fast RTC memory that can be used as heap // no 4byte-accessible IRAM heap #define WLED_HAS_PARALLEL_I2S 1 // esp32-S3 supports I2S parallel leds driver (NeoPixelBus) @@ -75,7 +75,7 @@ constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP8266; // Capabilities of ESP32-S2 // has no FPU #define WLED_HAVE_FAST_int_DIVIDE 1 // integer division is fast (no need to use bitshifts with rounding instead of integer division - #define WLED_HAVE_RTC_MEMORY_HEAP // has byte-accessible fast RTC memory that can be used as heap + #define WLED_HAVE_RTC_MEMORY_HEAP 1 // has byte-accessible fast RTC memory that can be used as heap // no 4byte-accessible IRAM heap #define WLED_HAS_PARALLEL_I2S 1 // esp32-S3 supports I2S parallel leds driver (NeoPixelBus) @@ -87,7 +87,7 @@ constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP8266; // Capabilities of ESP32-C3 // has no FPU // bitshift with rounding is faster than integer division - #define WLED_HAVE_RTC_MEMORY_HEAP // has byte-accessible fast RTC memory that can be used as heap + #define WLED_HAVE_RTC_MEMORY_HEAP 1 // has byte-accessible fast RTC memory that can be used as heap // no 4byte-accessible IRAM heap // no parallel I2S LEDs driver @@ -98,7 +98,7 @@ constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP8266; // Capabilities of ESP32-C5 // has no FPU // bitshift with rounding is faster than integer division - #define WLED_HAVE_RTC_MEMORY_HEAP // has byte-accessible fast RTC memory that can be used as heap + #define WLED_HAVE_RTC_MEMORY_HEAP 1 // has byte-accessible fast RTC memory that can be used as heap // no 4byte-accessible IRAM heap // no parallel I2S LEDs driver @@ -132,7 +132,7 @@ constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP8266; #define WLED_HAVE_FAST_FLOAT 1 // has an FPU for fast floating point (single precision) // TBC: is bitshift with rounding is faster than integer division ? #define WLED_HAVE_FAST_int_DIVIDE 1 // integer division is fast (no need to use bitshifts with rounding instead of integer division - #define WLED_HAVE_RTC_MEMORY_HEAP // TBC: does it have byte-accessible fast RTC memory that can be used as heap ? + #define WLED_HAVE_RTC_MEMORY_HEAP 1 // TBC: does it have byte-accessible fast RTC memory that can be used as heap ? // no 4byte-accessible IRAM heap // no parallel I2S LEDs driver From 546384bbbade14b0c68a6e814409f2085dc43e60 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:54:52 +0100 Subject: [PATCH 67/83] fixing minor errors --- wled00/wled_boards.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wled00/wled_boards.h b/wled00/wled_boards.h index e9b834343f..5effcf5089 100644 --- a/wled00/wled_boards.h +++ b/wled00/wled_boards.h @@ -80,7 +80,7 @@ constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP8266; #define WLED_HAS_PARALLEL_I2S 1 // esp32-S3 supports I2S parallel leds driver (NeoPixelBus) - constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP32S3; + constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP32S2; #endif #if CONFIG_IDF_TARGET_ESP32C3 @@ -109,7 +109,7 @@ constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP8266; // Capabilities of ESP32-C6 // has no FPU // bitshift with rounding is faster than integer division - #define WLED_HAVE_RTC_MEMORY_HEAP // has byte-accessible fast RTC memory that can be used as heap + #define WLED_HAVE_RTC_MEMORY_HEAP 1 // has byte-accessible fast RTC memory that can be used as heap // no 4byte-accessible IRAM heap // no parallel I2S LEDs driver @@ -120,7 +120,7 @@ constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP8266; // Capabilities of ESP32-C61 // has no FPU // bitshift with rounding is faster than integer division - #define WLED_HAVE_RTC_MEMORY_HEAP // has byte-accessible fast RTC memory that can be used as heap + #define WLED_HAVE_RTC_MEMORY_HEAP 1 // has byte-accessible fast RTC memory that can be used as heap // no 4byte-accessible IRAM heap // no parallel I2S LEDs driver @@ -132,7 +132,7 @@ constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP8266; #define WLED_HAVE_FAST_FLOAT 1 // has an FPU for fast floating point (single precision) // TBC: is bitshift with rounding is faster than integer division ? #define WLED_HAVE_FAST_int_DIVIDE 1 // integer division is fast (no need to use bitshifts with rounding instead of integer division - #define WLED_HAVE_RTC_MEMORY_HEAP 1 // TBC: does it have byte-accessible fast RTC memory that can be used as heap ? + #define WLED_HAVE_RTC_MEMORY_HEAP 1 // TBC: does it have byte-accessible fast RTC memory that can be used as heap ? // no 4byte-accessible IRAM heap // no parallel I2S LEDs driver From 1009855e89547e5a1853e712b1e13f54f224f1b1 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 18:52:56 +0100 Subject: [PATCH 68/83] shorten some more ifdef chains in wled.h plus: allow LOLIN_WIFI_FIX on all boards --- wled00/wled.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/wled00/wled.h b/wled00/wled.h index b75a8c67af..5bbeca5c04 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -331,7 +331,9 @@ WLED_GLOBAL bool rlyOpenDrain _INIT(RLYODRAIN); #define IRTYPE 0 #endif -#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32S2) || (defined(RX) && defined(TX)) +// RX and TX: use "default" pins for 8266 and classic esp32 +// except when arduino-esp32 has explicitly defined RX and TX (some arduino variants don't define RX and TX) +#if defined(ARDUINO_ARCH_ESP32) && (!defined(CONFIG_IDF_TARGET_ESP32) || (defined(RX) && defined(TX))) // use RX/TX as set by the framework - these boards do _not_ have RX=3 and TX=1 constexpr uint8_t hardwareRX = RX; constexpr uint8_t hardwareTX = TX; @@ -391,8 +393,8 @@ WLED_GLOBAL bool noWifiSleep _INIT(false); #endif WLED_GLOBAL bool force802_3g _INIT(false); #endif // WLED_SAVE_RAM -#ifdef ARDUINO_ARCH_ESP32 - #if defined(LOLIN_WIFI_FIX) && (defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)) +#if defined(ARDUINO_ARCH_ESP32) + #if defined(LOLIN_WIFI_FIX) // extend this fix to all esp32 boards WLED_GLOBAL uint8_t txPower _INIT(WIFI_POWER_8_5dBm); #else WLED_GLOBAL uint8_t txPower _INIT(WIFI_POWER_19_5dBm); @@ -419,7 +421,7 @@ WLED_GLOBAL byte bootPreset _INIT(0); // save preset to load WLED_GLOBAL bool useGlobalLedBuffer _INIT(false); // double buffering disabled on ESP8266 #else WLED_GLOBAL bool useGlobalLedBuffer _INIT(true); // double buffering enabled on ESP32 - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(WLED_HAS_PARALLEL_I2S) WLED_GLOBAL bool useParallelI2S _INIT(false); // parallel I2S for ESP32 #endif #endif From c6739d380f0627e35c1f6a422dcde115ac258352 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 18:54:19 +0100 Subject: [PATCH 69/83] ToDo: adjust Wi-Fi stregth to match value allowed by V5 framework change from uint8_t to int8_t (also verify backwards compatibility for V4) V5 allows WIFI_POWER_21dBm = 84 ... WIFI_POWER_MINUS_1dBm = -4. Also check if the UI can handle it. --- wled00/cfg.cpp | 2 +- wled00/data/settings_wifi.htm | 2 +- wled00/set.cpp | 2 +- wled00/wled.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index e487d82780..48f3feec96 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -159,7 +159,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(force802_3g, wifi[F("phy")]); //force phy mode g? #ifdef ARDUINO_ARCH_ESP32 CJSON(txPower, wifi[F("txpwr")]); - txPower = min(max((int)txPower, (int)WIFI_POWER_2dBm), (int)WIFI_POWER_19_5dBm); + txPower = min(max((int)txPower, (int)WIFI_POWER_2dBm), (int)WIFI_POWER_19_5dBm); // ToDO: V5 allows WIFI_POWER_21dBm = 84 ... WIFI_POWER_MINUS_1dBm = -4 #endif JsonObject hw = doc[F("hw")]; diff --git a/wled00/data/settings_wifi.htm b/wled00/data/settings_wifi.htm index 47220c75d5..6b70675722 100644 --- a/wled00/data/settings_wifi.htm +++ b/wled00/data/settings_wifi.htm @@ -250,7 +250,7 @@

Experimental

Disable WiFi sleep:
Can help with connectivity issues and Audioreactive sync.
Disabling WiFi sleep increases power consumption.

-
TX power: diff --git a/wled00/set.cpp b/wled00/set.cpp index 0c9ac37032..d8997398ce 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -118,7 +118,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) #ifdef ARDUINO_ARCH_ESP32 int tx = request->arg(F("TX")).toInt(); - txPower = min(max(tx, (int)WIFI_POWER_2dBm), (int)WIFI_POWER_19_5dBm); + txPower = min(max(tx, (int)WIFI_POWER_2dBm), (int)WIFI_POWER_19_5dBm); // ToDO: V5 allows WIFI_POWER_21dBm = 84 ... WIFI_POWER_MINUS_1dBm = -4 #endif force802_3g = request->hasArg(F("FG")); diff --git a/wled00/wled.h b/wled00/wled.h index 5bbeca5c04..7832d024e0 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -397,7 +397,7 @@ WLED_GLOBAL bool force802_3g _INIT(false); #if defined(LOLIN_WIFI_FIX) // extend this fix to all esp32 boards WLED_GLOBAL uint8_t txPower _INIT(WIFI_POWER_8_5dBm); #else -WLED_GLOBAL uint8_t txPower _INIT(WIFI_POWER_19_5dBm); +WLED_GLOBAL uint8_t txPower _INIT(WIFI_POWER_19_5dBm); // ToDO: change to int8_t; V5 allows WIFI_POWER_21dBm = 84 ... WIFI_POWER_MINUS_1dBm = -4. Also check if the UI can handle it. #endif #endif #define WLED_WIFI_CONFIGURED isWiFiConfigured() From 08ca41b96d210ada6e295194bfee4e8bd6df8a70 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 10 Feb 2026 19:55:36 +0100 Subject: [PATCH 70/83] expand chip-specific "if defined" to C61 and P4 (future support) Main objective is to fnd out how far away we are from a build for the -P4. I'll clean up the "if def" mess later. --- usermods/audioreactive/audio_reactive.cpp | 2 +- usermods/audioreactive/audio_source.h | 2 +- wled00/FX_fcn.cpp | 4 ++-- wled00/bus_manager.cpp | 2 +- wled00/bus_wrapper.h | 2 +- wled00/button.cpp | 2 +- wled00/cfg.cpp | 4 ++-- wled00/const.h | 12 ++++++------ wled00/dmx_output.cpp | 2 +- wled00/improv.cpp | 2 +- wled00/ota_update.cpp | 2 +- wled00/set.cpp | 2 +- wled00/src/dependencies/dmx/ESPDMX.cpp | 2 +- wled00/src/dependencies/dmx/SparkFunDMX.cpp | 2 +- wled00/udp.cpp | 4 ++++ wled00/wled.h | 10 +++++----- wled00/wled_boards.h | 3 ++- 17 files changed, 32 insertions(+), 27 deletions(-) diff --git a/usermods/audioreactive/audio_reactive.cpp b/usermods/audioreactive/audio_reactive.cpp index 813d38f6c9..3ceb5fbc77 100644 --- a/usermods/audioreactive/audio_reactive.cpp +++ b/usermods/audioreactive/audio_reactive.cpp @@ -668,7 +668,7 @@ class AudioReactive : public Usermod { static const char _dynamics[]; static const char _frequency[]; static const char _inputLvl[]; -#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32S3) +#if defined(CONFIG_IDF_TARGET_ESP32) // analog mic is only supported on classic esp32 static const char _analogmic[]; #endif static const char _digitalmic[]; diff --git a/usermods/audioreactive/audio_source.h b/usermods/audioreactive/audio_source.h index a14f8def0b..df0037dc81 100644 --- a/usermods/audioreactive/audio_source.h +++ b/usermods/audioreactive/audio_source.h @@ -22,7 +22,7 @@ // see https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/chip-series-comparison.html#related-documents // and https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/i2s.html#overview-of-all-modes -#if defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(ESP8266) || defined(ESP8265) +#if defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(ESP8266) || defined(ESP8265) // there are two things in these MCUs that could lead to problems with audio processing: // * no floating point hardware (FPU) support - FFT uses float calculations. If done in software, a strong slow-down can be expected (between 8x and 20x) // * single core, so FFT task might slow down other things like LED updates diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 3a70e60d48..bae5767a71 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1161,7 +1161,7 @@ void WS2812FX::finalizeInit() { BusManager::removeAll(); unsigned digitalCount = 0; - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_HAS_PARALLEL_I2S) // 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; unsigned busType = 0; @@ -1191,7 +1191,7 @@ void WS2812FX::finalizeInit() { bool use_placeholder = false; unsigned busMemUsage = bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount++ : 0); // does not include DMA/RMT buffer // estimate maximum I2S memory usage (only relevant for digital non-2pin busses) - #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) && !defined(ESP8266) + #if defined(WLED_HAS_PARALLEL_I2S) #if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S3) const bool usesI2S = ((useParallelI2S && digitalCount <= 8) || (!useParallelI2S && digitalCount == 1)); #elif defined(CONFIG_IDF_TARGET_ESP32S2) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 1b7adf658a..0ee160daf9 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -1262,7 +1262,7 @@ void BusManager::removeAll() { // If enabled, RMT idle level is set to HIGH when off // to prevent leakage current when using an N-channel MOSFET to toggle LED power void BusManager::esp32RMTInvertIdle() { -#if defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32P4) +#if defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32P4) // ESP32-C5/C6/P4 use shared RMT method - idle level inversion not supported return; #else diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index cf7a59a0d0..90a95a26c9 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -251,7 +251,7 @@ typedef NeoEsp32I2s0Apa106Method X1Apa106Method; typedef NeoEsp32I2s0Ws2805Method X1Ws2805Method; typedef NeoEsp32I2s0Tm1914Method X1Tm1914Method; -#elif !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) +#elif !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C61) && !defined(CONFIG_IDF_TARGET_ESP32P4) // regular ESP32 will use I2S1 typedef NeoEsp32I2s1Ws2812xMethod X1Ws2812xMethod; typedef NeoEsp32I2s1Sk6812Method X1Sk6812Method; diff --git a/wled00/button.cpp b/wled00/button.cpp index 0451f12a3c..96d68f1e93 100644 --- a/wled00/button.cpp +++ b/wled00/button.cpp @@ -109,7 +109,7 @@ bool isButtonPressed(uint8_t b) break; case BTN_TYPE_TOUCH: case BTN_TYPE_TOUCH_SWITCH: - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C61) && !defined(CONFIG_IDF_TARGET_ESP32P4) #ifdef SOC_TOUCH_VERSION_2 //ESP32 S2 and S3 provide a function to check touch state (state is updated in interrupt) if (touchInterruptGetLastStatus(pin)) return true; #else diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 48f3feec96..b948bb3d21 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -177,7 +177,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { uint8_t cctBlending = hw_led[F("cb")] | Bus::getCCTBlend(); Bus::setCCTBlend(cctBlending); strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C61) && !defined(CONFIG_IDF_TARGET_ESP32P4) CJSON(useParallelI2S, hw_led[F("prl")]); #endif @@ -947,7 +947,7 @@ void serializeConfig(JsonObject root) { hw_led[F("cb")] = Bus::getCCTBlend(); hw_led["fps"] = strip.getTargetFps(); hw_led[F("rgbwm")] = Bus::getGlobalAWMode(); // global auto white mode override - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C61) && !defined(CONFIG_IDF_TARGET_ESP32P4) hw_led[F("prl")] = BusManager::hasParallelOutput(); #endif diff --git a/wled00/const.h b/wled00/const.h index 9927101c05..3ffa8814c1 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -67,7 +67,7 @@ constexpr size_t FIXED_PALETTE_COUNT = DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_C constexpr size_t WLED_MAX_ANALOG_CHANNELS = static_cast(LEDC_CHANNEL_MAX) * static_cast(LEDC_SPEED_MODE_MAX); - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32P4) // 2 RMT, 6 LEDC, only has 1 I2S but NPB does not support it ATM #define WLED_MAX_DIGITAL_CHANNELS 2 //#define WLED_MAX_ANALOG_CHANNELS 6 @@ -513,10 +513,10 @@ static_assert(WLED_MAX_BUSSES <= 32, "WLED_MAX_BUSSES exceeds hard limit"); #define MAX_LEDS 1536 //can't rely on memory limit to limit this to 1536 LEDs #elif defined(CONFIG_IDF_TARGET_ESP32S2) #define MAX_LEDS 2048 //due to memory constraints S2 - #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) + #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) #define MAX_LEDS 4096 #else - #define MAX_LEDS 16384 + #define MAX_LEDS 16384 // classic esp32, S3 and P4 can take more #endif #endif @@ -524,12 +524,12 @@ static_assert(WLED_MAX_BUSSES <= 32, "WLED_MAX_BUSSES exceeds hard limit"); #ifdef ESP8266 #define MAX_LED_MEMORY 4096 #else - #if defined(ARDUINO_ARCH_ESP32S2) + #if defined(CONFIG_IDF_TARGET_ESP32S2) #define MAX_LED_MEMORY 16384 - #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) + #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) #define MAX_LED_MEMORY 32768 #else - #define MAX_LED_MEMORY 65536 + #define MAX_LED_MEMORY 65536 // classic esp32, S3 and P4 can take more #endif #endif #endif diff --git a/wled00/dmx_output.cpp b/wled00/dmx_output.cpp index f7b87cb048..fde58a1833 100644 --- a/wled00/dmx_output.cpp +++ b/wled00/dmx_output.cpp @@ -69,7 +69,7 @@ void handleDMXOutput() } void initDMXOutput() { - #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S2) + #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32S2) dmx.init(512); // initialize with bus length #else dmx.initWrite(512); // initialize with bus length diff --git a/wled00/improv.cpp b/wled00/improv.cpp index d94cf35381..2ff90d2eb1 100644 --- a/wled00/improv.cpp +++ b/wled00/improv.cpp @@ -10,7 +10,7 @@ #define DIMPROV_PRINTF(x...) #endif -#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S3) +#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S3) // ToDO check if C6, C61, P4 support this #undef WLED_DISABLE_IMPROV_WIFISCAN #define WLED_DISABLE_IMPROV_WIFISCAN #endif diff --git a/wled00/ota_update.cpp b/wled00/ota_update.cpp index 6748e6e7b1..ccc934597e 100644 --- a/wled00/ota_update.cpp +++ b/wled00/ota_update.cpp @@ -15,7 +15,7 @@ constexpr size_t METADATA_OFFSET = 256; // ESP32: metadata appears afte // Bootloader is at fixed offset 0x1000 (4KB), 0x0000 (0KB), or 0x2000 (8KB), and is typically 32KB // Bootloader offsets for different MCUs => see https://github.com/wled/WLED/issues/5064 -#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) +#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) constexpr size_t BOOTLOADER_OFFSET = 0x0000; // esp32-S3, esp32-C3 and (future support) esp32-c6 constexpr size_t BOOTLOADER_SIZE = 0x8000; // 32KB, typical bootloader size #elif defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32C5) diff --git a/wled00/set.cpp b/wled00/set.cpp index d8997398ce..002ecc68ab 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -192,7 +192,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) Bus::setCCTBlend(cctBlending); Bus::setGlobalAWMode(request->arg(F("AW")).toInt()); strip.setTargetFps(request->arg(F("FR")).toInt()); - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_HAS_PARALLEL_I2S) useParallelI2S = request->hasArg(F("PR")); #endif diff --git a/wled00/src/dependencies/dmx/ESPDMX.cpp b/wled00/src/dependencies/dmx/ESPDMX.cpp index b1a613375a..3d5bc6e4f1 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_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S2) +#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32S2) #include diff --git a/wled00/src/dependencies/dmx/SparkFunDMX.cpp b/wled00/src/dependencies/dmx/SparkFunDMX.cpp index a180869b80..9b653d7866 100644 --- a/wled00/src/dependencies/dmx/SparkFunDMX.cpp +++ b/wled00/src/dependencies/dmx/SparkFunDMX.cpp @@ -17,7 +17,7 @@ Distributed as-is; no warranty is given. #if defined(ARDUINO_ARCH_ESP32) #include -#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32S2) +#if !defined(ESP8266) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C61) && !defined(CONFIG_IDF_TARGET_ESP32S2) #include "SparkFunDMX.h" #include diff --git a/wled00/udp.cpp b/wled00/udp.cpp index ddd14bdddb..50d618de67 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -726,12 +726,16 @@ void sendSysInfoUDP() data[38] = NODE_TYPE_ID_ESP32C5; #elif defined(CONFIG_IDF_TARGET_ESP32C6) data[38] = NODE_TYPE_ID_ESP32C6; + #elif defined(CONFIG_IDF_TARGET_ESP32C61) + data[38] = NODE_TYPE_ID_ESP32C61; #elif defined(CONFIG_IDF_TARGET_ESP32C3) data[38] = NODE_TYPE_ID_ESP32C3; #elif defined(CONFIG_IDF_TARGET_ESP32S3) data[38] = NODE_TYPE_ID_ESP32S3; #elif defined(CONFIG_IDF_TARGET_ESP32S2) data[38] = NODE_TYPE_ID_ESP32S2; + #elif defined(CONFIG_IDF_TARGET_ESP32P4) + data[38] = NODE_TYPE_ID_ESP32P4; #elif defined(ARDUINO_ARCH_ESP32) data[38] = NODE_TYPE_ID_ESP32; #else diff --git a/wled00/wled.h b/wled00/wled.h index 7832d024e0..ead6104b22 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -156,9 +156,9 @@ #endif #ifdef WLED_ENABLE_DMX - #if defined(CONFIG_IDF_TARGET_ESP32C5) - #error "DMX output is not supported on ESP32-C5 (esp_dmx library excluded)" - #elif defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) + #if defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32P4) + #error "DMX output is not supported on ESP32-C5/C6/P4 (esp_dmx library excluded)" + #elif 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" @@ -475,8 +475,8 @@ 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 - #if defined(CONFIG_IDF_TARGET_ESP32C5) - #error "DMX output is not supported on ESP32-C5 (esp_dmx library excluded)" + #if defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32P4) + #error "DMX output is not supported on ESP32-C5/C6/P4 (esp_dmx library excluded)" #elif defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) WLED_GLOBAL DMXESPSerial dmx; #else //ESP32 diff --git a/wled00/wled_boards.h b/wled00/wled_boards.h index 5effcf5089..8ba07e61cd 100644 --- a/wled00/wled_boards.h +++ b/wled00/wled_boards.h @@ -1,6 +1,6 @@ /* WLED board capabilities: uses CONFIG_IDF_TARGET_... to extract board capability flags. - You can still use CONFIG_IDF_TARGET_ in the sourc code; this file provides shortcuts for repeating capability checks. + You can still use CONFIG_IDF_TARGET_ in the source code; this file provides shortcuts for repeating capability checks. */ #pragma once @@ -135,6 +135,7 @@ constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP8266; #define WLED_HAVE_RTC_MEMORY_HEAP 1 // TBC: does it have byte-accessible fast RTC memory that can be used as heap ? // no 4byte-accessible IRAM heap // no parallel I2S LEDs driver + #define WLED_HAS_PARALLEL_PARLIO 1 // (unsupported) P4 allows parallel leds driving with PARLIO unit constexpr unsigned WLED_BOARD = NODE_TYPE_ID_ESP32P4; From a39285a927fddf9a7ef7a2850fa5902414d06541 Mon Sep 17 00:00:00 2001 From: Jonathan Davey Date: Tue, 10 Feb 2026 20:06:02 +0000 Subject: [PATCH 71/83] Add WiFi band preference for dual-band ESP32 chips (#5367) Adds a user-configurable "WiFi band" dropdown to the WiFi settings page: 2.4 GHz only, 5 GHz only, or Auto (both). Defaults to Auto. Uses WiFi.setBandMode() from the Arduino ESP32 core (requires IDF 5.4.2+), guarded by #ifdef SOC_WIFI_SUPPORT_5G. Replaces the hardcoded WIFI_BAND_MODE_AUTO call in V5-C6 with a user-selectable setting. Changes: - wled.h: new wifiBandMode variable (default WIFI_BAND_MODE_AUTO) - cfg.cpp: serialize/deserialize with input validation (1-3 range) - set.cpp: handle BM form param with validation, trigger reconnect - xml.cpp: populate dropdown value, hide on non-5G chips - wled.cpp: pass wifiBandMode to WiFi.setBandMode() in initConnection() - settings_wifi.htm: dropdown in Experimental section Tested on ESP32-C5 hardware - all three modes work correctly. --- wled00/cfg.cpp | 7 +++++++ wled00/data/settings_wifi.htm | 5 +++++ wled00/set.cpp | 9 +++++++++ wled00/wled.cpp | 7 +++---- wled00/wled.h | 3 +++ wled00/xml.cpp | 5 +++++ 6 files changed, 32 insertions(+), 4 deletions(-) diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index b948bb3d21..b638738ed2 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -157,6 +157,10 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { noWifiSleep = !(wifi[F("sleep")] | !noWifiSleep); // inverted //noWifiSleep = !noWifiSleep; CJSON(force802_3g, wifi[F("phy")]); //force phy mode g? +#ifdef SOC_WIFI_SUPPORT_5G + CJSON(wifiBandMode, wifi[F("band")]); + if (wifiBandMode < WIFI_BAND_MODE_2G_ONLY || wifiBandMode > WIFI_BAND_MODE_AUTO) wifiBandMode = WIFI_BAND_MODE_AUTO; +#endif #ifdef ARDUINO_ARCH_ESP32 CJSON(txPower, wifi[F("txpwr")]); txPower = min(max((int)txPower, (int)WIFI_POWER_2dBm), (int)WIFI_POWER_19_5dBm); // ToDO: V5 allows WIFI_POWER_21dBm = 84 ... WIFI_POWER_MINUS_1dBm = -4 @@ -907,6 +911,9 @@ void serializeConfig(JsonObject root) { JsonObject wifi = root.createNestedObject(F("wifi")); wifi[F("sleep")] = !noWifiSleep; wifi[F("phy")] = force802_3g; +#ifdef SOC_WIFI_SUPPORT_5G + wifi[F("band")] = wifiBandMode; +#endif #ifdef ARDUINO_ARCH_ESP32 wifi[F("txpwr")] = txPower; #endif diff --git a/wled00/data/settings_wifi.htm b/wled00/data/settings_wifi.htm index 6b70675722..7e42db6cea 100644 --- a/wled00/data/settings_wifi.htm +++ b/wled00/data/settings_wifi.htm @@ -250,6 +250,11 @@

Experimental

Disable WiFi sleep:
Can help with connectivity issues and Audioreactive sync.
Disabling WiFi sleep increases power consumption.

+
WiFi band:
TX power:
-
TX power: + + + diff --git a/wled00/set.cpp b/wled00/set.cpp index 657b868d2c..24b14fc04e 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -118,7 +118,11 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) #ifdef ARDUINO_ARCH_ESP32 int tx = request->arg(F("TX")).toInt(); - txPower = min(max(tx, (int)WIFI_POWER_2dBm), (int)WIFI_POWER_19_5dBm); // ToDO: V5 allows WIFI_POWER_21dBm = 84 ... WIFI_POWER_MINUS_1dBm = -4 + #if (ESP_IDF_VERSION_MAJOR > 4) + txPower = min(max((int)tx, (int)WIFI_POWER_2dBm), (int)WIFI_POWER_21dBm); // V5 allows WIFI_POWER_21dBm = 84 ... WIFI_POWER_MINUS_1dBm = -4 + #else + txPower = min(max((int)tx, (int)WIFI_POWER_2dBm), (int)WIFI_POWER_19_5dBm); + #endif #endif force802_3g = request->hasArg(F("FG")); From 46a1b2f19007bddf8e555a90d6fc9bc5bdae2e4d Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 11 Feb 2026 00:34:16 +0100 Subject: [PATCH 77/83] clarification according to espressif docs, this is "maximum TX power" not "TX power" --- wled00/data/settings_wifi.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/data/settings_wifi.htm b/wled00/data/settings_wifi.htm index 3c8efac934..c4d03dedde 100644 --- a/wled00/data/settings_wifi.htm +++ b/wled00/data/settings_wifi.htm @@ -255,7 +255,7 @@

Experimental


-
TX power: From ede8a14421ad9c35cfe5944d2cd36536ae314b2d Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 11 Feb 2026 00:57:09 +0100 Subject: [PATCH 78/83] ifdef fixes * shortened another mega-ifdef * added missing CONFIG_IDF_TARGET_ESP32C61 --- wled00/cfg.cpp | 2 +- wled00/util.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 2f8d5bb594..3f73fba552 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -958,7 +958,7 @@ void serializeConfig(JsonObject root) { hw_led[F("cb")] = Bus::getCCTBlend(); hw_led["fps"] = strip.getTargetFps(); hw_led[F("rgbwm")] = Bus::getGlobalAWMode(); // global auto white mode override - #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C61) && !defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_HAS_PARALLEL_I2S) hw_led[F("prl")] = BusManager::hasParallelOutput(); #endif diff --git a/wled00/util.cpp b/wled00/util.cpp index 93b926737e..d8e39526b1 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -698,7 +698,7 @@ static void *validateFreeHeap(void *buffer) { void *d_malloc(size_t size) { void *buffer; - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32P4) // the newer ESP32 variants have byte-accessible fast RTC memory that can be used as heap, access speed is on-par with DRAM // the system does prefer normal DRAM until full, since free RTC memory is ~7.5k only, its below the minimum heap threshold and needs to be allocated explicitly // use RTC RAM for small allocations to improve fragmentation or if DRAM is running low From deaae112a3129fd34dcde2072f182ebf879cc238 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 11 Feb 2026 01:52:33 +0100 Subject: [PATCH 79/83] missed one --- wled00/bus_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 0ee160daf9..ee595f1665 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -550,7 +550,7 @@ void BusPwm::show() { unsigned ch = channel%8; // group channel // directly write to LEDC struct as there is no HAL exposed function for dithering // duty has 20 bit resolution with 4 fractional bits (24 bits in total) - #if defined(CONFIG_IDF_TARGET_ESP32C5) + #if defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32P4) // the .duty_init.duty member seems to only affect fade operations, and its necessary to also trigger an update with // LEDC.channel_group[gr].channel[ch].conf0.para_up = 1; // --> research latest (V5.5.x) esp-idf documentation on how to set the duty cycle registers (by API calls?). From 5e073ce76cac0645ccdf693edb50891b17193730 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 11 Feb 2026 10:48:33 +0100 Subject: [PATCH 80/83] add esp-idf managed folders to .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index a3c1bfbdcc..62e72a9a0a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,10 @@ compile_commands.json __pycache__/ +/.dummy +/dependencies.lock +/managed_components + esp01-update.sh platformio_override.ini replace_fs.py From c1dddeafc47d033e58b6806882f2049cbcaaed89 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:09:23 +0100 Subject: [PATCH 81/83] ermove duplicate extern references these variables are defined in wled.h, which is included already. --- wled00/bus_manager.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index ee595f1665..44023ae1e1 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -17,10 +17,6 @@ #include "bus_wrapper.h" #include "wled.h" -extern char cmDNS[]; -extern bool cctICused; -extern bool useParallelI2S; - // functions to get/set bits in an array - based on functions created by Brandon for GOL // toDo : make this a class that's completely defined in a header file // note: these functions are automatically inline by the compiler From 7ce497b1f7a19b4d14e1f86d4be53beb224f50d6 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 11 Feb 2026 17:01:17 +0100 Subject: [PATCH 82/83] fix broken ifdef chain in wled.h --- wled00/wled.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/wled.h b/wled00/wled.h index 0e017d835a..791cf1731b 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -478,9 +478,9 @@ 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 - #if defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32P4) + #if defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32P4) #error "DMX output is not supported on ESP32-C5/C6/P4 (esp_dmx library excluded)" - #elif defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S2) + #elif defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) WLED_GLOBAL DMXESPSerial dmx; #else //ESP32 WLED_GLOBAL SparkFunDMX dmx; From 3de117ba23760105f83a53f48c88c11eb30292c9 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 12 Feb 2026 11:16:41 +0100 Subject: [PATCH 83/83] typo --- wled00/bus_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 1f4219642c..bcc3a5ea30 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -552,7 +552,7 @@ void BusPwm::show() { // --> research latest (V5.5.x) esp-idf documentation on how to set the duty cycle registers (by API calls?). // https://docs.espressif.com/projects/esp-idf/en/v5.5.2/esp32c5/api-reference/peripherals/ledc.html#_CPPv424ledc_set_duty_and_update11ledc_mode_t14ledc_channel_t8uint32_t8uint32_t // LEDC.channel_group[gr].channel[ch].duty_init.duty = duty << ((!dithering)*4); // C5 LEDC struct uses duty_init, but requires additional steps to activate - // TODO: find out if / how dithering support can be impemented on P5 + // TODO: find out if / how dithering support can be implemented on P4 ledc_set_duty_and_update((ledc_mode_t)gr, (ledc_channel_t)ch, duty >> bitShift, hPoint >> bitShift); #else LEDC.channel_group[gr].channel[ch].duty.duty = duty << ((!dithering)*4); // lowest 4 bits are used for dithering, shift by 4 bits if not using dithering