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/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, diff --git a/platformio.ini b/platformio.ini index 231585ba4d..5bd38789cc 100644 --- a/platformio.ini +++ b/platformio.ini @@ -27,6 +27,8 @@ default_envs = esp32_wrover lolin_s2_mini ;; TODO: disabled NeoEsp32RmtMethodIsr esp32c3dev + esp32c6dev_4MB + esp32c5dev ; esp32s3dev_16MB_opi ;; TODO: disabled NeoEsp32RmtMethodIsr ; esp32s3dev_8MB_opi ;; TODO: disabled NeoEsp32RmtMethodIsr ; esp32s3_4M_qspi ;; TODO: disabled NeoEsp32RmtMethodIsr @@ -169,6 +171,7 @@ upload_speed = 115200 lib_compat_mode = strict lib_deps = fastled/FastLED @ 3.10.1 + ;; https://github.com/softhack007/FastLED.git#ESP32-C6 ;; patched version for -C6 ; IRremoteESP8266 @ 2.8.2 ;; TODO: add back ;; neopixelbus dependancy moved into [8266] and [esp32_all_variants] sections https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.2 @@ -385,6 +388,160 @@ lib_ignore = ${esp32_idf_V5.lib_ignore} board_build.partitions = ${esp32.default_partitions} ;; default partioning for 4MB Flash - can be overridden in build envs 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#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} + 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} +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 + +;; 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 + -DCONFIG_IDF_TARGET_ESP32C6=1 + -D CONFIG_ASYNC_TCP_USE_WDT=0 + -DCO + -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} +lib_deps = + ${esp32_idf_V5.lib_deps} +lib_ignore = ${esp32_idf_V5.lib_ignore} + + +[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 = ${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\" + -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 + -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 ;; 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 = ${esp32c6.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 +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\" + + +[env:esp32c5dev] +;; ESP32-C5 "devkit C" with 4MB flash, no 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 ;; flash config only, this board has no PSRAM + +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_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_DEBUG +lib_ignore = ${esp32c5.lib_ignore} + IRremoteESP8266 + QuickEspNow + +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-devkitc1-n8r4 +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_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 + + [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 7baa796894..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_ESP32S3) +#if defined(CONFIG_IDF_TARGET_ESP32) // analog mic is only supported on classic esp32 static const char _analogmic[]; #endif static const char _digitalmic[]; @@ -1160,7 +1160,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 @@ -1168,15 +1168,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 @@ -1204,7 +1204,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); @@ -1220,7 +1220,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).")); @@ -1797,7 +1797,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 @@ -1856,16 +1856,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 @@ -1903,14 +1903,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);")); @@ -1946,7 +1946,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');")); @@ -2069,7 +2069,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/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.h b/wled00/FX.h index 9c5291665c..b08be49cd4 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_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) + #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/FX_fcn.cpp b/wled00/FX_fcn.cpp index f47a30823f..895d7fc0cf 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(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(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) @@ -1336,8 +1336,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(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] #endif @@ -1347,7 +1347,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(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 fd6ce4c4ed..73cfbcd356 100644 --- a/wled00/FXparticleSystem.cpp +++ b/wled00/FXparticleSystem.cpp @@ -499,7 +499,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(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; @@ -513,7 +513,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(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 @@ -928,7 +928,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(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 @@ -956,7 +956,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(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; @@ -1409,7 +1409,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(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) @@ -1702,7 +1702,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(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; @@ -1723,7 +1723,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(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/NodeStruct.h b/wled00/NodeStruct.h index 9647162054..ba0491373a 100644 --- a/wled00/NodeStruct.h +++ b/wled00/NodeStruct.h @@ -55,4 +55,4 @@ struct NodeStruct }; typedef std::map NodesMap; -#endif // WLED_NODESTRUCT_H +#endif // WLED_NODESTRUCT_H \ No newline at end of file diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index a348b12f73..bcc3a5ea30 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -546,10 +546,20 @@ 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) || 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?). + // 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 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 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 @@ -1142,12 +1152,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(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(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)) { @@ -1248,6 +1258,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_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; unsigned rmt = 0; unsigned u = 0; @@ -1278,6 +1292,7 @@ void BusManager::esp32RMTInvertIdle() { rmt_set_idle_level(ch, idle_out, lvl); u++; } +#endif } #endif diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index 6006a2e601..90a95a26c9 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 ------------------ @@ -249,7 +251,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_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; @@ -465,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 - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #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; @@ -497,14 +499,15 @@ 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(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; } #endif - #if defined(ARDUINO_ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3)) + // ToDO: simplify long ifdef guard + #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 @@ -577,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 - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #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; @@ -676,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 - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #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; @@ -772,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 - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #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; @@ -894,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 - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #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; @@ -991,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 - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #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; @@ -1106,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 - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #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; @@ -1203,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) - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #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; @@ -1282,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) - #ifndef CONFIG_IDF_TARGET_ESP32C3 + #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 @@ -1369,8 +1372,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) - // 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_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) #elif defined(CONFIG_IDF_TARGET_ESP32S3) diff --git a/wled00/button.cpp b/wled00/button.cpp index d544dd73ab..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) + #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 37028130fe..391f6e3692 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -157,9 +157,17 @@ 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); + #if defined(ARDUINO_ARCH_ESP32) && (ESP_IDF_VERSION_MAJOR > 4) + txPower = min(max((int)txPower, (int)WIFI_POWER_2dBm), (int)WIFI_POWER_21dBm); // V5 allows WIFI_POWER_21dBm = 84 ... WIFI_POWER_MINUS_1dBm = -4 + #else + txPower = min(max((int)txPower, (int)WIFI_POWER_2dBm), (int)WIFI_POWER_19_5dBm); + #endif #endif JsonObject hw = doc[F("hw")]; @@ -177,7 +185,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(WLED_HAS_PARALLEL_I2S) CJSON(useParallelI2S, hw_led[F("prl")]); #endif @@ -907,6 +915,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 @@ -947,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) + #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_HAS_PARALLEL_I2S) hw_led[F("prl")] = BusManager::hasParallelOutput(); #endif diff --git a/wled00/const.h b/wled00/const.h index 24ab13c9f6..3ffa8814c1 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -66,7 +66,9 @@ constexpr size_t FIXED_PALETTE_COUNT = DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_C // define -> constexpr to avoid preprocessor errors and enum arithmetic warnings from newer compilers constexpr size_t WLED_MAX_ANALOG_CHANNELS = static_cast(LEDC_CHANNEL_MAX) * static_cast(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_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 #define WLED_MIN_VIRTUAL_BUSSES 4 // no longer used for bus creation but used to distinguish S2/S3 in UI @@ -511,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) + #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 @@ -522,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(ARDUINO_ARCH_ESP32C3) + #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 @@ -640,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) +#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." diff --git a/wled00/data/index.js b/wled00/data/index.js index cd508e8642..14bee01585 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -703,6 +703,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")} diff --git a/wled00/data/settings_wifi.htm b/wled00/data/settings_wifi.htm index c76850cd2e..c4d03dedde 100644 --- a/wled00/data/settings_wifi.htm +++ b/wled00/data/settings_wifi.htm @@ -73,7 +73,7 @@ const option = cE("option"); option.setAttribute("value", networks[i].ssid); - option.textContent = `${networks[i].ssid} (${networks[i].rssi} dBm)`; // [${networks[i].bssid.replaceAll(':','')}] + option.textContent = `${networks[i].ssid} (${networks[i].rssi} dBm, Ch ${networks[i].channel})`; // [${networks[i].bssid.replaceAll(':','')}] if (networks[i].ssid === input.value) { option.setAttribute("selected", "selected"); @@ -250,7 +250,15 @@

Experimental

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

-
Max. TX power: + + + +
+
Max. TX power: