From 12b7a82eac1fa65223c3c4a11fd83b920bdb7f55 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Mon, 1 Jul 2024 08:47:59 -0700 Subject: [PATCH 01/50] Set the ESP32S2 SPI bus in the base env so all S2 based devices get the setting --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 63c641b1b7..e128616d6a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -249,6 +249,7 @@ build_flags = -g -D ARDUINO_ARCH_ESP32 -D ARDUINO_ARCH_ESP32S2 -D FASTLED_ALL_PINS_HARDWARE_SPI + -D FASTLED_ESP32_SPI_BUS=FSPI -D CONFIG_IDF_TARGET_ESP32S2=1 -D CONFIG_ASYNC_TCP_USE_WDT=0 -D ARDUINO_USB_MSC_ON_BOOT=0 -D ARDUINO_USB_DFU_ON_BOOT=0 @@ -612,7 +613,6 @@ build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME= -D HW_PIN_CLOCKSPI=7 -D HW_PIN_DATASPI=11 -D HW_PIN_MISOSPI=9 - -D FASTLED_ESP32_SPI_BUS=FSPI ; -D STATUSLED=15 lib_deps = ${esp32s2.lib_deps} From 4fa3bed66125c6e4647e16251f5d9ac37abd0710 Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Thu, 4 Jul 2024 11:03:29 -0700 Subject: [PATCH 02/50] Revert unintentional changes to upstream --- .vscode/tasks.json | 42 ++++++++++++++++++++++++++++++++++++++++++ wled00/FX_2Dfcn.cpp | 2 ++ wled00/wled_serial.cpp | 1 - 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 .vscode/tasks.json diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000000..2ee772ce16 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,42 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Build: HTML and binary", + "dependsOn": [ + "Build: HTML only", + "Build: binary only" + ], + "dependsOrder": "sequence", + "problemMatcher": [ + "$platformio", + ], + }, + { + "type": "PlatformIO", + "label": "Build: binary only", + "task": "Build", + "group": { + "kind": "build", + "isDefault": true, + }, + "problemMatcher": [ + "$platformio" + ], + "presentation": { + "panel": "shared" + } + }, + { + "type": "npm", + "script": "build", + "group": "build", + "problemMatcher": [], + "label": "Build: HTML only", + "detail": "npm run build", + "presentation": { + "panel": "shared" + } + } + ] +} \ No newline at end of file diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index d96002f1af..5dc9e9ff21 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -198,8 +198,10 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col) uint16_t xX = (x+g), yY = (y+j); if (xX >= width() || yY >= height()) continue; // we have reached one dimension's end +#ifndef WLED_DISABLE_MODE_BLEND // if blending modes, blend with underlying pixel if (_modeBlend) tmpCol = color_blend(strip.getPixelColorXY(start + xX, startY + yY), col, 0xFFFFU - progress(), true); +#endif strip.setPixelColorXY(start + xX, startY + yY, tmpCol); diff --git a/wled00/wled_serial.cpp b/wled00/wled_serial.cpp index d9fa0f4a79..4d920e3406 100644 --- a/wled00/wled_serial.cpp +++ b/wled00/wled_serial.cpp @@ -69,7 +69,6 @@ void sendBytes(){ void handleSerial() { - return; if (pinManager.isPinAllocated(hardwareRX)) return; if (!Serial) return; // arduino docs: `if (Serial)` indicates whether or not the USB CDC serial connection is open. For all non-USB CDC ports, this will always return true From e6405822a8579e26b6c236bff599ab2dd2b0f5d0 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Mon, 8 Jul 2024 09:50:26 -0700 Subject: [PATCH 03/50] fix espnow syncing --- platformio_tubes.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 79e0f0f911..70ac750b3f 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -14,7 +14,6 @@ build_flags = -O2 -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_WEBSOCKETS -D WLED_DISABLE_ADALIGHT - -D WLED_DISABLE_ESPNOW -D IRTYPE=0 lib_ignore = ESPAsyncTCP @@ -46,6 +45,7 @@ build_unflags = build_flags = ${tubes.build_flags} ${env:esp32_quinled_dig2go.build_flags} + -D NUM_STRIPS=1 -D DEFAULT_LED_COUNT=150 lib_ignore = ESPAsyncTCP ESPAsyncUDP From 31dd6ae946c996c5424bcfa4f8d65143b4c81274 Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Thu, 4 Jul 2024 11:31:07 -0700 Subject: [PATCH 04/50] Fix palette size (don't count first 13) --- wled00/const.h | 2 +- wled00/palettes.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/wled00/const.h b/wled00/const.h index f6549c61e3..b493782e90 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -5,7 +5,7 @@ * Readability defines and their associated numerical values + compile-time constants */ -#define GRADIENT_PALETTE_COUNT 128 // custom palette.h +#define GRADIENT_PALETTE_COUNT 116 // custom palette.h //Defaults #define DEFAULT_CLIENT_SSID "Your_Network" diff --git a/wled00/palettes.h b/wled00/palettes.h index 8aab341c50..16f26b87dd 100644 --- a/wled00/palettes.h +++ b/wled00/palettes.h @@ -2408,7 +2408,6 @@ const byte* const gGradientPalettes[] PROGMEM = { */ }; const uint8_t gGradientPaletteCount = ARRAY_SIZE(gGradientPalettes); -#define GRADIENT_PALETTE_COUNT 128 #endif From 24453b5d1d763aa9f058b68003348f2763324005 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Wed, 7 Aug 2024 08:00:31 -0700 Subject: [PATCH 05/50] add esp32-c3-athom device --- platformio_tubes.ini | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 1a0df1fc2a..1d1aa0c233 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -125,3 +125,34 @@ lib_ignore = lib_deps = ${tubes_no_mic.lib_deps} +# ------------------------------------------------------------------------------ +# ESP32 C3 Athom +# ------------------------------------------------------------------------------ +[env:esp32-c3-athom] +extends = env:esp32c3dev +lib_ignore = IRremoteESP8266 + ${env:esp32c3dev.lib_ignore} +build_flags = ${env:esp32c3dev.build_flags} + -D LEDPIN=10 + -D BTNPIN=9 + -D WLED_DISABLE_INFRARED + -D IRTYPE=0 + +[env:esp32-c3-athom_tubes] +extends = env:esp32-c3-athom +platform = ${tubes_no_mic.platform} +platform_packages = ${tubes_no_mic.platform_packages} +build_unflags = ${env:esp32-c3-athom.build_unflags} + ${tubes_no_mic.build_unflags} +build_flags = + ${tubes_no_mic.build_flags} + -D WLED_WATCHDOG_TIMEOUT=0 +; -D LOLIN_WIFI_FIX ; seems to work much better with this + -D LEDPIN=10 + -D BTNPIN=9 + -D FASTLED_ESP32_SPI_BUS=HSPI + -D NUM_STRIPS=1 -D DEFAULT_LED_COUNT=150 +lib_ignore = ${env:esp32-c3-athom.lib_ignore} + ${tubes_no_mic.lib_ignore} +lib_deps = + ${tubes_no_mic.lib_deps} From 8d0218d3c7ad1353a481a805cfc833d0624089cd Mon Sep 17 00:00:00 2001 From: Craig Link Date: Mon, 29 Jul 2024 10:49:11 -0700 Subject: [PATCH 06/50] - reverts platformio.ini to be closer to main branch ini and package versions - standarize tube builds on framework v6.7.0 / 3.20017.0 via platformio_tubes.ini --- platformio.ini | 142 +++++++++++++++++++++++-------------------- platformio_tubes.ini | 95 +++++++++++++++++++++++++---- 2 files changed, 160 insertions(+), 77 deletions(-) diff --git a/platformio.ini b/platformio.ini index e128616d6a..5da7162652 100644 --- a/platformio.ini +++ b/platformio.ini @@ -47,9 +47,8 @@ default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, nodemcuv2_160, esp8266_2m_1 src_dir = ./wled00 data_dir = ./wled00/data build_cache_dir = ~/.buildcache -extra_configs = +extra_configs = platformio_override.ini - ;platformio_tubes.ini [common] # ------------------------------------------------------------------------------ @@ -143,6 +142,7 @@ build_unflags = build_flags_esp8266 = ${common.build_flags} ${esp8266.build_flags} build_flags_esp32 = ${common.build_flags} ${esp32.build_flags} +build_flags_esp32_V4= ${common.build_flags} ${esp32_idf_V4.build_flags} ldscript_1m128k = eagle.flash.1m128.ld ldscript_2m512k = eagle.flash.2m512.ld @@ -177,9 +177,9 @@ upload_speed = 115200 # ------------------------------------------------------------------------------ lib_compat_mode = strict lib_deps = - fastled/FastLED @ 3.7.0 - IRremoteESP8266 @ 2.8.6 - makuna/NeoPixelBus @ 2.7.8 + fastled/FastLED @ 3.6.0 + IRremoteESP8266 @ 2.8.2 + makuna/NeoPixelBus @ 2.7.5 https://github.com/Aircoookie/ESPAsyncWebServer.git @ 2.2.1 #For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line #TFT_eSPI @@ -221,39 +221,62 @@ build_flags = ; -D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED ;; (experimental) adds some extra heap, but may cause slowdown lib_deps = + #https://github.com/lorol/LITTLEFS.git ESPAsyncTCP @ 1.2.2 ESPAsyncUDP ${env.lib_deps} [esp32] -platform = espressif32@6.7.0 -platform_packages = framework-arduinoespressif32 @ 3.20017.0 +#platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.3/platform-espressif32-2.0.2.3.zip +platform = espressif32@3.5.0 +platform_packages = framework-arduinoespressif32 @ https://github.com/Aircoookie/arduino-esp32.git#1.0.6.4 build_flags = -g - -D ARDUINO_ARCH_ESP32 - -D FASTLED_ALL_PINS_HARDWARE_SPI + -DARDUINO_ARCH_ESP32 + #-DCONFIG_LITTLEFS_FOR_IDF_3_2 -D CONFIG_ASYNC_TCP_USE_WDT=0 - -D ARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3 + #use LITTLEFS library by lorol in ESP32 core 1.x.x instead of built-in in 2.x.x + -D LOROL_LITTLEFS + ; -DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3 default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv lib_deps = + https://github.com/lorol/LITTLEFS.git https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 ${env.lib_deps} # additional build flags for audioreactive AR_build_flags = -D USERMOD_AUDIOREACTIVE -D UM_AUDIOREACTIVE_USE_NEW_FFT -AR_lib_deps = https://github.com/kosme/arduinoFFT @ 2.0.2 +AR_lib_deps = https://github.com/kosme/arduinoFFT#419d7b0 + +[esp32_idf_V4] +;; experimental build environment for ESP32 using ESP-IDF 4.4.x / arduino-esp32 v2.0.5 +;; very similar to the normal ESP32 flags, but omitting Lorol LittleFS, as littlefs is included in the new framework already. +;; +;; please note that you can NOT update existing ESP32 installs with a "V4" build. Also updating by OTA will not work properly. +;; You need to completely erase your device (esptool erase_flash) first, then install the "V4" build from VSCode+platformio. +platform = espressif32@5.3.0 +platform_packages = +build_flags = -g + -Wshadow=compatible-local ;; emit warning in case a local variable "shadows" another local one + -DARDUINO_ARCH_ESP32 -DESP32 + #-DCONFIG_LITTLEFS_FOR_IDF_3_2 + -D CONFIG_ASYNC_TCP_USE_WDT=0 + -DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3 +default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv +lib_deps = + https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 + ${env.lib_deps} [esp32s2] ;; generic definitions for all ESP32-S2 boards -platform = ${esp32.platform} -platform_packages = ${esp32.platform_packages} +platform = espressif32@5.3.0 +platform_packages = build_flags = -g - -D ARDUINO_ARCH_ESP32 - -D ARDUINO_ARCH_ESP32S2 - -D FASTLED_ALL_PINS_HARDWARE_SPI - -D FASTLED_ESP32_SPI_BUS=FSPI - -D CONFIG_IDF_TARGET_ESP32S2=1 + -DARDUINO_ARCH_ESP32 + -DARDUINO_ARCH_ESP32S2 + -DCONFIG_IDF_TARGET_ESP32S2=1 -D CONFIG_ASYNC_TCP_USE_WDT=0 - -D ARDUINO_USB_MSC_ON_BOOT=0 -D ARDUINO_USB_DFU_ON_BOOT=0 - -D ARDUINO_USB_MODE=0 ;; this flag is mandatory for ESP32-S2 ! + -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 + -DCO + -DARDUINO_USB_MODE=0 ;; this flag is mandatory for ESP32-S2 ! ;; 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 @@ -263,16 +286,15 @@ lib_deps = [esp32c3] ;; generic definitions for all ESP32-C3 boards -platform = ${esp32.platform} -platform_packages = ${esp32.platform_packages} +platform = espressif32@5.3.0 +platform_packages = build_flags = -g - -D ARDUINO_ARCH_ESP32 - -D ARDUINO_ARCH_ESP32C3 - -D FASTLED_ALL_PINS_HARDWARE_SPI - -D FASTLED_ESP32_SPI_BUS=HSPI - -D CONFIG_IDF_TARGET_ESP32C3=1 + -DARDUINO_ARCH_ESP32 + -DARDUINO_ARCH_ESP32C3 + -DCONFIG_IDF_TARGET_ESP32C3=1 -D CONFIG_ASYNC_TCP_USE_WDT=0 - -D ARDUINO_USB_MODE=1 ;; this flag is mandatory for ESP32-C3 + -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 @@ -282,16 +304,16 @@ lib_deps = [esp32s3] ;; generic definitions for all ESP32-S3 boards -platform = ${esp32.platform} -platform_packages = ${esp32.platform_packages} +platform = espressif32@5.3.0 +platform_packages = build_flags = -g - -D ESP32 - -D ARDUINO_ARCH_ESP32 - -D ARDUINO_ARCH_ESP32S3 - -D FASTLED_ALL_PINS_HARDWARE_SPI - -D CONFIG_IDF_TARGET_ESP32S3=1 + -DESP32 + -DARDUINO_ARCH_ESP32 + -DARDUINO_ARCH_ESP32S3 + -DCONFIG_IDF_TARGET_ESP32S3=1 -D CONFIG_ASYNC_TCP_USE_WDT=0 - -D ARDUINO_USB_MSC_ON_BOOT=0 -D ARDUINO_DFU_ON_BOOT=0 + -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_DFU_ON_BOOT=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 @@ -414,10 +436,9 @@ board_build.partitions = ${esp32.default_partitions} [env:esp32_quinled_diguno] extends = env:esp32dev build_flags = ${env:esp32dev.build_flags} -D RLYPIN=12 -D BTNPIN=0 -D DATA_PINS=16 -D DMTYPE=1 -D I2S_SDPIN=19 -D I2S_WSPIN=4 -D I2S_CKPIN=18 - -D FASTLED_ESP32_SPI_BUS=HSPI - ${esp32.AR_build_flags} + -D USERMOD_AUDIOREACTIVE lib_deps = ${env:esp32dev.lib_deps} - ${esp32.AR_lib_deps} + https://github.com/blazoncek/arduinoFFT.git upload_speed = 690000 board_build.f_flash = 80000000L board_build.flash_mode = qio @@ -434,6 +455,21 @@ board_build.partitions = ${esp32.default_partitions} board_build.f_flash = 80000000L board_build.flash_mode = qio +[env:esp32dev_V4_dio80] +;; experimental ESP32 env using ESP-IDF V4.4.x +;; Warning: this build environment is not stable!! +;; please erase your device before installing. +board = esp32dev +platform = ${esp32_idf_V4.platform} +platform_packages = ${esp32_idf_V4.platform_packages} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=ESP32_V4_qio80 #-D WLED_DISABLE_BROWNOUT_DET +lib_deps = ${esp32_idf_V4.lib_deps} +monitor_filters = esp32_exception_decoder +board_build.partitions = ${esp32_idf_V4.default_partitions} +board_build.f_flash = 80000000L +board_build.flash_mode = dio + [env:esp32_eth] board = esp32-poe platform = ${esp32.platform} @@ -483,7 +519,7 @@ platform_packages = ${esp32s3.platform_packages} upload_speed = 921600 ; or 460800 build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_8MB - -D WLED_WATCHDOG_TIMEOUT=0 + -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 -D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip ;-D ARDUINO_USB_CDC_ON_BOOT=1 ;; -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") ;-D WLED_DEBUG @@ -503,7 +539,7 @@ platform_packages = ${esp32s3.platform_packages} upload_speed = 921600 build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp32s3.build_flags} - -D WLED_WATCHDOG_TIMEOUT=0 + -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 ;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") ; -D WLED_RELEASE_NAME=ESP32-S3_PSRAM @@ -802,27 +838,3 @@ lib_deps = ${esp32.lib_deps} TFT_eSPI @ ^2.3.70 board_build.partitions = ${esp32.default_partitions} - -# ------------------------------------------------------------------------------ -# ESP32 S3 Matrix M1 -# ------------------------------------------------------------------------------ -[env:esp32-s3-matrix-m1] -extends = env:esp32s3dev_8MB_PSRAM_opi -board_build.arduino.memory_type = qio_qspi ;; use with PSRAM: 2MB or 4MB -board_upload.flash_size = 4MB -board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv -build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=esp32-s3-matrix-m1 - -D CONFIG_ASYNC_TCP_USE_WDT=0 - -D WLED_WATCHDOG_TIMEOUT=0 - -D ARDUINO_USB_CDC_ON_BOOT=1 - -D ARDUINO_USB_MODE=1 - ;-D WLED_USE_PSRAM - -D BOARD_HAS_PSRAM ; tells WLED that PSRAM shall be used - -D IRTYPE=0 - -D WLED_DISABLE_INFRARED - -D ABL_MILLIAMPS_DEFAULT=250 - -D FASTLED_ALL_PINS_HARDWARE_SPI - -D NUM_STRIPS=1 -D PIXEL_COUNTS=64 -D DEFAULT_LED_COUNT=64 - -D DEFAULT_LED_COLOR_ORDER=1 -D LEDPIN=14 -lib_deps = ${esp32s3.lib_deps} -lib_ignore = IRremoteESP8266 \ No newline at end of file diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 70ac750b3f..049d5d78be 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -1,9 +1,23 @@ [tubes_no_mic] -build_flags = -O2 +; these settings create a basic template for tubes build from +; from which all other tube envs should build +; the base build does not support +; -- mic (audio reactive) +; -- ir remotes +; For devices with those inputs use the [tubes] settings +; which adds those back in +platform = espressif32@6.7.0 +platform_packages = framework-arduinoespressif32 @ 3.20017.0 +build_unflags = + -D LOROL_LITTLEFS +build_flags = + -g + -O2 + -D FASTLED_ALL_PINS_HARDWARE_SPI + -D ARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3 -D CONFIG_ASYNC_TCP_USE_WDT=0 -D WLED_WATCHDOG_TIMEOUT=0 -D USERMOD_TUBES - ;-D USERMOD_TUBES_DISABLE_ESPNOW ; Disable a bunch of unnecessary integrations -D WLED_DISABLE_BLYNK -D WLED_DISABLE_MQTT @@ -14,43 +28,100 @@ build_flags = -O2 -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_WEBSOCKETS -D WLED_DISABLE_ADALIGHT + -D WLED_DISABLE_ESPNOW -D IRTYPE=0 lib_ignore = ESPAsyncTCP ESPAsyncUDP IRremoteESP8266 lib_deps = + fastled/FastLED @ ^3.7.0 + makuna/NeoPixelBus @ ^2.7.8 + https://github.com/Aircoookie/ESPAsyncWebServer.git @ 2.2.1 gmag11/QuickEspNow @ ^0.6.2 gmag11/QuickDebug @ ^0.7.0 [tubes] extends = tubes_no_mic -build_flags = ${tubes_no_mic.build_flags} - ${esp32.AR_build_flags} +build_flags = + ${tubes_no_mic.build_flags} + ${esp32.AR_build_flags} lib_deps = ${tubes_no_mic.lib_deps} - ${esp32.AR_lib_deps} + IRremoteESP8266 @ ^2.8.6 + https://github.com/kosme/arduinoFFT @ 2.0.2 ; ${esp32.AR_LIB_deps} + [env:esp32_quinled_dig2go] +; basis quinled dig2go without any tubes support extends = env:esp32_quinled_diguno -lib_ignore = - ${env:esp32_quinled_diguno.lib_ignore} +build_unflags = ${env:esp32_quinled_diguno.build_unflags} + -D WLED_DISABLE_INFRARED + -D IRTYPE +lib_ignore = ${env:esp32_quinled_diguno.lib_ignore} lib_deps = ${env:esp32_quinled_diguno.lib_deps} IRremoteESP8266 @ 2.8.6 [env:esp32_quinled_dig2go_tubes] extends = env:esp32_quinled_dig2go +platform = ${tubes.platform} +platform_packages = ${tubes.platform_packages} build_unflags = - -D WLED_DISABLE_INFRARED - -D IRTYPE=0 + ${tubes.build_unflags} + ${env:esp32_quinled_dig2go} build_flags = ${tubes.build_flags} ${env:esp32_quinled_dig2go.build_flags} + -D FASTLED_ESP32_SPI_BUS=HSPI -D NUM_STRIPS=1 -D DEFAULT_LED_COUNT=150 lib_ignore = - ESPAsyncTCP - ESPAsyncUDP + ${tubes.lib_ignore} + ${env:esp32_quinled_dig2go.lib_ignore} lib_deps = ${tubes.lib_deps} - ${env:esp32_quinled_dig2go.lib_deps} + IRremoteESP8266 @ 2.8.6 + +# ------------------------------------------------------------------------------ +# ESP32 S3 Matrix M1 +# ------------------------------------------------------------------------------ +[env:esp32-s3-matrix-m1] +; builds using the default WLED settings +extends = env:esp32s3dev_8MB_PSRAM_opi +board_build.arduino.memory_type = qio_qspi ;; use with PSRAM: 2MB or 4MB +board_upload.flash_size = 4MB +board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv +build_unflags = ${env:esp32s3dev_8MB_PSRAM_opi.build_unflags} + -D ARDUINO_USB_CDC_ON_BOOT=1 + -D ARDUINO_USB_MSC_ON_BOOT=0 + -D ARDUINO_DFU_ON_BOOT=0 +build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=esp32-s3-matrix-m1 + -D WLED_WATCHDOG_TIMEOUT=0 + -D ARDUINO_USB_CDC_ON_BOOT=1 + -D ARDUINO_USB_MODE=1 + -D BOARD_HAS_PSRAM ; tells WLED that PSRAM shall be used + -D ABL_MILLIAMPS_DEFAULT=250 + -D NUM_STRIPS=1 -D PIXEL_COUNTS=64 -D DEFAULT_LED_COUNT=64 + -D DEFAULT_LED_COLOR_ORDER=1 -D LEDPIN=14 +lib_deps = ${esp32s3.lib_deps} +;lib_ignore = IRremoteESP8266 + +[env:esp32-s3-matrix-m1_tubes] +extends = env:esp32-s3-matrix-m1 +platform = ${tubes.platform} +platform_packages = ${tubes.platform_packages} +board_build.partitions = tools/WLED_ESP32_4MB_noOTA.csv +build_unflags = ${env:esp32-s3-matrix-m1.build_unflags} + ${tubes_no_mic.build_unflags} + -D CONFIG_ASYNC_TCP_USE_WDT=0 +build_flags = + ${tubes_no_mic.build_flags} + ${env:esp32-s3-matrix-m1.build_flags} + -D IRTYPE=0 + -D FASTLED_ALL_PINS_HARDWARE_SPI +lib_ignore = + ${tubes_no_mic.lib_ignore} + ${env:esp32-s3-matrix-m1.lib_ignore} +lib_deps = + ${tubes_no_mic.lib_deps} + From 8421a04d4915b684be917ff2b35a4993b578fc07 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Mon, 8 Jul 2024 10:00:26 -0700 Subject: [PATCH 07/50] Revert "revert change to later espressif platform and FastLED 3.7" This reverts commit e2964a496f000b042f9a0a3f895bf97e57a6847a. --- platformio.ini | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/platformio.ini b/platformio.ini index 990b35e8aa..e128616d6a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -177,7 +177,7 @@ upload_speed = 115200 # ------------------------------------------------------------------------------ lib_compat_mode = strict lib_deps = - fastled/FastLED @ 3.6.0 + fastled/FastLED @ 3.7.0 IRremoteESP8266 @ 2.8.6 makuna/NeoPixelBus @ 2.7.8 https://github.com/Aircoookie/ESPAsyncWebServer.git @ 2.2.1 @@ -226,19 +226,15 @@ lib_deps = ${env.lib_deps} [esp32] -#platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.3/platform-espressif32-2.0.2.3.zip -platform = espressif32@3.5.0 -platform_packages = framework-arduinoespressif32 @ https://github.com/Aircoookie/arduino-esp32.git#1.0.6.4 +platform = espressif32@6.7.0 +platform_packages = framework-arduinoespressif32 @ 3.20017.0 build_flags = -g -D ARDUINO_ARCH_ESP32 -D FASTLED_ALL_PINS_HARDWARE_SPI -D CONFIG_ASYNC_TCP_USE_WDT=0 - #use LITTLEFS library by lorol in ESP32 core 1.x.x instead of built-in in 2.x.x - -D LOROL_LITTLEFS - ; -D ARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv + -D ARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3 default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv lib_deps = - https://github.com/lorol/LITTLEFS.git https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 ${env.lib_deps} # additional build flags for audioreactive @@ -247,8 +243,8 @@ AR_lib_deps = https://github.com/kosme/arduinoFFT @ 2.0.2 [esp32s2] ;; generic definitions for all ESP32-S2 boards -platform = espressif32@5.3.0 -platform_packages = +platform = ${esp32.platform} +platform_packages = ${esp32.platform_packages} build_flags = -g -D ARDUINO_ARCH_ESP32 -D ARDUINO_ARCH_ESP32S2 @@ -267,8 +263,8 @@ lib_deps = [esp32c3] ;; generic definitions for all ESP32-C3 boards -platform = espressif32@5.3.0 -platform_packages = +platform = ${esp32.platform} +platform_packages = ${esp32.platform_packages} build_flags = -g -D ARDUINO_ARCH_ESP32 -D ARDUINO_ARCH_ESP32C3 @@ -286,8 +282,8 @@ lib_deps = [esp32s3] ;; generic definitions for all ESP32-S3 boards -platform = espressif32@5.3.0 -platform_packages = +platform = ${esp32.platform} +platform_packages = ${esp32.platform_packages} build_flags = -g -D ESP32 -D ARDUINO_ARCH_ESP32 From 8cba07c91141701f55bc9f6a4ee9736defdcf48f Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Thu, 4 Jul 2024 14:31:19 -0700 Subject: [PATCH 08/50] revert change to later espressif platform and FastLED 3.7 --- platformio.ini | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/platformio.ini b/platformio.ini index e128616d6a..990b35e8aa 100644 --- a/platformio.ini +++ b/platformio.ini @@ -177,7 +177,7 @@ upload_speed = 115200 # ------------------------------------------------------------------------------ lib_compat_mode = strict lib_deps = - fastled/FastLED @ 3.7.0 + fastled/FastLED @ 3.6.0 IRremoteESP8266 @ 2.8.6 makuna/NeoPixelBus @ 2.7.8 https://github.com/Aircoookie/ESPAsyncWebServer.git @ 2.2.1 @@ -226,15 +226,19 @@ lib_deps = ${env.lib_deps} [esp32] -platform = espressif32@6.7.0 -platform_packages = framework-arduinoespressif32 @ 3.20017.0 +#platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.3/platform-espressif32-2.0.2.3.zip +platform = espressif32@3.5.0 +platform_packages = framework-arduinoespressif32 @ https://github.com/Aircoookie/arduino-esp32.git#1.0.6.4 build_flags = -g -D ARDUINO_ARCH_ESP32 -D FASTLED_ALL_PINS_HARDWARE_SPI -D CONFIG_ASYNC_TCP_USE_WDT=0 - -D ARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3 + #use LITTLEFS library by lorol in ESP32 core 1.x.x instead of built-in in 2.x.x + -D LOROL_LITTLEFS + ; -D ARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv lib_deps = + https://github.com/lorol/LITTLEFS.git https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 ${env.lib_deps} # additional build flags for audioreactive @@ -243,8 +247,8 @@ AR_lib_deps = https://github.com/kosme/arduinoFFT @ 2.0.2 [esp32s2] ;; generic definitions for all ESP32-S2 boards -platform = ${esp32.platform} -platform_packages = ${esp32.platform_packages} +platform = espressif32@5.3.0 +platform_packages = build_flags = -g -D ARDUINO_ARCH_ESP32 -D ARDUINO_ARCH_ESP32S2 @@ -263,8 +267,8 @@ lib_deps = [esp32c3] ;; generic definitions for all ESP32-C3 boards -platform = ${esp32.platform} -platform_packages = ${esp32.platform_packages} +platform = espressif32@5.3.0 +platform_packages = build_flags = -g -D ARDUINO_ARCH_ESP32 -D ARDUINO_ARCH_ESP32C3 @@ -282,8 +286,8 @@ lib_deps = [esp32s3] ;; generic definitions for all ESP32-S3 boards -platform = ${esp32.platform} -platform_packages = ${esp32.platform_packages} +platform = espressif32@5.3.0 +platform_packages = build_flags = -g -D ESP32 -D ARDUINO_ARCH_ESP32 From 9b55c6f0cd120b38062e74b9fb9a57f68a21da34 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Mon, 29 Jul 2024 12:29:05 -0700 Subject: [PATCH 09/50] Simple Cleanup - fix function naming convention in node.h - encapuslate some of the callback functions within the LightNode class - defined packing to ensure standard packets on the network - move status_code() function to LightNode class --- usermods/Tubes/controller.h | 12 ++-- usermods/Tubes/debug.h | 15 +---- usermods/Tubes/node.h | 126 ++++++++++++++++++++---------------- 3 files changed, 79 insertions(+), 74 deletions(-) diff --git a/usermods/Tubes/controller.h b/usermods/Tubes/controller.h index b431c10dd8..d4d7338a02 100644 --- a/usermods/Tubes/controller.h +++ b/usermods/Tubes/controller.h @@ -406,7 +406,7 @@ class PatternController : public MessageReceiver { // Update current status if (updateTimer.every(STATUS_UPDATE_PERIOD)) { // Transmit less often when following - if (!node->is_following() || random(0, 4) == 0) { + if (!node->isFollowing() || random(0, 4) == 0) { send_update(); } } @@ -524,7 +524,7 @@ class PatternController : public MessageReceiver { if (new_bpm == 0) new_bpm = current_state.bpm>>8 >= 123 ? 120<<8 : 125<<8; - if (node->is_following()) { + if (node->isFollowing()) { // Send a request up to ROOT broadcast_bpm(new_bpm); } else { @@ -792,7 +792,7 @@ class PatternController : public MessageReceiver { load_options(options); // The master controls all followers - if (!node->is_following()) + if (!node->isFollowing()) broadcast_options(); } @@ -803,7 +803,7 @@ class PatternController : public MessageReceiver { load_options(options); // The master controls all followers - if (!node->is_following()) + if (!node->isFollowing()) broadcast_options(); } @@ -1126,7 +1126,7 @@ class PatternController : public MessageReceiver { } void broadcast_action(Action& action) { - if (!node->is_following()) { + if (!node->isFollowing()) { onAction(&action); } node->sendCommand(COMMAND_ACTION, &action, sizeof(Action)); @@ -1311,7 +1311,7 @@ class PatternController : public MessageReceiver { } virtual bool onButton(uint8_t button_id) { - bool isMaster = !this->node->is_following(); + bool isMaster = !this->node->isFollowing(); switch (button_id) { case WIZMOTE_BUTTON_ON: diff --git a/usermods/Tubes/debug.h b/usermods/Tubes/debug.h index 3b61224ecc..ef7fbbdd62 100644 --- a/usermods/Tubes/debug.h +++ b/usermods/Tubes/debug.h @@ -42,19 +42,6 @@ class DebugController { lastFrame = (uint32_t)-1; } - std::string status_code(NodeStatus status) { - switch (status) { - case NODE_STATUS_QUIET: - return std::string(" (quiet)"); - case NODE_STATUS_STARTING: - return std::string(" (starting)"); - case NODE_STATUS_STARTED: - return std::string(""); - default: - return std::string("??"); - } - } - void update() { EVERY_N_MILLISECONDS( 10000 ) { @@ -63,7 +50,7 @@ class DebugController { auto knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP(); Serial.printf("\n=== %s%s WiFi[ch%d] %s IP: %u.%u.%u.%u Free memory: %d space: %u/%u Uptime: %s\n", controller->node->node_name, - status_code(controller->node->status).c_str(), + controller->node->status_code(), WiFi.channel(), knownSsid.c_str(), knownIp[0], diff --git a/usermods/Tubes/node.h b/usermods/Tubes/node.h index fcb3717be7..14c9a1708f 100644 --- a/usermods/Tubes/node.h +++ b/usermods/Tubes/node.h @@ -25,6 +25,10 @@ #define REBROADCAST_TIME 30000 // Time at which followers are presumed re-uplinked #define WIFI_CHECK_RATE 2000 // Time at which we should check wifi status again +#pragma pack(push,4) // set packing for consist transport across network +// ideally this would have been pack 1, so we're actually wasting a +// number of bytes across the network, but we've already shipped... + typedef uint16_t MeshId; typedef struct { @@ -49,13 +53,13 @@ typedef struct { byte data[MESSAGE_DATA_SIZE] = {0}; } NodeMessage; +#pragma pack(pop) + typedef struct { uint8_t status; char message[40]; } NodeInfo; -void onDataReceived (uint8_t* address, uint8_t* data, uint8_t len, signed int rssi, bool broadcast); - const char *command_name(CommandId command) { switch (command) { case COMMAND_STATE: @@ -85,21 +89,33 @@ class MessageReceiver { } }; -typedef enum{ - NODE_STATUS_QUIET=0, - NODE_STATUS_STARTING=1, - NODE_STATUS_STARTED=2, -} NodeStatus; - - class LightNode { public: static LightNode* instance; MessageReceiver *receiver; MeshNodeHeader header; + + typedef enum{ + NODE_STATUS_QUIET=0, + NODE_STATUS_STARTING=1, + NODE_STATUS_STARTED=2, + } NodeStatus; NodeStatus status = NODE_STATUS_QUIET; + PGM_P status_code() { + switch (status) { + case NODE_STATUS_QUIET: + return PSTR(" (quiet)"); + case NODE_STATUS_STARTING: + return PSTR(" (starting)"); + case NODE_STATUS_STARTED: + return PSTR(""); + default: + return PSTR("??"); + } + } + char node_name[20]; Timer statusTimer; // Use this timer to initialize and check wifi status @@ -138,10 +154,10 @@ class LightNode { header.id, header.uplinkId ); - configure_ap(); + configuredAP(); } - void configure_ap() { + void configuredAP() { #ifdef DEFAULT_WIFI strcpy(clientSSID, DEFAULT_WIFI); strcpy(clientPass, DEFAULT_WIFI_PASSWORD); @@ -195,7 +211,7 @@ class LightNode { } } - void print_message(NodeMessage* message, signed int rssi) { + void printMessage(NodeMessage* message, signed int rssi) { Serial.printf("%03X/%03X %s", message->header.id, message->header.uplinkId, @@ -217,7 +233,7 @@ class LightNode { if (message->header.version != header.version) { #ifdef NODE_DEBUGGING Serial.print(" -- !version "); - print_message(message, rssi); + printMessage(message, rssi); Serial.println(); #endif return; @@ -251,16 +267,16 @@ class LightNode { if (ignore) { #ifdef NODE_DEBUGGING Serial.print(" -- ignored "); - print_message(message, rssi); + printMessage(message, rssi); Serial.println(); #endif return; } // Execute the received command - if (message->recipients != RECIPIENTS_ROOT || !is_following()) { + if (message->recipients != RECIPIENTS_ROOT || !isFollowing()) { Serial.print(" >> "); - print_message(message, rssi); + printMessage(message, rssi); Serial.print(" "); // Adjust the timebase to match uplink @@ -284,7 +300,7 @@ class LightNode { // Re-broadcast the message if appropriate if (!rebroadcastTimer.ended() && message->recipients != RECIPIENTS_INFO) { message->header = header; - if (!is_following()) + if (!isFollowing()) message->recipients = RECIPIENTS_ALL; broadcastMessage(message, true); } @@ -298,7 +314,7 @@ class LightNode { #ifdef NODE_DEBUGGING Serial.print(" <<< "); - print_message(message, 0); + printMessage(message, 0); Serial.println(); #endif @@ -323,7 +339,7 @@ class LightNode { message.recipients = RECIPIENTS_INFO; } else if (command == COMMAND_STATE) { message.recipients = RECIPIENTS_ALL; - } else if (is_following()) { + } else if (isFollowing()) { // Follower nodes must request that the root re-sends this message message.recipients = RECIPIENTS_ROOT; } else { @@ -348,7 +364,7 @@ class LightNode { void update() { // Check the last time we heard from the uplink node - if (is_following() && uplinkTimer.ended()) { + if (isFollowing() && uplinkTimer.ended()) { follow(NULL); } @@ -367,8 +383,9 @@ class LightNode { } void reset(MeshId id = 0) { - if (id == 0) + if (id == 0) { id = random(256, 4000); // Leave room at bottom and top of 12 bits + } header.id = id; follow(NULL); } @@ -398,42 +415,43 @@ class LightNode { onMeshChange(); } - bool is_following() { + bool isFollowing() { return header.uplinkId != 0; } -}; -typedef struct wizmote_message { - uint8_t program; // 0x91 for ON button, 0x81 for all others - uint8_t seq[4]; // Incremetal sequence number 32 bit unsigned integer LSB first - uint8_t byte5 = 32; // Unknown - uint8_t button; // Identifies which button is being pressed - uint8_t byte8 = 1; // Unknown, but always 0x01 - uint8_t byte9 = 100; // Unnkown, but always 0x64 - - uint8_t byte10; // Unknown, maybe checksum - uint8_t byte11; // Unknown, maybe checksum - uint8_t byte12; // Unknown, maybe checksum - uint8_t byte13; // Unknown, maybe checksum -} wizmote_message; - -void onWizmote(uint8_t* address, wizmote_message* data, uint8_t len) { - // First make sure this is a WizMote message. - if (len != sizeof(wizmote_message) || data->byte8 != 1 || data->byte9 != 100 || data->byte5 != 32) - return; - - static uint32_t last_seq = 0; - uint32_t cur_seq = data->seq[0] | (data->seq[1] << 8) | (data->seq[2] << 16) | (data->seq[3] << 24); - if (cur_seq == last_seq) - return; - last_seq = cur_seq; - - LightNode::instance->receiver->onButton(data->button); -} + typedef struct wizmote_message { + uint8_t program; // 0x91 for ON button, 0x81 for all others + uint8_t seq[4]; // Incremetal sequence number 32 bit unsigned integer LSB first + uint8_t byte5 = 32; // Unknown + uint8_t button; // Identifies which button is being pressed + uint8_t byte8 = 1; // Unknown, but always 0x01 + uint8_t byte9 = 100; // Unnkown, but always 0x64 + + uint8_t byte10; // Unknown, maybe checksum + uint8_t byte11; // Unknown, maybe checksum + uint8_t byte12; // Unknown, maybe checksum + uint8_t byte13; // Unknown, maybe checksum + } wizmote_message; + + static void onWizmote(uint8_t* address, wizmote_message* data, uint8_t len) { + // First make sure this is a WizMote message. + if (len != sizeof(wizmote_message) || data->byte8 != 1 || data->byte9 != 100 || data->byte5 != 32) + return; + + static uint32_t last_seq = 0; + uint32_t cur_seq = data->seq[0] | (data->seq[1] << 8) | (data->seq[2] << 16) | (data->seq[3] << 24); + if (cur_seq == last_seq) + return; + last_seq = cur_seq; + + instance->receiver->onButton(data->button); + } + + static void onDataReceived(uint8_t* address, uint8_t* data, uint8_t len, signed int rssi, bool broadcast) { + instance->onPeerData(address, data, len, rssi, broadcast); + onWizmote(address, (wizmote_message*)data, len); + } +}; LightNode* LightNode::instance = nullptr; -void onDataReceived(uint8_t* address, uint8_t* data, uint8_t len, signed int rssi, bool broadcast) { - LightNode::instance->onPeerData(address, data, len, rssi, broadcast); - onWizmote(address, (wizmote_message*)data, len); -} From cfce2e2d0950d04af5aee8a9180a7001d5d71ffb Mon Sep 17 00:00:00 2001 From: Craig Link Date: Mon, 29 Jul 2024 12:07:53 -0700 Subject: [PATCH 10/50] fix a few dependencies between variations --- platformio_tubes.ini | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 049d5d78be..d57940a1fc 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -10,14 +10,15 @@ platform = espressif32@6.7.0 platform_packages = framework-arduinoespressif32 @ 3.20017.0 build_unflags = -D LOROL_LITTLEFS + -D CONFIG_ASYNC_TCP_USE_WDT build_flags = -g -O2 -D FASTLED_ALL_PINS_HARDWARE_SPI -D ARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3 - -D CONFIG_ASYNC_TCP_USE_WDT=0 -D WLED_WATCHDOG_TIMEOUT=0 -D USERMOD_TUBES + -D CONFIG_ASYNC_TCP_RUNNING_CORE=-1 ; Disable a bunch of unnecessary integrations -D WLED_DISABLE_BLYNK -D WLED_DISABLE_MQTT @@ -74,11 +75,11 @@ build_flags = -D FASTLED_ESP32_SPI_BUS=HSPI -D NUM_STRIPS=1 -D DEFAULT_LED_COUNT=150 lib_ignore = - ${tubes.lib_ignore} + ESPAsyncTCP + ESPAsyncUDP ${env:esp32_quinled_dig2go.lib_ignore} lib_deps = ${tubes.lib_deps} - IRremoteESP8266 @ 2.8.6 @@ -104,7 +105,8 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME= -D NUM_STRIPS=1 -D PIXEL_COUNTS=64 -D DEFAULT_LED_COUNT=64 -D DEFAULT_LED_COLOR_ORDER=1 -D LEDPIN=14 lib_deps = ${esp32s3.lib_deps} -;lib_ignore = IRremoteESP8266 +lib_ignore = ${env:esp32s3dev_8MB_PSRAM_opi.lib_ignore} + IRremoteESP8266 [env:esp32-s3-matrix-m1_tubes] extends = env:esp32-s3-matrix-m1 @@ -113,7 +115,6 @@ platform_packages = ${tubes.platform_packages} board_build.partitions = tools/WLED_ESP32_4MB_noOTA.csv build_unflags = ${env:esp32-s3-matrix-m1.build_unflags} ${tubes_no_mic.build_unflags} - -D CONFIG_ASYNC_TCP_USE_WDT=0 build_flags = ${tubes_no_mic.build_flags} ${env:esp32-s3-matrix-m1.build_flags} From 3956dfa4feb145cc1cdaf2e31261c63855cb8877 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Mon, 29 Jul 2024 12:32:53 -0700 Subject: [PATCH 11/50] add class protections to LightNode --- usermods/Tubes/node.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/usermods/Tubes/node.h b/usermods/Tubes/node.h index 14c9a1708f..45983bfa1d 100644 --- a/usermods/Tubes/node.h +++ b/usermods/Tubes/node.h @@ -126,6 +126,7 @@ class LightNode { LightNode::instance = this; } +protected: void onWifiConnect() { if (status == NODE_STATUS_QUIET) return; @@ -326,6 +327,8 @@ class LightNode { Serial.printf(" *** Broadcast error %d\n", err); } +public: + void sendCommand(CommandId command, void *data, uint8_t len) { if (len > MESSAGE_DATA_SIZE) { Serial.printf("Message is too big: %d vs %d\n", @@ -419,6 +422,7 @@ class LightNode { return header.uplinkId != 0; } +protected: typedef struct wizmote_message { uint8_t program; // 0x91 for ON button, 0x81 for all others uint8_t seq[4]; // Incremetal sequence number 32 bit unsigned integer LSB first From 446fa23209845e1e6244ac1cebe0b37bae3bb391 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Fri, 9 Aug 2024 09:07:22 -0700 Subject: [PATCH 12/50] fix some silly bugs during port. - statusTimer should just end verses being reset on "every" - only update global timer once - bad code: len < sizeof(WLED_MAX_DATA_LEN) - remove sizeof() - set WiFi power in ESPNOWBroadcast by new macro --- platformio_tubes.ini | 2 +- usermods/Tubes/Tubes.h | 2 ++ usermods/Tubes/beats.h | 4 ---- usermods/Tubes/node.h | 22 ++++++++++++---------- wled00/espnow_broadcast.cpp | 37 ++++++++++++++++++++++++++++--------- 5 files changed, 43 insertions(+), 24 deletions(-) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 1d1aa0c233..d4363790de 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -147,7 +147,7 @@ build_unflags = ${env:esp32-c3-athom.build_unflags} build_flags = ${tubes_no_mic.build_flags} -D WLED_WATCHDOG_TIMEOUT=0 -; -D LOLIN_WIFI_FIX ; seems to work much better with this + ;-D LOLIN_WIFI_FIX ; seems to work much better with this -D LEDPIN=10 -D BTNPIN=9 -D FASTLED_ESP32_SPI_BUS=HSPI diff --git a/usermods/Tubes/Tubes.h b/usermods/Tubes/Tubes.h index 42aba85315..1483347016 100644 --- a/usermods/Tubes/Tubes.h +++ b/usermods/Tubes/Tubes.h @@ -74,6 +74,8 @@ class TubesUsermod : public Usermod { randomize(); } + globalTimer.update(); + if (master) master->update(); beats.update(); diff --git a/usermods/Tubes/beats.h b/usermods/Tubes/beats.h index c60e6b1b5e..d540ef46b5 100644 --- a/usermods/Tubes/beats.h +++ b/usermods/Tubes/beats.h @@ -16,16 +16,12 @@ class BeatController { void setup() { - globalTimer.setup(); - // Starts in phrase 1 sync(DEFAULT_BPM << 8, 0); } void update() { - globalTimer.update(); - // Maintains an accumulator with 14 bits of precision accum += globalTimer.delta_micros << 8; while (accum > micros_per_frac) { diff --git a/usermods/Tubes/node.h b/usermods/Tubes/node.h index 33cb71ab09..7ad6a72d38 100644 --- a/usermods/Tubes/node.h +++ b/usermods/Tubes/node.h @@ -96,7 +96,7 @@ class LightNode { case NODE_STATUS_RECEIVING: return PSTR(" (receiving)"); case NODE_STATUS_STARTED: - return PSTR(""); + return PSTR(" (started)"); default: return PSTR("??"); } @@ -110,9 +110,9 @@ class LightNode { protected: - const uint32_t STATUS_CHECK_RATE = 200; // Time at which we should check wifi status again - const uint32_t UPLINK_TIMEOUT = 20000; // Time at which uplink is presumed lost - const uint32_t REBROADCAST_TIME = 30000; // Time at which followers are presumed re-uplinked + const uint32_t STATUS_TIMEOUT_BASE = 3000; // Base time to wait to send broadcasts + const uint32_t UPLINK_TIMEOUT = 20000; // Time at which uplink is presumed lost + const uint32_t REBROADCAST_TIME = 30000; // Time at which followers are presumed re-uplinked Timer statusTimer; // Use this timer to initialize and check wifi status Timer uplinkTimer; // When this timer ends, assume uplink is lost. @@ -276,9 +276,12 @@ class LightNode { void broadcastMessage(NodeMessage *message, bool is_rebroadcast=false) { // Don't broadcast anything if this node isn't active. +#ifdef NODE_DEBUGGING + Serial.printf("broadcastMessage() - %s %s\n", status_code(), statusTimer.ended() ? "True" : "False"); +#endif if (status != NODE_STATUS_STARTED) { - if (status == NODE_STATUS_RECEIVING && statusTimer.every(STATUS_CHECK_RATE)) { + if (status == NODE_STATUS_RECEIVING && statusTimer.ended()) { status = NODE_STATUS_STARTED; statusTimer.stop(); Serial.printf("LightNode %s\n", status_code()); @@ -295,11 +298,10 @@ class LightNode { Serial.println(); #endif - __attribute__((unused)) auto err = espnowBroadcast.send((const uint8_t*)message, sizeof(*message)); - + __attribute__((unused)) auto success = espnowBroadcast.send((const uint8_t*)message, sizeof(*message)); #ifdef NODE_DEBUGGING - if (err != ESP_OK) { - Serial.printf("espnowBroadcast.send() failed: %d\n", err); + if (!success) { + Serial.println("espnowBroadcast.send() failed!"); } else { Serial.println("successful broadcast"); } @@ -429,7 +431,7 @@ class LightNode { if (NODE_STATUS_QUIET == status) { Serial.printf("checkESPNowState() - %d node_status:%s\n", state, status_code()); status = NODE_STATUS_RECEIVING; - statusTimer.start(3000 - header.id / 2); + statusTimer.start(STATUS_TIMEOUT_BASE - header.id / 2); Serial.printf("LightNode %s\n", status_code()); } break; diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index 860370b374..1a27296966 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -32,11 +32,15 @@ ESP_EVENT_DEFINE_BASE(SYSTEM_EVENT); #define WIFI_EVENT_AP_START SYSTEM_EVENT_AP_START #endif -//#define ESPNOW_DEBUGGING +// #define ESPNOW_DEBUGGING #define BROADCAST_ADDR_ARRAY_INITIALIZER {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} #define WLED_ESPNOW_WIFI_CHANNEL 1 +#ifndef WLED_WIFI_POWER_SETTING +#define WLED_WIFI_POWER_SETTING WIFI_POWER_15dBm +#endif + typedef struct { uint8_t mac[6]; uint8_t len; @@ -206,9 +210,15 @@ void ESPNOWBroadcast::loop(size_t maxMessagesToProcess /*= 1*/) { bool ESPNOWBroadcast::send(const uint8_t* msg, size_t len) { #ifdef ESP32 static const uint8_t broadcast[] = BROADCAST_ADDR_ARRAY_INITIALIZER; - return ESP_OK == esp_now_send(broadcast, msg, len); + auto err = esp_now_send(broadcast, msg, len); +#ifdef ESPNOW_DEBUGGING + if (ESP_OK != err) { + Serial.printf( "esp_now_send() failed %d\n", err); + } +#endif + return ESP_OK == err; #else - return false; + return false; #endif } @@ -250,6 +260,10 @@ void ESPNOWBroadcastImpl::start() { auto status = WiFi.status(); if ( status >= WL_DISCONNECTED ) { if (esp_wifi_start() == ESP_OK) { + if (!WiFi.setTxPower(WLED_WIFI_POWER_SETTING)) { + auto power = WiFi.getTxPower(); + Serial.printf("setTxPower(%d) failed. getTX: %d\n", WLED_WIFI_POWER_SETTING, power); + } if (esp_now_init() == ESP_OK) { if (esp_now_register_recv_cb(ESPNOWBroadcastImpl::onESPNowRxCallback) == ESP_OK) { static esp_now_peer_info_t peer = { @@ -264,6 +278,9 @@ void ESPNOWBroadcastImpl::start() { if (esp_now_add_peer(&peer) == ESP_OK) { ESPNOWBroadcast::STATE starting {ESPNOWBroadcast::STARTING}; if (_state.compare_exchange_strong(starting, ESPNOWBroadcast::STARTED)) { +#ifdef ESPNOW_DEBUGGING + Serial.println("ESPNOWBroadcast started :)"); +#endif return; } else { #ifdef ESPNOW_DEBUGGING @@ -389,14 +406,16 @@ void ESPNOWBroadcastImpl::onESPNowRxCallback(const uint8_t *mac, const uint8_t * // logMACAddr(mac); // Serial.printf( " %d:bytes rssi:%d\n", len, rssi); - if (!espnowBroadcastImpl.queuedNetworkRingBuffer.push(mac, data, len, rssi)) { - if (len > sizeof(WLED_ESPNOW_MAX_MESSAGE_LENGTH)) { + if (len > WLED_ESPNOW_MAX_MESSAGE_LENGTH) { #ifdef ESPNOW_DEBUGGING - Serial.printf("Receive to large of packet %d bytes. ignoring...\n", len); + Serial.printf("Receive to large of packet %d > %d bytes. ignoring...\n", len, WLED_ESPNOW_MAX_MESSAGE_LENGTH); +#endif + } else if (!espnowBroadcastImpl.queuedNetworkRingBuffer.push(mac, data, len, rssi)) { + Serial.println("Failed to aquire ring buffer. Dropping network message"); + } else { +#ifdef ESPNOW_DEBUGGING + Serial.printf("Receive %d bytes. RSSI %d\n", len, rssi); #endif - } else { - Serial.println("Failed to aquire ring buffer. Dropping network message"); - } } } From 53bb7e8d3b6c28f024a5ee4fcc502260071f172b Mon Sep 17 00:00:00 2001 From: Craig Link Date: Fri, 9 Aug 2024 09:10:18 -0700 Subject: [PATCH 13/50] remove unused build flag --- platformio_tubes.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index d4363790de..75d8d20f6b 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -147,7 +147,6 @@ build_unflags = ${env:esp32-c3-athom.build_unflags} build_flags = ${tubes_no_mic.build_flags} -D WLED_WATCHDOG_TIMEOUT=0 - ;-D LOLIN_WIFI_FIX ; seems to work much better with this -D LEDPIN=10 -D BTNPIN=9 -D FASTLED_ESP32_SPI_BUS=HSPI From ee20e07f2273f78433ce308940c72a6711f0397f Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Wed, 31 Jul 2024 00:09:06 -0700 Subject: [PATCH 14/50] actually use PSRAM --- platformio_tubes.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index d57940a1fc..2aa3886f1f 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -101,6 +101,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME= -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 -D BOARD_HAS_PSRAM ; tells WLED that PSRAM shall be used + -D WLED_USE_PSRAM -D ABL_MILLIAMPS_DEFAULT=250 -D NUM_STRIPS=1 -D PIXEL_COUNTS=64 -D DEFAULT_LED_COUNT=64 -D DEFAULT_LED_COLOR_ORDER=1 -D LEDPIN=14 From fe4807596c922c2a51c2c9c8ee596df1bb3493c9 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Fri, 9 Aug 2024 09:21:32 -0700 Subject: [PATCH 15/50] clean up RX callback --- wled00/espnow_broadcast.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index 1a27296966..85dadef747 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -402,19 +402,14 @@ void ESPNOWBroadcastImpl::onESPNowRxCallback(const uint8_t *mac, const uint8_t * // be safe about accessing memory that isn't directly exposed to the callback rssi = 0; } - // Serial.printf( "RX from " ); - // logMACAddr(mac); - // Serial.printf( " %d:bytes rssi:%d\n", len, rssi); - if (len > WLED_ESPNOW_MAX_MESSAGE_LENGTH) { -#ifdef ESPNOW_DEBUGGING - Serial.printf("Receive to large of packet %d > %d bytes. ignoring...\n", len, WLED_ESPNOW_MAX_MESSAGE_LENGTH); -#endif - } else if (!espnowBroadcastImpl.queuedNetworkRingBuffer.push(mac, data, len, rssi)) { - Serial.println("Failed to aquire ring buffer. Dropping network message"); + if (!espnowBroadcastImpl.queuedNetworkRingBuffer.push(mac, data, len, rssi)) { + Serial.printf("Failed to queue message (%d bytes) to ring buffer. Dropping message\n", len); } else { #ifdef ESPNOW_DEBUGGING - Serial.printf("Receive %d bytes. RSSI %d\n", len, rssi); + Serial.printf("Received %d bytes from "); + logMACAddr(mac); + Serial.printf(" RSSI %d\n", len, rssi); #endif } } From a522febed4530c30b978f9499c92b3cb55a4014e Mon Sep 17 00:00:00 2001 From: Craig Link Date: Fri, 2 Aug 2024 16:54:38 -0700 Subject: [PATCH 16/50] add RSSI support back for modern IDF builds --- usermods/Tubes/node.h | 4 +-- wled00/espnow_broadcast.cpp | 53 ++++++++++++++++++++++++++++++++++--- wled00/espnow_broadcast.h | 2 +- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/usermods/Tubes/node.h b/usermods/Tubes/node.h index 5260b3a2a6..33cb71ab09 100644 --- a/usermods/Tubes/node.h +++ b/usermods/Tubes/node.h @@ -467,10 +467,10 @@ class LightNode { receiver->onButton(data->button); } - static void onEspNowMessage(const uint8_t *address, const uint8_t *msg, uint8_t len) { + static void onEspNowMessage(const uint8_t *address, const uint8_t *msg, uint8_t len, int8_t rssi) { if (msg) { if(len == sizeof(NodeMessage)) { - instance->onPeerData(address, (const NodeMessage*)msg, len, 0, true); + instance->onPeerData(address, (const NodeMessage*)msg, len, rssi, true); instance->onWizmote(address, (const wizmote_message*)msg, len); } else { #ifdef NODE_DEBUGGING diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index 543aa6524d..860370b374 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -40,8 +40,10 @@ ESP_EVENT_DEFINE_BASE(SYSTEM_EVENT); typedef struct { uint8_t mac[6]; uint8_t len; + int8_t rssi; uint8_t data[WLED_ESPNOW_MAX_MESSAGE_LENGTH]; } QueuedNetworkMessage; +static_assert(sizeof(QueuedNetworkMessage) == WLED_ESPNOW_MAX_MESSAGE_LENGTH+8, "QueuedNetworkMessage larger than needed"); static_assert(WLED_ESPNOW_MAX_MESSAGE_LENGTH <= ESP_NOW_MAX_DATA_LEN, "WLED_ESPNOW_MAX_MESSAGE_LENGTH must be <= 250 bytes"); @@ -74,7 +76,7 @@ class ESPNOWBroadcastImpl : public ESPNOWBroadcast { buf = xRingbufferCreateNoSplit(sizeof(QueuedNetworkMessage), WLED_ESPNOW_MAX_QUEUED_MESSAGES); } - bool push(const uint8_t* mac, const uint8_t* data, uint8_t len); + bool push(const uint8_t* mac, const uint8_t* data, uint8_t len, int8_t rssi); QueuedNetworkMessage* pop() { size_t size = 0; @@ -185,7 +187,7 @@ void ESPNOWBroadcast::loop(size_t maxMessagesToProcess /*= 1*/) { if (msg) { auto callback = _rxCallbacks; while( *callback ) { - (*callback)(msg->mac, msg->data, msg->len); + (*callback)(msg->mac, msg->data, msg->len, msg->rssi); callback++; } espnowBroadcastImpl.queuedNetworkRingBuffer.popComplete(msg); @@ -345,8 +347,49 @@ void ESPNOWBroadcastImpl::onWiFiEvent(void* arg, esp_event_base_t event_base, in } } +typedef struct { + uint16_t frame_head; + uint16_t duration; + uint8_t destination_address[6]; + uint8_t source_address[6]; + uint8_t broadcast_address[6]; + uint16_t sequence_control; + + uint8_t category_code; + uint8_t organization_identifier[3]; // 0x18fe34 + uint8_t random_values[4]; + struct { + uint8_t element_id; // 0xdd + uint8_t lenght; // + uint8_t organization_identifier[3]; // 0x18fe34 + uint8_t type; // 4 + uint8_t version; + uint8_t body[0]; + } vendor_specific_content; +} __attribute__ ((packed)) espnow_frame_format_t; + +#ifdef ESPNOW_DEBUGGING +void logMACAddr(const uint8_t* mac) { + Serial.printf("%x:%x:%x:%x:%x:%x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] ); +} +#endif + void ESPNOWBroadcastImpl::onESPNowRxCallback(const uint8_t *mac, const uint8_t *data, int len) { - if (!espnowBroadcastImpl.queuedNetworkRingBuffer.push(mac, data, len)) { + //const espnow_frame_format_t* espnow_data = (espnow_frame_format_t*)(data - sizeof (espnow_frame_format_t)); + const wifi_promiscuous_pkt_t* promiscuous_pkt = (wifi_promiscuous_pkt_t*)(data - sizeof (wifi_pkt_rx_ctrl_t) - sizeof (espnow_frame_format_t)); + int8_t rssi = 0; + try { + auto rssi32 = promiscuous_pkt->rx_ctrl.rssi; + rssi = rssi32 <= -128 ? -127 : rssi32 > 0 ? 0 : rssi32; + } catch(...) { + // be safe about accessing memory that isn't directly exposed to the callback + rssi = 0; + } + // Serial.printf( "RX from " ); + // logMACAddr(mac); + // Serial.printf( " %d:bytes rssi:%d\n", len, rssi); + + if (!espnowBroadcastImpl.queuedNetworkRingBuffer.push(mac, data, len, rssi)) { if (len > sizeof(WLED_ESPNOW_MAX_MESSAGE_LENGTH)) { #ifdef ESPNOW_DEBUGGING Serial.printf("Receive to large of packet %d bytes. ignoring...\n", len); @@ -357,13 +400,14 @@ void ESPNOWBroadcastImpl::onESPNowRxCallback(const uint8_t *mac, const uint8_t * } } -bool ESPNOWBroadcastImpl::QueuedNetworkRingBuffer::push(const uint8_t* mac, const uint8_t* data, uint8_t len) { +bool ESPNOWBroadcastImpl::QueuedNetworkRingBuffer::push(const uint8_t* mac, const uint8_t* data, uint8_t len, int8_t rssi) { #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0) QueuedNetworkMessage msg[1]; if (len <= sizeof(msg->data)) { memcpy(msg->mac, mac, sizeof(msg->mac)); memcpy(&(msg->data), data, len); msg->len = len; + msg->rssi = rssi; if (pdTRUE == xRingbufferSend(buf, (void**)&msg, sizeof(*msg), 0)) { return true; @@ -377,6 +421,7 @@ bool ESPNOWBroadcastImpl::QueuedNetworkRingBuffer::push(const uint8_t* mac, cons memcpy(msg->mac, mac, sizeof(msg->mac)); memcpy(&(msg->data), data, len); msg->len = len; + msg->rssi = rssi; xRingbufferSendComplete(buf, msg); return true; } diff --git a/wled00/espnow_broadcast.h b/wled00/espnow_broadcast.h index 05dd490300..ae23b9ee3c 100644 --- a/wled00/espnow_broadcast.h +++ b/wled00/espnow_broadcast.h @@ -27,7 +27,7 @@ class ESPNOWBroadcast { bool send(const uint8_t* msg, size_t len); - typedef void (*receive_callback_t)(const uint8_t *sender, const uint8_t *data, uint8_t len); + typedef void (*receive_callback_t)(const uint8_t *sender, const uint8_t *data, uint8_t len, int8_t rssi); bool registerCallback( receive_callback_t callback ); bool removeCallback( receive_callback_t callback ); From 247cd2b303b65a451972096ce7c76854cfae54eb Mon Sep 17 00:00:00 2001 From: Craig Link <278699+craiglink@users.noreply.github.com> Date: Fri, 2 Aug 2024 12:34:21 -0700 Subject: [PATCH 17/50] Rewrites the ESPNow code to use the IDF esp_now api vs QuickEspNow. (#30) This rewrites the ESPNow code to use the IDF esp_now api vs QuickEspNow. Additionally the WiFi / ESPNow code paths trigger based on WiFi events vs pooling at calls to Wifi.Disconnect() create a race condition. To eliminate other potential race conditions by events called from the WiFi task, a ESP32 RingBuffers are used to shared Wifi events and network messages with the main application task, reducing the risk of a race condition --- platformio_tubes.ini | 6 +- usermods/Tubes/controller.h | 3 +- usermods/Tubes/node.h | 269 ++++++++++++++----------- wled00/espnow_broadcast.cpp | 390 ++++++++++++++++++++++++++++++++++++ wled00/espnow_broadcast.h | 50 +++++ wled00/wled.cpp | 9 + 6 files changed, 600 insertions(+), 127 deletions(-) create mode 100644 wled00/espnow_broadcast.cpp create mode 100644 wled00/espnow_broadcast.h diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 2aa3886f1f..1a0df1fc2a 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -6,8 +6,8 @@ ; -- ir remotes ; For devices with those inputs use the [tubes] settings ; which adds those back in -platform = espressif32@6.7.0 -platform_packages = framework-arduinoespressif32 @ 3.20017.0 +platform = espressif32@6.8.1 +platform_packages = ;framework-arduinoespressif32 @ 3.20017.0 build_unflags = -D LOROL_LITTLEFS -D CONFIG_ASYNC_TCP_USE_WDT @@ -39,8 +39,6 @@ lib_deps = fastled/FastLED @ ^3.7.0 makuna/NeoPixelBus @ ^2.7.8 https://github.com/Aircoookie/ESPAsyncWebServer.git @ 2.2.1 - gmag11/QuickEspNow @ ^0.6.2 - gmag11/QuickDebug @ ^0.7.0 [tubes] extends = tubes_no_mic diff --git a/usermods/Tubes/controller.h b/usermods/Tubes/controller.h index d4d7338a02..dc24e0cb4a 100644 --- a/usermods/Tubes/controller.h +++ b/usermods/Tubes/controller.h @@ -173,7 +173,6 @@ class PatternController : public MessageReceiver { void setup() { - node->setup(); EEPROM.begin(EEPSIZE); role = (ControllerRole)EEPROM.read(ROLE_EEPROM_LOCATION); if (role == 255) { @@ -205,6 +204,8 @@ class PatternController : public MessageReceiver { else strip.ablMilliampsMax = 1400; + node->setup(); + if (role >= MasterRole) { node->reset(3850 + role); // MASTER ID options.brightness = DEFAULT_MASTER_BRIGHTNESS; diff --git a/usermods/Tubes/node.h b/usermods/Tubes/node.h index 45983bfa1d..5260b3a2a6 100644 --- a/usermods/Tubes/node.h +++ b/usermods/Tubes/node.h @@ -1,34 +1,25 @@ #pragma once #include -#if defined ESP32 -#include -#include -#elif defined ESP8266 -#include -#define WIFI_MODE_STA WIFI_STA -#else -#error "Unsupported platform" -#endif //ESP32 -#include - #include "global_state.h" +#include "espnow_broadcast.h" // #define NODE_DEBUGGING // #define RELAY_DEBUGGING #define TESTING_NODE_ID 0 #define CURRENT_NODE_VERSION 2 -#define BROADCAST_ADDR ESPNOW_BROADCAST_ADDRESS - -#define UPLINK_TIMEOUT 20000 // Time at which uplink is presumed lost -#define REBROADCAST_TIME 30000 // Time at which followers are presumed re-uplinked -#define WIFI_CHECK_RATE 2000 // Time at which we should check wifi status again #pragma pack(push,4) // set packing for consist transport across network // ideally this would have been pack 1, so we're actually wasting a // number of bytes across the network, but we've already shipped... +typedef enum{ + RECIPIENTS_ALL=0, // Send to all neighbors; non-followers will ignore + RECIPIENTS_ROOT=1, // Send to root for rebroadcasting downward, all will see + RECIPIENTS_INFO=2, // Send to all neighbors "FYI"; none will ignore +} MessageRecipients; + typedef uint16_t MeshId; typedef struct { @@ -37,14 +28,7 @@ typedef struct { uint8_t version = CURRENT_NODE_VERSION; } MeshNodeHeader; -typedef enum{ - RECIPIENTS_ALL=0, // Send to all neighbors; non-followers will ignore - RECIPIENTS_ROOT=1, // Send to root for rebroadcasting downward, all will see - RECIPIENTS_INFO=2, // Send to all neighbors "FYI"; none will ignore -} MessageRecipients; - #define MESSAGE_DATA_SIZE 64 - typedef struct { MeshNodeHeader header; MessageRecipients recipients; @@ -60,6 +44,7 @@ typedef struct { char message[40]; } NodeInfo; + const char *command_name(CommandId command) { switch (command) { case COMMAND_STATE: @@ -98,8 +83,9 @@ class LightNode { typedef enum{ NODE_STATUS_QUIET=0, - NODE_STATUS_STARTING=1, - NODE_STATUS_STARTED=2, + NODE_STATUS_RECEIVING, + NODE_STATUS_STARTED, + NODE_STATUS_MAX, } NodeStatus; NodeStatus status = NODE_STATUS_QUIET; @@ -107,8 +93,8 @@ class LightNode { switch (status) { case NODE_STATUS_QUIET: return PSTR(" (quiet)"); - case NODE_STATUS_STARTING: - return PSTR(" (starting)"); + case NODE_STATUS_RECEIVING: + return PSTR(" (receiving)"); case NODE_STATUS_STARTED: return PSTR(""); default: @@ -118,36 +104,19 @@ class LightNode { char node_name[20]; - Timer statusTimer; // Use this timer to initialize and check wifi status - Timer uplinkTimer; // When this timer ends, assume uplink is lost. - Timer rebroadcastTimer; // Until this timer ends, re-broadcast messages from uplink - LightNode(MessageReceiver *r) : receiver(r) { - LightNode::instance = this; + instance = this; } -protected: - void onWifiConnect() { - if (status == NODE_STATUS_QUIET) - return; - - Serial.println("WiFi connected: stop broadcasting"); - quickEspNow.stop(); - status = NODE_STATUS_QUIET; - rebroadcastTimer.stop(); - statusTimer.start(WIFI_CHECK_RATE); - } + protected: - void onWifiDisconnect() { - if (status != NODE_STATUS_QUIET) - return; + const uint32_t STATUS_CHECK_RATE = 200; // Time at which we should check wifi status again + const uint32_t UPLINK_TIMEOUT = 20000; // Time at which uplink is presumed lost + const uint32_t REBROADCAST_TIME = 30000; // Time at which followers are presumed re-uplinked - Serial.println("WiFi disconnected: start broadcasting"); - WiFi.mode (WIFI_MODE_STA); - WiFi.disconnect(false, true); - quickEspNow.begin(1, WIFI_IF_STA); - start(); - } + Timer statusTimer; // Use this timer to initialize and check wifi status + Timer uplinkTimer; // When this timer ends, assume uplink is lost. + Timer rebroadcastTimer; // Until this timer ends, re-broadcast messages from uplink void onMeshChange() { sprintf(node_name, @@ -155,10 +124,11 @@ class LightNode { header.id, header.uplinkId ); - configuredAP(); + + configureAP(); } - void configuredAP() { + void configureAP() { #ifdef DEFAULT_WIFI strcpy(clientSSID, DEFAULT_WIFI); strcpy(clientPass, DEFAULT_WIFI_PASSWORD); @@ -172,47 +142,39 @@ class LightNode { apBehavior = AP_BEHAVIOR_BUTTON_ONLY; // Must press button for 6 seconds to get AP } - void start() { - // Initialization timer: wait for a bit before trying to broadcast. - // If this node's ID is high, it's more likely to be the leader, so wait less. - status = NODE_STATUS_STARTING; - statusTimer.start(3000 - header.id / 2); - rebroadcastTimer.stop(); - } - - void onPeerPing(MeshNodeHeader* node) { + void onPeerPing(const MeshNodeHeader& node) { // When receiving a message, if the IDs match, it's a conflict // Reset to create a new ID. - if (node->id == header.id) { + if (node.id == header.id) { Serial.println("Detected an ID conflict."); reset(); } // If the message arrives from a higher ID, switch into follower mode - if (node->id > header.uplinkId && node->id > header.id) { + if (node.id > header.uplinkId && node.id > header.id) { #ifdef RELAY_DEBUGGING // When debugging relay, pretend not to see any nodes above 0x800 if (node->id < 0x800) #endif - follow(node); + follow(&node); } // If the message arrived from our uplink, track that we're still linked. - if (node->id == header.uplinkId) { + if (node.id == header.uplinkId) { uplinkTimer.start(UPLINK_TIMEOUT); } // If a message indicates that another node is following this one, or // should be (it's not following anything, but this node's ID is higher) // enter or continue re-broadcasting mode. - if (node->uplinkId == header.id - || (node->uplinkId == 0 && node->id < header.id)) { - Serial.printf(" %03X/%03X is following me\n", node->id, node->uplinkId); + if (node.uplinkId == header.id + || (node.uplinkId == 0 && node.id < header.id)) { + Serial.printf(" %03X/%03X is following me", node.id, node.uplinkId); rebroadcastTimer.start(REBROADCAST_TIME); } } - void printMessage(NodeMessage* message, signed int rssi) { + void printMessage(const NodeMessage* message, signed int rssi) { Serial.printf("%03X/%03X %s", message->header.id, message->header.uplinkId, @@ -224,12 +186,11 @@ class LightNode { Serial.printf(" %ddB ", rssi); } - void onPeerData(uint8_t* address, uint8_t* data, uint8_t len, signed int rssi, bool broadcast) { + void onPeerData(const uint8_t* address, const NodeMessage* message, uint8_t len, signed int rssi, bool broadcast) { // Ignore this message if it isn't a valid message payload. - if (len != sizeof(NodeMessage)) + if (len != sizeof(*message)) return; - NodeMessage* message = (NodeMessage*)data; // Ignore this message if it's the wrong version. if (message->header.version != header.version) { #ifdef NODE_DEBUGGING @@ -241,7 +202,7 @@ class LightNode { } // Track that another node exists, updating this node's understanding of the mesh. - onPeerPing(&message->header); + onPeerPing(message->header); bool ignore = false; switch (message->recipients) { @@ -290,7 +251,7 @@ class LightNode { // Execute the command auto valid = receiver->onCommand( message->command, - &message->data + const_cast(message->data) ); Serial.println(); @@ -300,17 +261,32 @@ class LightNode { // Re-broadcast the message if appropriate if (!rebroadcastTimer.ended() && message->recipients != RECIPIENTS_INFO) { - message->header = header; - if (!isFollowing()) - message->recipients = RECIPIENTS_ALL; - broadcastMessage(message, true); + static NodeMessage msg; + memcpy(&msg, &message, len); + msg.header = header; + if (!isFollowing()) { + msg.recipients = RECIPIENTS_ALL; + } +#ifdef NODE_DEBUGGING + Serial.println("rebroadcast"); +#endif + broadcastMessage(&msg, true); } } void broadcastMessage(NodeMessage *message, bool is_rebroadcast=false) { // Don't broadcast anything if this node isn't active. - if (status != NODE_STATUS_STARTED) - return; + + if (status != NODE_STATUS_STARTED) { + if (status == NODE_STATUS_RECEIVING && statusTimer.every(STATUS_CHECK_RATE)) { + status = NODE_STATUS_STARTED; + statusTimer.stop(); + Serial.printf("LightNode %s\n", status_code()); + } else { + Serial.printf("broadcastMessage() - not started - %s\n", status_code()); + return; + } + } message->timebase = strip.timebase + millis(); #ifdef NODE_DEBUGGING @@ -319,17 +295,25 @@ class LightNode { Serial.println(); #endif - auto err = quickEspNow.send( - ESPNOW_BROADCAST_ADDRESS, - (uint8_t*)message, sizeof(*message) - ); - if (err) - Serial.printf(" *** Broadcast error %d\n", err); + __attribute__((unused)) auto err = espnowBroadcast.send((const uint8_t*)message, sizeof(*message)); + +#ifdef NODE_DEBUGGING + if (err != ESP_OK) { + Serial.printf("espnowBroadcast.send() failed: %d\n", err); + } else { + Serial.println("successful broadcast"); + } +#endif + } -public: + public: void sendCommand(CommandId command, void *data, uint8_t len) { + // if (!ESP_NOW.isStarted()) { + // Serial.println("SendCommand ESP Not Started!"); + // return; + // } if (len > MESSAGE_DATA_SIZE) { Serial.printf("Message is too big: %d vs %d\n", len, MESSAGE_DATA_SIZE); @@ -350,6 +334,9 @@ class LightNode { } message.command = command; memcpy(&message.data, data, len); +#ifdef NODE_DEBUGGING + Serial.println("sendCommand"); +#endif broadcastMessage(&message); } @@ -359,30 +346,27 @@ class LightNode { #else reset(); #endif - statusTimer.stop(); - quickEspNow.onDataRcvd(onDataReceived); - Serial.println("Mesh: ok"); + +#ifdef NODE_DEBUGGING + delay(2000); +#endif + + espnowBroadcast.registerCallback(onEspNowMessage); + + Serial.println("setup: ok"); } void update() { + + //process any wifi events to turn on/off ESPNode + checkESPNowState(); + // Check the last time we heard from the uplink node if (isFollowing() && uplinkTimer.ended()) { follow(NULL); } - if (statusTimer.every(WIFI_CHECK_RATE)) { - // The broadcast timer doubles as a timer for startup delay - // Once the initial timer has ended, mark this node as started - if (status == NODE_STATUS_STARTING) - status = NODE_STATUS_STARTED; - - // Check WiFi status and update node status if wifi changed - if (WiFi.isConnected()) - onWifiConnect(); - else - onWifiDisconnect(); - } } void reset(MeshId id = 0) { @@ -393,7 +377,7 @@ class LightNode { follow(NULL); } - void follow(MeshNodeHeader* node) { + void follow(const MeshNodeHeader* node) { if (node == NULL) { if (header.uplinkId != 0) { Serial.println("Uplink lost"); @@ -422,22 +406,54 @@ class LightNode { return header.uplinkId != 0; } -protected: +protected: + + void checkESPNowState() { + auto state = espnowBroadcast.getState(); + static auto prev = espnowBroadcast.STOPPED; + switch(state) { + case ESPNOWBroadcast::STOPPED: + if (NODE_STATUS_QUIET != status) { + Serial.printf("checkESPNowState() - %d node_status:%s\n", state, status_code()); + status = NODE_STATUS_QUIET; + rebroadcastTimer.stop(); + Serial.printf("LightNode %s\n", status_code()); + } + break; + case ESPNOWBroadcast::STARTING: {} + if ( state != prev ) { + Serial.printf("checkESPNowState() - %d node_status:%s\n", state, status_code()); + } + break; + case ESPNOWBroadcast::STARTED: + if (NODE_STATUS_QUIET == status) { + Serial.printf("checkESPNowState() - %d node_status:%s\n", state, status_code()); + status = NODE_STATUS_RECEIVING; + statusTimer.start(3000 - header.id / 2); + Serial.printf("LightNode %s\n", status_code()); + } + break; + default: + break; + } + prev = state; + } + typedef struct wizmote_message { - uint8_t program; // 0x91 for ON button, 0x81 for all others - uint8_t seq[4]; // Incremetal sequence number 32 bit unsigned integer LSB first - uint8_t byte5 = 32; // Unknown - uint8_t button; // Identifies which button is being pressed - uint8_t byte8 = 1; // Unknown, but always 0x01 - uint8_t byte9 = 100; // Unnkown, but always 0x64 - - uint8_t byte10; // Unknown, maybe checksum - uint8_t byte11; // Unknown, maybe checksum - uint8_t byte12; // Unknown, maybe checksum - uint8_t byte13; // Unknown, maybe checksum + uint8_t program; // 0x91 for ON button, 0x81 for all others + uint8_t seq[4]; // Incremetal sequence number 32 bit unsigned integer LSB first + uint8_t byte5 = 32; // Unknown + uint8_t button; // Identifies which button is being pressed + uint8_t byte8 = 1; // Unknown, but always 0x01 + uint8_t byte9 = 100; // Unnkown, but always 0x64 + + uint8_t byte10; // Unknown, maybe checksum + uint8_t byte11; // Unknown, maybe checksum + uint8_t byte12; // Unknown, maybe checksum + uint8_t byte13; // Unknown, maybe checksum } wizmote_message; - static void onWizmote(uint8_t* address, wizmote_message* data, uint8_t len) { + void onWizmote(const uint8_t* address, const wizmote_message* data, uint8_t len) { // First make sure this is a WizMote message. if (len != sizeof(wizmote_message) || data->byte8 != 1 || data->byte9 != 100 || data->byte5 != 32) return; @@ -448,13 +464,22 @@ class LightNode { return; last_seq = cur_seq; - instance->receiver->onButton(data->button); + receiver->onButton(data->button); } - static void onDataReceived(uint8_t* address, uint8_t* data, uint8_t len, signed int rssi, bool broadcast) { - instance->onPeerData(address, data, len, rssi, broadcast); - onWizmote(address, (wizmote_message*)data, len); + static void onEspNowMessage(const uint8_t *address, const uint8_t *msg, uint8_t len) { + if (msg) { + if(len == sizeof(NodeMessage)) { + instance->onPeerData(address, (const NodeMessage*)msg, len, 0, true); + instance->onWizmote(address, (const wizmote_message*)msg, len); + } else { +#ifdef NODE_DEBUGGING + Serial.printf("wrong size QueueNodeMessage received %d\n", len); +#endif + } + } } + }; LightNode* LightNode::instance = nullptr; diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp new file mode 100644 index 0000000000..543aa6524d --- /dev/null +++ b/wled00/espnow_broadcast.cpp @@ -0,0 +1,390 @@ + +#ifndef WLED_DISABLE_ESPNOW_NEW +#include +#include + +#if defined ESP32 +#include +#include +#include + +#elif defined ESP8266 +#include +#define WIFI_MODE_STA WIFI_STA +#else +#error "Unsupported platform" +#endif //ESP32 + +#include "espnow_broadcast.h" + +#ifdef ESP32 + +#include +#include +#include + +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0) +// Legacy Event Loop +ESP_EVENT_DEFINE_BASE(SYSTEM_EVENT); +#define WIFI_EVENT SYSTEM_EVENT +#define WIFI_EVENT_STA_START SYSTEM_EVENT_STA_START +#define WIFI_EVENT_STA_STOP SYSTEM_EVENT_STA_STOP +#define WIFI_EVENT_AP_START SYSTEM_EVENT_AP_START +#endif + +//#define ESPNOW_DEBUGGING + +#define BROADCAST_ADDR_ARRAY_INITIALIZER {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} +#define WLED_ESPNOW_WIFI_CHANNEL 1 + +typedef struct { + uint8_t mac[6]; + uint8_t len; + uint8_t data[WLED_ESPNOW_MAX_MESSAGE_LENGTH]; +} QueuedNetworkMessage; +static_assert(WLED_ESPNOW_MAX_MESSAGE_LENGTH <= ESP_NOW_MAX_DATA_LEN, "WLED_ESPNOW_MAX_MESSAGE_LENGTH must be <= 250 bytes"); + + +class ESPNOWBroadcastImpl : public ESPNOWBroadcast { + + friend ESPNOWBroadcast; + + std::atomic _state {STOPPED}; + STATE getState() { + return _state.load(); + } + + bool setupWiFi(); + + void start(); + + static esp_err_t onSystemEvent(void *ctx, system_event_t *event); + + static void onWiFiEvent(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data); + + static void onESPNowRxCallback(const uint8_t *mac_addr, const uint8_t *data, int len); + + class QueuedNetworkRingBuffer { + protected: + //QueuedNetworkMessage messages[WLED_ESPNOW_MAX_QUEUED_MESSAGES]; + RingbufHandle_t buf = nullptr; + + public: + QueuedNetworkRingBuffer() { + buf = xRingbufferCreateNoSplit(sizeof(QueuedNetworkMessage), WLED_ESPNOW_MAX_QUEUED_MESSAGES); + } + + bool push(const uint8_t* mac, const uint8_t* data, uint8_t len); + + QueuedNetworkMessage* pop() { + size_t size = 0; + return (QueuedNetworkMessage*)xRingbufferReceive(buf, &size, 0); + } + + void popComplete(QueuedNetworkMessage* msg) { + vRingbufferReturnItem(buf, (void *)msg); + } + }; + + QueuedNetworkRingBuffer queuedNetworkRingBuffer {}; + +}; + +ESPNOWBroadcastImpl espnowBroadcastImpl {}; +#endif // ESP32 + +ESPNOWBroadcast espnowBroadcast {}; + + +ESPNOWBroadcast::STATE ESPNOWBroadcast::getState() { +#ifdef ESP32 + return espnowBroadcastImpl.getState(); +#else + return ESPNOWBroadcast::STOPPED; +#endif +} + +bool ESPNOWBroadcast::setup() { + + static bool setup = false; +#ifdef ESP32 + if (setup) { + return true; + } + + #ifdef ESPNOW_DEBUGGING + delay(2000); + #endif + +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0) + tcpip_adapter_init(); + esp_event_loop_init(ESPNOWBroadcastImpl::onSystemEvent, nullptr); +#else + + auto err = esp_event_loop_create_default(); + if ( ESP_OK != err && ESP_ERR_INVALID_STATE != err ) { + Serial.printf("esp_event_loop_create_default() err %d\n", err); + return false; + } + err = esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_START, ESPNOWBroadcastImpl::onWiFiEvent, nullptr, nullptr); + if ( ESP_OK != err ) { + Serial.printf("esp_event_handler_instance_register(WIFI_EVENT_STA_START) err %d\n", err); + return false; + } + err = esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_STOP, ESPNOWBroadcastImpl::onWiFiEvent, nullptr, nullptr); + if ( ESP_OK != err ) { + Serial.printf("esp_event_handler_instance_register(WIFI_EVENT_STA_STOP) err %d\n", err); + return false; + } + err = esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_AP_START, ESPNOWBroadcastImpl::onWiFiEvent, nullptr, nullptr); + if ( ESP_OK != err ) { + Serial.printf("esp_event_handler_instance_register(WIFI_EVENT_AP_START) err %d\n", err); + return false; + } +#endif + + setup = espnowBroadcastImpl.setupWiFi(); +#endif //ESP32 + return setup; +} + +#ifdef ESP32 +bool ESPNOWBroadcastImpl::setupWiFi() { + Serial.println("ESPNOWBroadcast::setupWiFi()"); + + _state.exchange(STOPPED); + + // To enable ESPNow, we need to be in WIFI_STA mode + if ( !WiFi.mode(WIFI_STA) ) { + Serial.println("WiFi.mode() failed"); + return false; + } + // and not have the WiFi connect + // Calling discount with tigger an async Wifi Event + if ( !WiFi.disconnect(false, true) ) { + Serial.println("WiFi.disconnect() failed"); + return false; + } + + return true; +} +#endif //ESP32 + + +void ESPNOWBroadcast::loop(size_t maxMessagesToProcess /*= 1*/) { +#ifdef ESP32 + switch (espnowBroadcastImpl._state.load()) { + case ESPNOWBroadcast::STARTING: + // if WiFI is in starting state, actually stat ESPNow from our main task thread. + espnowBroadcastImpl.start(); + break; + case ESPNOWBroadcast::STARTED: { + auto ndx = maxMessagesToProcess; + while(ndx-- > 0) { + auto *msg = espnowBroadcastImpl.queuedNetworkRingBuffer.pop(); + if (msg) { + auto callback = _rxCallbacks; + while( *callback ) { + (*callback)(msg->mac, msg->data, msg->len); + callback++; + } + espnowBroadcastImpl.queuedNetworkRingBuffer.popComplete(msg); + } else { + break; + } + } + break; + } + default: + break; + } +#endif // ESP32 +} + +bool ESPNOWBroadcast::send(const uint8_t* msg, size_t len) { +#ifdef ESP32 + static const uint8_t broadcast[] = BROADCAST_ADDR_ARRAY_INITIALIZER; + return ESP_OK == esp_now_send(broadcast, msg, len); +#else + return false; +#endif +} + +bool ESPNOWBroadcast::registerCallback( ESPNOWBroadcast::receive_callback_t callback ) { + // last element is always null + size_t ndx; + for (ndx = 0; ndx < _rxCallbacksSize-1; ndx++) { + if (nullptr == _rxCallbacks[ndx]) { + _rxCallbacks[ndx] = callback; + break; + } + } + return ndx < _rxCallbacksSize; +} + +bool ESPNOWBroadcast::removeCallback( ESPNOWBroadcast::receive_callback_t callback ) { + size_t ndx; + for (ndx = 0; ndx < _rxCallbacksSize-1; ndx++) { + if (_rxCallbacks[ndx] == callback ) { + break; + } + } + + for (; ndx < _rxCallbacksSize-1; ndx++) { + _rxCallbacks[ndx] = _rxCallbacks[ndx+1]; + } + + return ndx < _rxCallbacksSize; + +} + +#ifdef ESP32 + +void ESPNOWBroadcastImpl::start() { + + Serial.println("starting ESPNow"); + + if ( WiFi.mode(WIFI_STA) ) { + auto status = WiFi.status(); + if ( status >= WL_DISCONNECTED ) { + if (esp_wifi_start() == ESP_OK) { + if (esp_now_init() == ESP_OK) { + if (esp_now_register_recv_cb(ESPNOWBroadcastImpl::onESPNowRxCallback) == ESP_OK) { + static esp_now_peer_info_t peer = { + BROADCAST_ADDR_ARRAY_INITIALIZER, + {0}, + WLED_ESPNOW_WIFI_CHANNEL, + WIFI_IF_STA, + false, + NULL + }; + + if (esp_now_add_peer(&peer) == ESP_OK) { + ESPNOWBroadcast::STATE starting {ESPNOWBroadcast::STARTING}; + if (_state.compare_exchange_strong(starting, ESPNOWBroadcast::STARTED)) { + return; + } else { +#ifdef ESPNOW_DEBUGGING + Serial.println("atomic state out of sync"); +#endif + } + } else { +#ifdef ESPNOW_DEBUGGING + Serial.println("esp_now_add_peer failed"); +#endif + } + } else { +#ifdef ESPNOW_DEBUGGING + Serial.println("esp_now_register_recv_cb failed"); +#endif + } + } else { +#ifdef ESPNOW_DEBUGGING + Serial.println("esp_now_init_init failed"); +#endif + } + } else { +#ifdef ESPNOW_DEBUGGING + Serial.println("esp_wifi_start failed"); +#endif + } + } else { +#ifdef ESPNOW_DEBUGGING + Serial.printf("WiFi.status not disconnected - %d\n", status); +#endif + } + } else { +#ifdef ESPNOW_DEBUGGING + Serial.println("WiFi.mode failed"); +#endif + } + Serial.println("restarting ESPNow"); + setupWiFi(); +} + +esp_err_t ESPNOWBroadcastImpl::onSystemEvent(void *ctx, system_event_t *event) { +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0) + onWiFiEvent(ctx, SYSTEM_EVENT, event->event_id, nullptr ); +#endif + return ESP_OK; +} + + +void ESPNOWBroadcastImpl::onWiFiEvent(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { + if ( event_base == WIFI_EVENT ) { + +#ifdef ESPNOW_DEBUGGING + #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0) + Serial.printf("WiFiEvent( %d )\n", event_id ); + #else + Serial.printf("WiFiEvent( %s )\n", WiFi.eventName((arduino_event_id_t)event_id) ); + #endif +#endif + switch (event_id) { + case WIFI_EVENT_STA_START: { + ESPNOWBroadcast::STATE stopped {ESPNOWBroadcast::STOPPED}; + espnowBroadcastImpl._state.compare_exchange_strong(stopped, ESPNOWBroadcast::STARTING); + break; + } + + case WIFI_EVENT_STA_STOP: + case WIFI_EVENT_AP_START: { + ESPNOWBroadcast::STATE started {ESPNOWBroadcast::STARTED}; + ESPNOWBroadcast::STATE starting {ESPNOWBroadcast::STARTING}; + if (espnowBroadcastImpl._state.compare_exchange_strong(started, ESPNOWBroadcast::STOPPED) || + espnowBroadcastImpl._state.compare_exchange_strong(starting, ESPNOWBroadcast::STOPPED)) { +#ifdef ESPNOW_DEBUGGING + Serial.println("WiFi connected: stop broadcasting"); +#endif + esp_now_unregister_recv_cb(); + esp_now_deinit(); + } + break; + } + } + } +} + +void ESPNOWBroadcastImpl::onESPNowRxCallback(const uint8_t *mac, const uint8_t *data, int len) { + if (!espnowBroadcastImpl.queuedNetworkRingBuffer.push(mac, data, len)) { + if (len > sizeof(WLED_ESPNOW_MAX_MESSAGE_LENGTH)) { +#ifdef ESPNOW_DEBUGGING + Serial.printf("Receive to large of packet %d bytes. ignoring...\n", len); +#endif + } else { + Serial.println("Failed to aquire ring buffer. Dropping network message"); + } + } +} + +bool ESPNOWBroadcastImpl::QueuedNetworkRingBuffer::push(const uint8_t* mac, const uint8_t* data, uint8_t len) { +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0) + QueuedNetworkMessage msg[1]; + if (len <= sizeof(msg->data)) { + memcpy(msg->mac, mac, sizeof(msg->mac)); + memcpy(&(msg->data), data, len); + msg->len = len; + + if (pdTRUE == xRingbufferSend(buf, (void**)&msg, sizeof(*msg), 0)) { + return true; + } + } + return false; +#else + QueuedNetworkMessage* msg = nullptr; + if (len <= sizeof(msg->data)) { + if (pdTRUE == xRingbufferSendAcquire(buf, (void**)&msg, sizeof(*msg), 0)) { + memcpy(msg->mac, mac, sizeof(msg->mac)); + memcpy(&(msg->data), data, len); + msg->len = len; + xRingbufferSendComplete(buf, msg); + return true; + } + } + return false; +#endif +} + +#endif // ESP32 + +#endif \ No newline at end of file diff --git a/wled00/espnow_broadcast.h b/wled00/espnow_broadcast.h new file mode 100644 index 0000000000..05dd490300 --- /dev/null +++ b/wled00/espnow_broadcast.h @@ -0,0 +1,50 @@ + +#pragma once + +#ifndef WLED_DISABLE_ESPNOW_NEW + +#include "const.h" + +#ifndef WLED_ESPNOW_MAX_QUEUED_MESSAGES +#define WLED_ESPNOW_MAX_QUEUED_MESSAGES 6 +#endif + +#ifndef WLED_ESPNOW_MAX_MESSAGE_LENGTH +#define WLED_ESPNOW_MAX_MESSAGE_LENGTH 250 +#endif + +#ifndef WLED_ESPNOW_MAX_REGISTERED_CALLBACKS +#define WLED_ESPNOW_MAX_REGISTERED_CALLBACKS WLED_MAX_USERMODS+1 +#endif + +class ESPNOWBroadcast { + + public: + + bool setup(); + + void loop(size_t maxMessagesToProcess = WLED_ESPNOW_MAX_QUEUED_MESSAGES); + + bool send(const uint8_t* msg, size_t len); + + typedef void (*receive_callback_t)(const uint8_t *sender, const uint8_t *data, uint8_t len); + bool registerCallback( receive_callback_t callback ); + bool removeCallback( receive_callback_t callback ); + + enum STATE { + STOPPED = 0, + STARTING, + STARTED, + MAX + }; + + STATE getState(); + + protected: + receive_callback_t _rxCallbacks[WLED_ESPNOW_MAX_REGISTERED_CALLBACKS] = {0}; + static constexpr size_t _rxCallbacksSize = sizeof(_rxCallbacks)/sizeof(_rxCallbacks[0]); + +}; + +extern ESPNOWBroadcast espnowBroadcast; +#endif \ No newline at end of file diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 8ba6b1a565..5c64aa3b46 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -2,6 +2,7 @@ #include "wled.h" #include "wled_ethernet.h" #include +#include "espnow_broadcast.h" #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET) #include "soc/soc.h" @@ -499,6 +500,10 @@ pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), Pin initServer(); DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap()); +#ifndef WLED_DISABLE_ESPNOW_NEW + espnowBroadcast.setup(); +#endif + enableWatchdog(); #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET) @@ -808,6 +813,10 @@ void WLED::handleConnection() return; } +#ifndef WLED_DISABLE_ESPNOW_NEW + espnowBroadcast.loop(); +#endif + // reconnect WiFi to clear stale allocations if heap gets too low if (now - heapTime > 5000) { uint32_t heap = ESP.getFreeHeap(); From f9a3fc8078c9d06b575ea65473302a70f3a2e467 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Fri, 9 Aug 2024 09:39:10 -0700 Subject: [PATCH 18/50] add separate debug flag for rx callback logging --- wled00/espnow_broadcast.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index 85dadef747..946745e16e 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -32,7 +32,8 @@ ESP_EVENT_DEFINE_BASE(SYSTEM_EVENT); #define WIFI_EVENT_AP_START SYSTEM_EVENT_AP_START #endif -// #define ESPNOW_DEBUGGING +//#define ESPNOW_DEBUGGING +//#define ESNOW_CALLBACK_DEBUGGING // Serial is called from multiple threads #define BROADCAST_ADDR_ARRAY_INITIALIZER {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} #define WLED_ESPNOW_WIFI_CHANNEL 1 @@ -385,12 +386,6 @@ typedef struct { } vendor_specific_content; } __attribute__ ((packed)) espnow_frame_format_t; -#ifdef ESPNOW_DEBUGGING -void logMACAddr(const uint8_t* mac) { - Serial.printf("%x:%x:%x:%x:%x:%x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] ); -} -#endif - void ESPNOWBroadcastImpl::onESPNowRxCallback(const uint8_t *mac, const uint8_t *data, int len) { //const espnow_frame_format_t* espnow_data = (espnow_frame_format_t*)(data - sizeof (espnow_frame_format_t)); const wifi_promiscuous_pkt_t* promiscuous_pkt = (wifi_promiscuous_pkt_t*)(data - sizeof (wifi_pkt_rx_ctrl_t) - sizeof (espnow_frame_format_t)); @@ -406,10 +401,13 @@ void ESPNOWBroadcastImpl::onESPNowRxCallback(const uint8_t *mac, const uint8_t * if (!espnowBroadcastImpl.queuedNetworkRingBuffer.push(mac, data, len, rssi)) { Serial.printf("Failed to queue message (%d bytes) to ring buffer. Dropping message\n", len); } else { -#ifdef ESPNOW_DEBUGGING - Serial.printf("Received %d bytes from "); - logMACAddr(mac); - Serial.printf(" RSSI %d\n", len, rssi); +#ifdef ESPNOW_CALLBACK_DEBUGGING + char buf[128]; + sprintf(buf, "Received %d bytes from %x:%x:%x:%x:%x:%x RSSI %d", len, + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + rssi + ); + Serial.println(buf); #endif } } From d59f2f013fe0557dc0ab2ab03afa17247724a2ed Mon Sep 17 00:00:00 2001 From: Craig Link Date: Fri, 9 Aug 2024 09:45:05 -0700 Subject: [PATCH 19/50] remove extra log line --- usermods/Tubes/node.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/usermods/Tubes/node.h b/usermods/Tubes/node.h index 7ad6a72d38..f5362fb0dc 100644 --- a/usermods/Tubes/node.h +++ b/usermods/Tubes/node.h @@ -276,10 +276,6 @@ class LightNode { void broadcastMessage(NodeMessage *message, bool is_rebroadcast=false) { // Don't broadcast anything if this node isn't active. -#ifdef NODE_DEBUGGING - Serial.printf("broadcastMessage() - %s %s\n", status_code(), statusTimer.ended() ? "True" : "False"); -#endif - if (status != NODE_STATUS_STARTED) { if (status == NODE_STATUS_RECEIVING && statusTimer.ended()) { status = NODE_STATUS_STARTED; From deb35f43bd4ddf50fb1daf47467da88aab3e020e Mon Sep 17 00:00:00 2001 From: Craig Link <278699+craiglink@users.noreply.github.com> Date: Wed, 7 Aug 2024 08:01:50 -0700 Subject: [PATCH 20/50] add esp32-c3-athom device (#34) --- platformio_tubes.ini | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 1a0df1fc2a..1d1aa0c233 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -125,3 +125,34 @@ lib_ignore = lib_deps = ${tubes_no_mic.lib_deps} +# ------------------------------------------------------------------------------ +# ESP32 C3 Athom +# ------------------------------------------------------------------------------ +[env:esp32-c3-athom] +extends = env:esp32c3dev +lib_ignore = IRremoteESP8266 + ${env:esp32c3dev.lib_ignore} +build_flags = ${env:esp32c3dev.build_flags} + -D LEDPIN=10 + -D BTNPIN=9 + -D WLED_DISABLE_INFRARED + -D IRTYPE=0 + +[env:esp32-c3-athom_tubes] +extends = env:esp32-c3-athom +platform = ${tubes_no_mic.platform} +platform_packages = ${tubes_no_mic.platform_packages} +build_unflags = ${env:esp32-c3-athom.build_unflags} + ${tubes_no_mic.build_unflags} +build_flags = + ${tubes_no_mic.build_flags} + -D WLED_WATCHDOG_TIMEOUT=0 +; -D LOLIN_WIFI_FIX ; seems to work much better with this + -D LEDPIN=10 + -D BTNPIN=9 + -D FASTLED_ESP32_SPI_BUS=HSPI + -D NUM_STRIPS=1 -D DEFAULT_LED_COUNT=150 +lib_ignore = ${env:esp32-c3-athom.lib_ignore} + ${tubes_no_mic.lib_ignore} +lib_deps = + ${tubes_no_mic.lib_deps} From 568df6ec196391a876656e42875a0d6bc4742551 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Tue, 13 Aug 2024 16:28:49 -0700 Subject: [PATCH 21/50] reduce unnecessary use of heap to create some singleton objects and instead use them by reference and appropraitely used a const reference in the debug class --- usermods/Tubes/Tubes.h | 28 ++++++------ usermods/Tubes/controller.h | 85 +++++++++++++++++++------------------ usermods/Tubes/debug.h | 54 +++++++++++------------ usermods/Tubes/led_strip.h | 2 +- usermods/Tubes/master.h | 16 +++---- usermods/Tubes/node.h | 5 ++- usermods/Tubes/timer.h | 4 +- 7 files changed, 93 insertions(+), 101 deletions(-) diff --git a/usermods/Tubes/Tubes.h b/usermods/Tubes/Tubes.h index 1483347016..1b4b4214be 100644 --- a/usermods/Tubes/Tubes.h +++ b/usermods/Tubes/Tubes.h @@ -9,7 +9,6 @@ #include "FX.h" -#include "beats.h" #include "virtual_strip.h" #include "led_strip.h" #include "master.h" @@ -24,10 +23,9 @@ class TubesUsermod : public Usermod { private: - BeatController beats; - PatternController controller = PatternController(MAX_REAL_LEDS, &beats); - DebugController debug = DebugController(&controller); - Master *master = nullptr; + PatternController controller = PatternController(MAX_REAL_LEDS); + DebugController debug = DebugController(controller); + Master master = Master(controller); bool isLegacy = false; void randomize() { @@ -59,11 +57,9 @@ class TubesUsermod : public Usermod { // Start timing globalTimer.setup(); - beats.setup(); controller.setup(); if (controller.isMasterRole()) { - master = new Master(&controller); - master->setup(); + master.setup(); } debug.setup(); } @@ -76,23 +72,23 @@ class TubesUsermod : public Usermod { globalTimer.update(); - if (master) - master->update(); - beats.update(); + if (controller.isMasterRole()) { + master.update(); + } controller.update(); debug.update(); // Draw after everything else is done - controller.led_strip->update(); + controller.led_strip.update(); } - void handleOverlayDraw() - { + void handleOverlayDraw() { // Draw effects layers over whatever WLED is doing. controller.handleOverlayDraw(); debug.handleOverlayDraw(); - if (master) - master->handleOverlayDraw(); + if (controller.isMasterRole()) { + master.handleOverlayDraw(); + } // When AP mode is on, make sure it's obvious // Blink when there's a connected client diff --git a/usermods/Tubes/controller.h b/usermods/Tubes/controller.h index dc24e0cb4a..54378e60c9 100644 --- a/usermods/Tubes/controller.h +++ b/usermods/Tubes/controller.h @@ -131,10 +131,10 @@ class PatternController : public MessageReceiver { #ifdef USELCD Lcd *lcd; #endif - LEDs *led_strip; - BeatController *beats; - Effects *effects; - LightNode *node; + LEDs led_strip; + BeatController beats; + Effects effects; + LightNode node; ControllerOptions options; char key_buffer[20] = {0}; @@ -146,16 +146,13 @@ class PatternController : public MessageReceiver { // When a pattern is boring, spice it up a bit with more effects bool isBoring = false; - PatternController(uint8_t num, BeatController *b) : num_leds(num), beats(b) { + PatternController(uint8_t num) : + num_leds(num), led_strip(num), node(this) { #ifdef USELCD lcd = new Lcd(); #endif - led_strip = new LEDs(num_leds); - effects = new Effects(); - node = new LightNode(this); - // mesh = new BLEMeshNode(this); - for (uint8_t i=0; i < NUM_VSTRIPS; i++) { + for (auto i=0; i < NUM_VSTRIPS; i++) { #ifdef DOUBLED vstrips[i] = new VirtualStrip(num_leds * 2 + 1); #else @@ -164,7 +161,7 @@ class PatternController : public MessageReceiver { } } - bool isMasterRole() { + bool isMasterRole() const { #if defined(GOLDEN) || defined(CHRISTMAS) return true; #endif @@ -204,10 +201,12 @@ class PatternController : public MessageReceiver { else strip.ablMilliampsMax = 1400; - node->setup(); + + beats.setup(); + node.setup(); if (role >= MasterRole) { - node->reset(3850 + role); // MASTER ID + node.reset(3850 + role); // MASTER ID options.brightness = DEFAULT_MASTER_BRIGHTNESS; } else if (role >= LegacyRole) { options.brightness = DEFAULT_TUBE_BRIGHTNESS; @@ -217,7 +216,7 @@ class PatternController : public MessageReceiver { options.brightness = DEFAULT_TUBE_BRIGHTNESS; } #if defined(GOLDEN) || defined(CHRISTMAS) - node->reset(0xFFF); + node.reset(0xFFF); #endif options.debugging = false; load_options(options, true); @@ -300,11 +299,11 @@ class PatternController : public MessageReceiver { selectTimer.start(20000); } - bool isSelecting() { + bool isSelecting() const { return !selectTimer.ended(); } - bool isSelected() { + bool isSelected() const { return updater.status == Ready; } @@ -365,8 +364,10 @@ class PatternController : public MessageReceiver { { read_keys(); + beats.update(); + // Update the mesh - node->update(); + node.update(); // Update sound meter sound.update(); @@ -407,7 +408,7 @@ class PatternController : public MessageReceiver { // Update current status if (updateTimer.every(STATUS_UPDATE_PERIOD)) { // Transmit less often when following - if (!node->isFollowing() || random(0, 4) == 0) { + if (!node.isFollowing() || random(0, 4) == 0) { send_update(); } } @@ -440,7 +441,7 @@ class PatternController : public MessageReceiver { if (fader < 255) { // Perform a cross-fade between current WLED mode and the external buffer for (int i = 0; i < length; i++) { - CRGB c = led_strip->getPixelColor(i); + CRGB c = led_strip.getPixelColor(i); if (fader > 0) { CRGB color2 = strip.getPixelColor(i); uint8_t r = blend8(c.r, color2.r, fader); @@ -468,7 +469,7 @@ class PatternController : public MessageReceiver { // Draw effects layers over whatever WLED is doing. // But not in manual (WLED) mode if (!patternOverride) { - effects->draw(&strip); + effects.draw(&strip); } // Make the art half-size if it has a small number of pixels @@ -502,20 +503,20 @@ class PatternController : public MessageReceiver { } void restart_phrase() { - beats->start_phrase(); + beats.start_phrase(); update_beat(); send_update(); } void set_phrase_position(uint8_t pos) { - beats->sync(beats->bpm, (beats->frac & -0xFFF) + (pos<<8)); + beats.sync(beats.bpm, (beats.frac & -0xFFF) + (pos<<8)); update_beat(); send_update(); } void set_tapped_bpm(accum88 bpm, uint8_t pos=15) { // By default, restarts at 15th beat - because this is the end of a tap - beats->sync(bpm, (beats->frac & -0xFFF) + (pos<<8)); + beats.sync(bpm, (beats.frac & -0xFFF) + (pos<<8)); update_beat(); send_update(); } @@ -525,7 +526,7 @@ class PatternController : public MessageReceiver { if (new_bpm == 0) new_bpm = current_state.bpm>>8 >= 123 ? 120<<8 : 125<<8; - if (node->isFollowing()) { + if (node.isFollowing()) { // Send a request up to ROOT broadcast_bpm(new_bpm); } else { @@ -534,8 +535,8 @@ class PatternController : public MessageReceiver { } void update_beat() { - current_state.bpm = next_state.bpm = beats->bpm; - current_state.beat_frame = particle_beat_frame = beats->frac; // (particle_beat_frame is a hack) + current_state.bpm = next_state.bpm = beats.bpm; + current_state.beat_frame = particle_beat_frame = beats.frac; // (particle_beat_frame is a hack) if (current_state.bpm>>8 <= 118) // Hip hop / ghettofunk energy = MediumEnergy; else if (current_state.bpm>>8 >= 125) // House & breaks @@ -708,7 +709,7 @@ class PatternController : public MessageReceiver { current_state.print(); Serial.println(); - effects->load(current_state.effect_params); + effects.load(current_state.effect_params); } // Choose the effect to display at the next effect cycle @@ -793,7 +794,7 @@ class PatternController : public MessageReceiver { load_options(options); // The master controls all followers - if (!node->isFollowing()) + if (!node.isFollowing()) broadcast_options(); } @@ -804,7 +805,7 @@ class PatternController : public MessageReceiver { load_options(options); // The master controls all followers - if (!node->isFollowing()) + if (!node.isFollowing()) broadcast_options(); } @@ -886,10 +887,10 @@ class PatternController : public MessageReceiver { wled_fader = vstrip->fader; vstrip->update(beat_frame, beat_pulse); - vstrip->blend(led_strip->leds, led_strip->num_leds, options.brightness, vstrip == first_strip); + vstrip->blend(led_strip.leds, led_strip.num_leds, options.brightness, vstrip == first_strip); } - effects->update(first_strip, beat_frame, (BeatPulse)beat_pulse); + effects.update(first_strip, beat_frame, (BeatPulse)beat_pulse); } virtual void acknowledge() { @@ -987,7 +988,7 @@ class PatternController : public MessageReceiver { return; case 's': - beats->start_phrase(); + beats.start_phrase(); update_beat(); send_update(); return; @@ -1031,7 +1032,7 @@ class PatternController : public MessageReceiver { case 'i': Serial.printf("Reset! ID -> %03X\n", arg >> 4); - node->reset(arg >> 4); + node.reset(arg >> 4); return; case 'U': @@ -1127,31 +1128,31 @@ class PatternController : public MessageReceiver { } void broadcast_action(Action& action) { - if (!node->isFollowing()) { + if (!node.isFollowing()) { onAction(&action); } - node->sendCommand(COMMAND_ACTION, &action, sizeof(Action)); + node.sendCommand(COMMAND_ACTION, &action, sizeof(Action)); } void broadcast_info(NodeInfo *info) { - node->sendCommand(COMMAND_INFO, &info, sizeof(NodeInfo)); + node.sendCommand(COMMAND_INFO, &info, sizeof(NodeInfo)); } void broadcast_state() { - node->sendCommand(COMMAND_STATE, ¤t_state, sizeof(TubeStates)); + node.sendCommand(COMMAND_STATE, ¤t_state, sizeof(TubeStates)); } void broadcast_options() { - node->sendCommand(COMMAND_OPTIONS, &options, sizeof(options)); + node.sendCommand(COMMAND_OPTIONS, &options, sizeof(options)); } void broadcast_autoupdate() { - node->sendCommand(COMMAND_UPGRADE, &updater.current_version, sizeof(updater.current_version)); + node.sendCommand(COMMAND_UPGRADE, &updater.current_version, sizeof(updater.current_version)); } void broadcast_bpm(accum88 bpm) { // Hacked in feature: request a new BPM - node->sendCommand(COMMAND_BEATS, &bpm, sizeof(bpm)); + node.sendCommand(COMMAND_BEATS, &bpm, sizeof(bpm)); } virtual bool onCommand(CommandId command, void *data) { @@ -1184,7 +1185,7 @@ class PatternController : public MessageReceiver { load_pattern(state); load_palette(state); load_effect(state); - beats->sync(state.bpm, state.beat_frame); + beats.sync(state.bpm, state.beat_frame); return true; } @@ -1312,7 +1313,7 @@ class PatternController : public MessageReceiver { } virtual bool onButton(uint8_t button_id) { - bool isMaster = !this->node->isFollowing(); + bool isMaster = !this->node.isFollowing(); switch (button_id) { case WIZMOTE_BUTTON_ON: diff --git a/usermods/Tubes/debug.h b/usermods/Tubes/debug.h index ef7fbbdd62..afdb0bc910 100644 --- a/usermods/Tubes/debug.h +++ b/usermods/Tubes/debug.h @@ -24,17 +24,11 @@ std::string formatted_time(long ms) { class DebugController { public: - PatternController *controller; - LEDs *led_strip; - LightNode *node; + const PatternController& controller; uint32_t lastPhraseTime; uint32_t lastFrame; - DebugController(PatternController *c) : controller(c) - { - led_strip = controller->led_strip; - node = controller->node; - } + DebugController(const PatternController& c) : controller(c) {} void setup() { @@ -49,8 +43,8 @@ class DebugController { auto knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID(); auto knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP(); Serial.printf("\n=== %s%s WiFi[ch%d] %s IP: %u.%u.%u.%u Free memory: %d space: %u/%u Uptime: %s\n", - controller->node->node_name, - controller->node->status_code(), + controller.node.node_name, + controller.node.status_code(), WiFi.channel(), knownSsid.c_str(), knownIp[0], @@ -64,15 +58,15 @@ class DebugController { ); Serial.printf("=== Controller: "); - if (controller->isMasterRole()) { + if (controller.isMasterRole()) { Serial.print("PRIMARY "); } - if (controller->sound.active) { + if (controller.sound.active) { Serial.print("SOUND "); } Serial.printf("role=%d power_save=%d\n", - controller->role, - controller->power_save + controller.role, + controller.power_save ); // Dump WLED status @@ -89,24 +83,24 @@ class DebugController { seg.speed, seg.intensity ); - if (controller->patternOverride) { - Serial.printf(" (PATTERN %d)", controller->patternOverride); + if (controller.patternOverride) { + Serial.printf(" (PATTERN %d)", controller.patternOverride); } else { - Serial.printf(" at %d", controller->wled_fader); + Serial.printf(" at %d", controller.wled_fader); } - if (controller->paletteOverride) { - Serial.printf(" (PALETTE %d)", controller->paletteOverride); + if (controller.paletteOverride) { + Serial.printf(" (PALETTE %d)", controller.paletteOverride); } Serial.println(); Serial.printf("=== firmware: v%d from SSID %s %u.%u.%u.%u OTA=%d\n\n", - controller->updater.current_version.version, - controller->updater.current_version.ssid, - controller->updater.current_version.host[0], - controller->updater.current_version.ssid[1], - controller->updater.current_version.ssid[2], - controller->updater.current_version.ssid[3], - controller->updater.status + controller.updater.current_version.version, + controller.updater.current_version.ssid, + controller.updater.current_version.host[0], + controller.updater.current_version.ssid[1], + controller.updater.current_version.ssid[2], + controller.updater.current_version.ssid[3], + controller.updater.status ); } @@ -115,16 +109,16 @@ class DebugController { void handleOverlayDraw() { // Show the beat on the master OR if debugging - if (controller->options.debugging) { + if (controller.options.debugging) { uint16_t num_leds = strip.getLengthTotal(); - uint8_t p1 = (controller->current_state.beat_frame >> 8) % 16; + uint8_t p1 = (controller.current_state.beat_frame >> 8) % 16; strip.setPixelColor(p1, CRGB::White); - uint8_t p2 = scale8(controller->node->header.id>>4, num_leds-1); + uint8_t p2 = scale8(controller.node.header.id>>4, num_leds-1); strip.setPixelColor(p2, CRGB::Yellow); - uint8_t p3 = scale8(controller->node->header.uplinkId>>4, num_leds-1); + uint8_t p3 = scale8(controller.node.header.uplinkId>>4, num_leds-1); if (p3 == p2) { strip.setPixelColor(p3, CRGB::Green); } else { diff --git a/usermods/Tubes/led_strip.h b/usermods/Tubes/led_strip.h index 7edf523956..80d461c15a 100644 --- a/usermods/Tubes/led_strip.h +++ b/usermods/Tubes/led_strip.h @@ -44,7 +44,7 @@ class LEDs { } } - CRGB getPixelColor(uint8_t pos) { + CRGB getPixelColor(uint8_t pos) const { if (pos > num_leds) return CRGB::Black; return leds[pos]; diff --git a/usermods/Tubes/master.h b/usermods/Tubes/master.h index 3ae0b2303a..4efcb33a6e 100644 --- a/usermods/Tubes/master.h +++ b/usermods/Tubes/master.h @@ -25,10 +25,10 @@ class Master { uint8_t palette_mode = false; uint8_t palette_id = 0; - PatternController *controller; + PatternController& controller; Button button[5]; - Master(PatternController *c) : controller(c) { }; + Master(PatternController& c) : controller(c) { }; void setup() { button[0].setup(BUTTON_PIN_1); @@ -77,7 +77,7 @@ class Master { if (b == 4) { Serial.println((char *)F("Skip >>")); - controller->force_next(); + controller.force_next(); ok(); return; } @@ -95,7 +95,7 @@ class Master { #ifdef EXTRA_STUFF if (b == 2) { if (palette_mode) - controller->_load_palette(palette_id); + controller._load_palette(palette_id); palette_mode = false; } #endif @@ -151,20 +151,20 @@ class Master { else if (frac > 128) bpm += (256-frac) / 2; - controller->set_tapped_bpm(bpm); + controller.set_tapped_bpm(bpm); ok(); } else if (taps >= 2) { - controller->set_tapped_bpm(controller->current_state.bpm, taps-1); + controller.set_tapped_bpm(controller.current_state.bpm, taps-1); } } - void updateStatus(PatternController *controller) { + void updateStatus(const PatternController& controller) { if (taps) { displayProgress(taps); } else if (palette_mode) { displayPalette(background); } else { - uint8_t beat_pos = (controller->current_state.beat_frame >> 8) % 16; + uint8_t beat_pos = (controller.current_state.beat_frame >> 8) % 16; strip.setPixelColor(15 - beat_pos, CRGB::White); } } diff --git a/usermods/Tubes/node.h b/usermods/Tubes/node.h index f5362fb0dc..82799f678d 100644 --- a/usermods/Tubes/node.h +++ b/usermods/Tubes/node.h @@ -89,7 +89,7 @@ class LightNode { } NodeStatus; NodeStatus status = NODE_STATUS_QUIET; - PGM_P status_code() { + PGM_P status_code() const { switch (status) { case NODE_STATUS_QUIET: return PSTR(" (quiet)"); @@ -469,10 +469,11 @@ class LightNode { if (msg) { if(len == sizeof(NodeMessage)) { instance->onPeerData(address, (const NodeMessage*)msg, len, rssi, true); + } else if(len == sizeof(wizmote_message)) { instance->onWizmote(address, (const wizmote_message*)msg, len); } else { #ifdef NODE_DEBUGGING - Serial.printf("wrong size QueueNodeMessage received %d\n", len); + Serial.printf("wrong size EspNowMessage received %d\n", len); #endif } } diff --git a/usermods/Tubes/timer.h b/usermods/Tubes/timer.h index 87b5de71b3..f888a12316 100644 --- a/usermods/Tubes/timer.h +++ b/usermods/Tubes/timer.h @@ -43,7 +43,7 @@ class Timer { start(0); } - uint32_t since_mark() { + uint32_t since_mark() const { if (globalTimer.now_millis < markTime) return 0; return globalTimer.now_millis - markTime; @@ -54,7 +54,7 @@ class Timer { markTime += duration_ms; } - bool ended() { + bool ended() const { return globalTimer.now_millis > markTime; } From 421063a4a80b6408ad3b96a7730800fe12f6b47b Mon Sep 17 00:00:00 2001 From: Craig Link Date: Wed, 14 Aug 2024 09:46:38 -0700 Subject: [PATCH 22/50] Make particles arrary static and not use heap Avoids heap fragmentation and potential crashes Leverages C++ std::move for creating new particles --- usermods/Tubes/effects.h | 45 +++++++++++------------ usermods/Tubes/particle.h | 75 +++++++++++++++++++-------------------- 2 files changed, 58 insertions(+), 62 deletions(-) diff --git a/usermods/Tubes/effects.h b/usermods/Tubes/effects.h index baceddafec..a23254850b 100644 --- a/usermods/Tubes/effects.h +++ b/usermods/Tubes/effects.h @@ -6,44 +6,44 @@ void addGlitter(CRGB color=CRGB::White, PenMode pen=Draw) { - addParticle(new Particle(random16(), color, pen, 128)); + addParticle(Particle(random16(), color, pen, 128)); } void addSpark(CRGB color=CRGB::White, PenMode pen=Draw) { - Particle *particle = new Particle(random16(), color, pen, 64); + Particle particle {random16(), color, pen, 64}; uint8_t r = random8(); if (r > 128) - particle->velocity = r; + particle.velocity = r; else - particle->velocity = -(128 + r); - addParticle(particle); + particle.velocity = -(128 + r); + addParticle(std::move(particle)); } void addBeatbox(CRGB color=CRGB::White, PenMode pen=Draw) { - Particle *particle = new Particle(random16(), color, pen, 256, drawBeatbox); - addParticle(particle); + Particle particle {random16(), color, pen, 256, drawBeatbox}; + addParticle(std::move(particle)); } void addBubble(CRGB color=CRGB::White, PenMode pen=Draw) { - Particle *particle = new Particle(random16(), color, pen, 1024, drawPop); - particle->velocity = random16(0, 40) - 20; - addParticle(particle); + Particle particle {random16(), color, pen, 1024, drawPop}; + particle.velocity = random16(0, 40) - 20; + addParticle(std::move(particle)); } void addFlash(CRGB color=CRGB::Blue, PenMode pen=Draw) { - addParticle(new Particle(random16(), color, pen, 256, drawFlash)); + addParticle(Particle(random16(), color, pen, 256, drawFlash)); } void addDrop(CRGB color, PenMode pen=Draw) { - Particle *particle = new Particle(65535, color, pen, 360); - particle->velocity = -500; - particle->gravity = -10; - addParticle(particle); + Particle particle {65535, color, pen, 360}; + particle.velocity = -500; + particle.gravity = -10; + addParticle(std::move(particle)); } class Effects { @@ -101,13 +101,11 @@ class Effects { void animate(BeatFrame_24_8 frame, uint8_t beat_pulse) { unsigned int len = numParticles; - for (unsigned i=len; i > 0; i--) { - Particle *particle = particles[i-1]; - - particle->update(frame); - if (particle->age > particle->lifetime) { - removeParticle(i-1); - continue; + for (unsigned i=len; i > 0; --i) { + Particle& particle = particles[i]; + particle.update(frame); + if (particle.age > particle.lifetime) { + removeParticle(i); } } } @@ -115,8 +113,7 @@ class Effects { void draw(WS2812FX* leds) { uint8_t len = numParticles; for (uint8_t i=0; idrawFn(particle, leds); + particles[i].draw(leds); } } diff --git a/usermods/Tubes/particle.h b/usermods/Tubes/particle.h index 9005e2ef4f..db4f773f83 100644 --- a/usermods/Tubes/particle.h +++ b/usermods/Tubes/particle.h @@ -11,27 +11,26 @@ class Particle; -typedef void (*ParticleFn)(Particle *particle, WS2812FX* leds); +typedef void (*ParticleFn)(Particle& particle, WS2812FX* leds); uint8_t particleVolume = DEFAULT_PARTICLE_VOLUME; -extern void drawPoint(Particle *particle, WS2812FX* leds); -extern void drawFlash(Particle *particle, WS2812FX* leds); +extern void drawPoint(Particle& particle, WS2812FX* leds); class Particle { public: - Particle(uint16_t pos, CRGB c=CRGB::White, PenMode p=Draw, uint32_t life=20000, ParticleFn fn=drawPoint) : + Particle(uint16_t pos = 0, CRGB c=CRGB::White, PenMode p=Draw, uint32_t life=20000, ParticleFn fn=drawPoint) : + born(0), + lifetime(life), age(0), color(c), + pen(p), brightness(192<<8), drawFn(fn), + position(pos), velocity(0), gravity(0) - { - pen = p; - position = pos; - lifetime = life; - }; + {}; BeatFrame_24_8 born; BeatFrame_24_8 lifetime; @@ -45,7 +44,7 @@ class Particle { uint16_t position; int16_t velocity; int16_t gravity; - void (*die_fn)(Particle *particle) = NULL; +// void (*die_fn)(Particle *particle) = NULL; #ifdef PARTICLE_PALETTES CRGBPalette16 palette; // 48 bytes per particle!? @@ -104,6 +103,10 @@ class Particle { return CRGB(r,g,b); } + void draw(WS2812FX* leds) { + drawFn(*this, leds); + } + void draw_with_pen(WS2812FX* leds, int pos, CRGB color) { CRGB c = CRGB(strip.getPixelColor(pos)); CRGB new_color; @@ -165,7 +168,7 @@ class Particle { }; -Particle* particles[MAX_PARTICLES]; +Particle particles[MAX_PARTICLES]; BeatFrame_24_8 particle_beat_frame; uint8_t numParticles = 0; @@ -173,11 +176,7 @@ void removeParticle(uint8_t i) { if (i >= numParticles) return; - // Free the memory of the old particle - Particle *old_particle = particles[i]; - delete old_particle; - - // Reset the current free particle + // coalesce current particle list int rest = numParticles - i; if (rest > 0) { memmove(&particles[i], &particles[i+1], sizeof(particles[0]) * rest); @@ -186,32 +185,32 @@ void removeParticle(uint8_t i) { numParticles -= 1; } -void addParticle(Particle *particle) { - particle->born = particle_beat_frame; +void addParticle(Particle&& particle) { + particle.born = particle_beat_frame; if (numParticles >= MAX_PARTICLES) { removeParticle(0); } particles[numParticles++] = particle; } -void drawFlash(Particle *particle, WS2812FX* leds) { +void drawFlash(Particle& particle, WS2812FX* leds) { auto num_leds = leds->getLengthTotal(); - uint16_t age_frac = particle->age_frac16(particle->age); - CRGB c = particle->color_at(age_frac); + uint16_t age_frac = particle.age_frac16(particle.age); + CRGB c = particle.color_at(age_frac); for (int pos = 0; pos < num_leds; pos++) { - particle->draw_with_pen(leds, pos, c); + particle.draw_with_pen(leds, pos, c); } } -void drawPoint(Particle *particle, WS2812FX* leds) { - uint16_t age_frac = particle->age_frac16(particle->age); - CRGB c = particle->color_at(age_frac); +void drawPoint(Particle& particle, WS2812FX* leds) { + uint16_t age_frac = particle.age_frac16(particle.age); + CRGB c = particle.color_at(age_frac); - uint16_t pos = scale16(particle->position, leds->getLengthTotal() - 1); - particle->draw_with_pen(leds, pos, c); + uint16_t pos = scale16(particle.position, leds->getLengthTotal() - 1); + particle.draw_with_pen(leds, pos, c); } -void drawRadius(Particle *particle, WS2812FX* leds, uint16_t pos, uint8_t radius, CRGB c, bool dim=true) { +void drawRadius(Particle& particle, WS2812FX* leds, uint16_t pos, uint8_t radius, CRGB c, bool dim=true) { auto num_leds = leds->getLengthTotal(); for (int i = 0; i < radius; i++) { uint8_t bright = dim ? ((radius-i) * 255) / radius : 255; @@ -219,30 +218,30 @@ void drawRadius(Particle *particle, WS2812FX* leds, uint16_t pos, uint8_t radius uint8_t y = pos - i; if (y >= 0 && y < num_leds) - particle->draw_with_pen(leds, y, c); + particle.draw_with_pen(leds, y, c); if (i == 0) continue; y = pos + i; if (y >= 0 && y < num_leds) - particle->draw_with_pen(leds, y, c); + particle.draw_with_pen(leds, y, c); } } -void drawPop(Particle *particle, WS2812FX* leds) { - uint16_t age_frac = particle->age_frac16(particle->age); - CRGB c = particle->color_at(age_frac); - uint16_t pos = scale16(particle->position, leds->getLengthTotal() - 1); +void drawPop(Particle& particle, WS2812FX* leds) { + uint16_t age_frac = particle.age_frac16(particle.age); + CRGB c = particle.color_at(age_frac); + uint16_t pos = scale16(particle.position, leds->getLengthTotal() - 1); uint8_t radius = scale16((sin16(age_frac/2) - 32768) * 2, 8); drawRadius(particle, leds, pos, radius, c); } -void drawBeatbox(Particle *particle, WS2812FX* leds) { - uint16_t age_frac = particle->age_frac16(particle->age); - CRGB c = particle->color_at(age_frac); - uint16_t pos = scale16(particle->position, leds->getLengthTotal() - 1); +void drawBeatbox(Particle& particle, WS2812FX* leds) { + uint16_t age_frac = particle.age_frac16(particle.age); + CRGB c = particle.color_at(age_frac); + uint16_t pos = scale16(particle.position, leds->getLengthTotal() - 1); uint8_t radius = 3; // Bump up the radius with any beats From 565e88335c41d8ca2c17b7d120e77cba15e0c10a Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Sun, 18 Aug 2024 10:20:25 -0700 Subject: [PATCH 23/50] Fix errors when strips have more LEDs than MAX_VIRTUAL_LEDs Remove excess LEDs buffering --- usermods/Tubes/controller.h | 36 ++++++++++++++++++-------- usermods/Tubes/led_strip.h | 23 +---------------- usermods/Tubes/pattern.h | 36 +++++++++++++------------- usermods/Tubes/virtual_strip.h | 46 +++++++++++++--------------------- 4 files changed, 62 insertions(+), 79 deletions(-) diff --git a/usermods/Tubes/controller.h b/usermods/Tubes/controller.h index 54378e60c9..a253dd5c3c 100644 --- a/usermods/Tubes/controller.h +++ b/usermods/Tubes/controller.h @@ -107,7 +107,6 @@ class PatternController : public MessageReceiver { const static int FRAMES_PER_SECOND = 60; // how often we animate, in frames per second const static int REFRESH_PERIOD = 1000 / FRAMES_PER_SECOND; // how often we animate, in milliseconds - uint8_t num_leds; VirtualStrip *vstrips[NUM_VSTRIPS]; uint8_t next_vstrip = 0; bool canOverride = false; @@ -146,18 +145,13 @@ class PatternController : public MessageReceiver { // When a pattern is boring, spice it up a bit with more effects bool isBoring = false; - PatternController(uint8_t num) : - num_leds(num), led_strip(num), node(this) { + PatternController() : node(this) { #ifdef USELCD lcd = new Lcd(); #endif for (auto i=0; i < NUM_VSTRIPS; i++) { -#ifdef DOUBLED - vstrips[i] = new VirtualStrip(num_leds * 2 + 1); -#else - vstrips[i] = new VirtualStrip(num_leds); -#endif + vstrips[i] = new VirtualStrip(); } } @@ -441,7 +435,7 @@ class PatternController : public MessageReceiver { if (fader < 255) { // Perform a cross-fade between current WLED mode and the external buffer for (int i = 0; i < length; i++) { - CRGB c = led_strip.getPixelColor(i); + CRGB c = getBlendedPixelColor(i); if (fader > 0) { CRGB color2 = strip.getPixelColor(i); uint8_t r = blend8(c.r, color2.r, fader); @@ -887,12 +881,34 @@ class PatternController : public MessageReceiver { wled_fader = vstrip->fader; vstrip->update(beat_frame, beat_pulse); - vstrip->blend(led_strip.leds, led_strip.num_leds, options.brightness, vstrip == first_strip); } effects.update(first_strip, beat_frame, (BeatPulse)beat_pulse); } + CRGB getBlendedPixelColor(int32_t pos) { + // Calculate the color of the pixel at position i by blending the colors of the virtual strips + CRGB color = CRGB::Black; + + for (uint8_t i=0; i < NUM_VSTRIPS; i++) { + VirtualStrip *vstrip = vstrips[i]; + + // Don't bother blending a fully faded strip, or the WLED strip itself + if (vstrip->fade == Dead || vstrip->isWled()) + continue; + + auto br = vstrip->brightness; //(options.brightness, vstrip->brightness); + + // Fetch the color from the strip and dim it according to the brightness + CRGB c = vstrip->getPixelColor(pos); + nscale8x3(c.r, c.g, c.b, br); + nscale8x3(c.r, c.g, c.b, vstrip->fader>>8); + color |= c; + } + + return color; + } + virtual void acknowledge() { addFlash(CRGB::Green); } diff --git a/usermods/Tubes/led_strip.h b/usermods/Tubes/led_strip.h index 80d461c15a..55c58591f4 100644 --- a/usermods/Tubes/led_strip.h +++ b/usermods/Tubes/led_strip.h @@ -3,34 +3,19 @@ #define USE_WLED #include "wled.h" -#define MAX_REAL_LEDS 150 - class LEDs { public: - CRGB leds[MAX_REAL_LEDS]; - // CRGB led_array[MAX_REAL_LEDS]; - const static int TARGET_FRAMES_PER_SECOND = 150; const static int TARGET_REFRESH = 1000 / TARGET_FRAMES_PER_SECOND; - int num_leds; - uint16_t fps = 0; - LEDs(int num=MAX_REAL_LEDS) : num_leds(num) { }; + LEDs() { }; void setup() { Serial.println((char *)F("LEDs: ok")); } - void reverse() { - for (int i=1; i<8; i++) { - CRGB c = leds[i]; - leds[i] = leds[16-i]; - leds[16-i] = c; - } - } - void update() { EVERY_N_MILLISECONDS( TARGET_REFRESH ) { fps++; @@ -43,10 +28,4 @@ class LEDs { fps = 0; } } - - CRGB getPixelColor(uint8_t pos) const { - if (pos > num_leds) - return CRGB::Black; - return leds[pos]; - } }; diff --git a/usermods/Tubes/pattern.h b/usermods/Tubes/pattern.h index a9cd57a3c5..94cec51dd0 100644 --- a/usermods/Tubes/pattern.h +++ b/usermods/Tubes/pattern.h @@ -6,14 +6,14 @@ void rainbow(VirtualStrip *strip) { // FastLED's built-in rainbow generator - fill_rainbow( strip->leds, strip->num_leds, strip->hue, 3); + fill_rainbow( strip->leds, strip->length(), strip->hue, 3); } void palette_wave(VirtualStrip *strip) { // FastLED's built-in rainbow generator uint8_t hue = strip->hue; - for (uint8_t i=0; i < strip->num_leds; i++) { + for (uint8_t i=0; i < strip->length(); i++) { CRGB c = strip->palette_color(i, hue); nscale8x3(c.r, c.g, c.b, sin8(hue*8)); strip->leds[i] = c; @@ -23,35 +23,35 @@ void palette_wave(VirtualStrip *strip) void particleTest(VirtualStrip *strip) { - fill_solid( strip->leds, strip->num_leds, CRGB::Black); + fill_solid( strip->leds, strip->length(), CRGB::Black); fill_solid( strip->leds, 2, strip->palette_color(0, strip->hue)); } void solidBlack(VirtualStrip *strip) { - fill_solid( strip->leds, strip->num_leds, CRGB::Black); + fill_solid( strip->leds, strip->length(), CRGB::Black); } void solidWhite(VirtualStrip *strip) { - fill_solid( strip->leds, strip->num_leds, CRGB::White); + fill_solid( strip->leds, strip->length(), CRGB::White); } void solidRed(VirtualStrip *strip) { - fill_solid( strip->leds, strip->num_leds, CRGB::Red); + fill_solid( strip->leds, strip->length(), CRGB::Red); } void solidBlue(VirtualStrip *strip) { - fill_solid( strip->leds, strip->num_leds, CRGB::Blue); + fill_solid( strip->leds, strip->length(), CRGB::Blue); } void confetti(VirtualStrip *strip) { strip->darken(2); - int pos = random16(strip->num_leds); + int pos = random16(strip->length()); strip->leds[pos] += strip->palette_color(random8(64), strip->hue); } @@ -65,8 +65,8 @@ void biwave(VirtualStrip *strip) uint16_t r = strip->frame * 32; r = cos16( r + random_offset ) + 32768; - uint8_t p1 = scaled16to8(l, 0, strip->num_leds-1); - uint8_t p2 = scaled16to8(r, 0, strip->num_leds-1); + uint8_t p1 = scaled16to8(l, 0, strip->length()-1); + uint8_t p2 = scaled16to8(r, 0, strip->length()-1); if (p2 < p1) { uint16_t t = p1; @@ -90,14 +90,14 @@ void sinelon(VirtualStrip *strip) // a colored dot sweeping back and forth, with fading trails strip->darken(30); - int pos = scale16(sin16( strip->frame << 5 ) + 32768, strip->num_leds-1); // beatsin16 re-implemented + int pos = scale16(sin16( strip->frame << 5 ) + 32768, strip->length()-1); // beatsin16 re-implemented strip->leds[pos] += strip->hue_color(); } void bpm_palette(VirtualStrip *strip) { uint8_t beat = strip->bpm_sin16(64, 255); - for (int i = 0; i < strip->num_leds; i++) { + for (int i = 0; i < strip->length(); i++) { CRGB c = strip->palette_color(i*2, strip->hue, beat-strip->hue+(i*10)); strip->leds[i] = c; } @@ -109,7 +109,7 @@ void bpm(VirtualStrip *strip) CRGBPalette16 palette = PartyColors_p; uint8_t beat = strip->bpm_sin16(64, 255); - for (int i = 0; i < strip->num_leds; i++) { + for (int i = 0; i < strip->length(); i++) { strip->leds[i] = ColorFromPalette(palette, strip->hue+(i*2), beat-strip->hue+(i*10)); } } @@ -123,7 +123,7 @@ void juggle(VirtualStrip *strip) for( int i = 0; i < 8; i++) { CRGB c = strip->palette_color(dothue + strip->hue); // c = CHSV(dothue, 200, 255); - strip->leds[beatsin16( i+7, 0, strip->num_leds-1 )] |= c; + strip->leds[beatsin16( i+7, 0, strip->length()-1 )] |= c; dothue += 32; } } @@ -142,18 +142,18 @@ void fillnoise8(uint32_t frame, uint8_t num_leds) { data = qsub8(data,16); data = qadd8(data,scale8(data,39)); - uint8_t olddata = noise[i]; + uint8_t olddata = noise[i % MAX_VIRTUAL_LEDS]; uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing); - noise[i] = newdata; + noise[i % MAX_VIRTUAL_LEDS] = newdata; } } void drawNoise(VirtualStrip *strip) { // generate noise data - fillnoise8(strip->frame >> 2, strip->num_leds); + fillnoise8(strip->frame >> 2, strip->length()); - for(int i = 0; i < strip->num_leds; i++) { + for(int i = 0; i < strip->length(); i++) { CRGB color = strip->palette_color(noise[i], strip->hue); strip->leds[i] = color; } diff --git a/usermods/Tubes/virtual_strip.h b/usermods/Tubes/virtual_strip.h index 2c8fa72e8e..74731047b1 100644 --- a/usermods/Tubes/virtual_strip.h +++ b/usermods/Tubes/virtual_strip.h @@ -7,7 +7,7 @@ #include "wled.h" #define DEFAULT_FADE_SPEED 100 -#define MAX_VIRTUAL_LEDS 150 +#define MAX_VIRTUAL_LEDS 500 #define DEFAULT_WLED_FX FX_MODE_RAINBOW_CYCLE @@ -45,7 +45,6 @@ class VirtualStrip { public: CRGB leds[MAX_VIRTUAL_LEDS]; - uint8_t num_leds; uint8_t brightness; // Fade in/out @@ -62,11 +61,19 @@ class VirtualStrip { bool beat_pulse; int bps = 0; - VirtualStrip(uint8_t num) : num_leds(num) + VirtualStrip() { fade = Dead; } + int32_t length() { + // Try to be the same as the main segment, but not if it's too big + auto len = strip.getMainSegment().length(); + if (len > MAX_VIRTUAL_LEDS) + return MAX_VIRTUAL_LEDS; + return len; + } + void load(Background &b, uint8_t fs=DEFAULT_FADE_SPEED) { background = b; @@ -90,12 +97,12 @@ class VirtualStrip { void darken(uint8_t amount=10) { - fadeToBlackBy( leds, num_leds, amount); + fadeToBlackBy( leds, length(), amount); } void fill(CRGB crgb) { - fill_solid( leds, num_leds, crgb); + fill_solid( leds, length(), crgb); } void update(BeatFrame_24_8 fr, uint8_t bp) @@ -171,30 +178,7 @@ class VirtualStrip { CRGB hue_color(uint8_t offset=0, uint8_t saturation=255, uint8_t value=192) { return CHSV(hue + offset, saturation, value); } - - void blend(CRGB output[], uint8_t num_leds, uint8_t br, bool overwrite=0) { - if (fade == Dead) - return; - - // WLED is blended in elsewhere - if (isWled()) - return; - - br = scale8(brightness, br); - - for (unsigned i=0; i < num_leds; i++) { - uint8_t pos = i; - CRGB c = leds[pos]; - - nscale8x3(c.r, c.g, c.b, brightness); - nscale8x3(c.r, c.g, c.b, fader>>8); - if (overwrite) - output[i] = c; - else - output[i] |= c; - } - } - + uint8_t bpm_sin16( uint16_t lowest=0, uint16_t highest=65535 ) { return scaled16to8(sin16( frame << 7 ) + 32768, lowest, highest); @@ -205,4 +189,8 @@ class VirtualStrip { return scaled16to8(cos16( frame << 7 ) + 32768, lowest, highest); } + CRGB getPixelColor(int32_t pos) { + return leds[pos % length()]; + } + }; From 557afa5fb4ee4ce92b061313474294ef128c7426 Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Sun, 18 Aug 2024 14:11:51 -0700 Subject: [PATCH 24/50] PR suggestions --- usermods/Tubes/Tubes.h | 7 +++++++ usermods/Tubes/controller.h | 7 ++++++- usermods/Tubes/pattern.h | 11 ++++++++--- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/usermods/Tubes/Tubes.h b/usermods/Tubes/Tubes.h index 1b4b4214be..ebd34b6c4e 100644 --- a/usermods/Tubes/Tubes.h +++ b/usermods/Tubes/Tubes.h @@ -20,6 +20,13 @@ #define MASTER_PIN 25 #define LEGACY_PIN 32 // DigUno Q4 +#ifndef NUM_STRIPS +#define NUM_STRIPS 1 +#endif + +#ifndef MAX_REAL_LEDS +#define MAX_REAL_LEDS (DEFAULT_LED_COUNT * NUM_STRIPS) +#endif class TubesUsermod : public Usermod { private: diff --git a/usermods/Tubes/controller.h b/usermods/Tubes/controller.h index a253dd5c3c..ccb5c0b5a3 100644 --- a/usermods/Tubes/controller.h +++ b/usermods/Tubes/controller.h @@ -155,6 +155,11 @@ class PatternController : public MessageReceiver { } } + // Compatibility ctor for older call sites that pass a real LED count. + PatternController(uint16_t real_led_count) : PatternController() { + (void)real_led_count; + } + bool isMasterRole() const { #if defined(GOLDEN) || defined(CHRISTMAS) return true; @@ -1444,4 +1449,4 @@ class PatternController : public MessageReceiver { } -}; \ No newline at end of file +}; diff --git a/usermods/Tubes/pattern.h b/usermods/Tubes/pattern.h index 94cec51dd0..be940c87d9 100644 --- a/usermods/Tubes/pattern.h +++ b/usermods/Tubes/pattern.h @@ -133,7 +133,12 @@ uint8_t noise[MAX_VIRTUAL_LEDS]; void fillnoise8(uint32_t frame, uint8_t num_leds) { uint16_t scale = 17; uint8_t dataSmoothing = 240; - + + auto max_leds = sizeof(noise)/sizeof(noise[0]); + if (num_leds > max_leds) { + num_leds = max_leds; + } + for (int i = 0; i < num_leds; i++) { uint8_t data = inoise8(i * scale, frame>>2); @@ -142,9 +147,9 @@ void fillnoise8(uint32_t frame, uint8_t num_leds) { data = qsub8(data,16); data = qadd8(data,scale8(data,39)); - uint8_t olddata = noise[i % MAX_VIRTUAL_LEDS]; + uint8_t olddata = noise[i]; uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing); - noise[i % MAX_VIRTUAL_LEDS] = newdata; + noise[i] = newdata; } } From b6ae6bb8a7f66238833d74f1b35baa33f1cf7cc7 Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Sun, 18 Aug 2024 14:31:20 -0700 Subject: [PATCH 25/50] Update explanation of strip blending --- usermods/Tubes/controller.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/usermods/Tubes/controller.h b/usermods/Tubes/controller.h index ccb5c0b5a3..c2e0f0ac98 100644 --- a/usermods/Tubes/controller.h +++ b/usermods/Tubes/controller.h @@ -895,6 +895,7 @@ class PatternController : public MessageReceiver { // Calculate the color of the pixel at position i by blending the colors of the virtual strips CRGB color = CRGB::Black; + bool first_strip = true; for (uint8_t i=0; i < NUM_VSTRIPS; i++) { VirtualStrip *vstrip = vstrips[i]; @@ -902,13 +903,22 @@ class PatternController : public MessageReceiver { if (vstrip->fade == Dead || vstrip->isWled()) continue; - auto br = vstrip->brightness; //(options.brightness, vstrip->brightness); + auto br = vstrip->brightness; + // TODO: code intended to use scale8(options.brightness, vstrip->brightness); + // but that was never implemented - should review later to see if we want + // options.brightness to be a factor in the brightness of the strip // Fetch the color from the strip and dim it according to the brightness CRGB c = vstrip->getPixelColor(pos); nscale8x3(c.r, c.g, c.b, br); nscale8x3(c.r, c.g, c.b, vstrip->fader>>8); - color |= c; + + if (first_strip) { + color = c; + first_strip = false; + } else { + color |= c; + } } return color; From 6e9ce673419eead18bdabb015b1bea28e3ba7516 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Sun, 18 Aug 2024 17:34:57 -0700 Subject: [PATCH 26/50] add support for espnow message filtering and make a few more methods const for clarity --- usermods/Tubes/bluetooth.h | 4 ++- usermods/Tubes/controller.h | 4 +-- usermods/Tubes/node.h | 53 ++++++++++++++----------------------- wled00/espnow_broadcast.cpp | 23 +++++++++++++--- wled00/espnow_broadcast.h | 21 ++++++++++++--- 5 files changed, 62 insertions(+), 43 deletions(-) diff --git a/usermods/Tubes/bluetooth.h b/usermods/Tubes/bluetooth.h index d98f5bcf88..3a48a51861 100644 --- a/usermods/Tubes/bluetooth.h +++ b/usermods/Tubes/bluetooth.h @@ -1,3 +1,4 @@ +#if 0 #pragma once // THIS FILE ISN'T USED ANY MORE @@ -492,4 +493,5 @@ void procUpdaterTask(void* pvParameters) { pClient->disconnect(); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/usermods/Tubes/controller.h b/usermods/Tubes/controller.h index c2e0f0ac98..d760d11b66 100644 --- a/usermods/Tubes/controller.h +++ b/usermods/Tubes/controller.h @@ -1186,7 +1186,7 @@ class PatternController : public MessageReceiver { node.sendCommand(COMMAND_BEATS, &bpm, sizeof(bpm)); } - virtual bool onCommand(CommandId command, void *data) { + virtual bool onCommand(CommandId command, void *data) override { switch (command) { case COMMAND_INFO: Serial.printf(" \"%s\"\n", @@ -1343,7 +1343,7 @@ class PatternController : public MessageReceiver { force_next(); } - virtual bool onButton(uint8_t button_id) { + virtual bool onButton(uint8_t button_id) override { bool isMaster = !this->node.isFollowing(); switch (button_id) { diff --git a/usermods/Tubes/node.h b/usermods/Tubes/node.h index 82799f678d..2c44f4861d 100644 --- a/usermods/Tubes/node.h +++ b/usermods/Tubes/node.h @@ -64,14 +64,8 @@ const char *command_name(CommandId command) { class MessageReceiver { public: - virtual bool onCommand(CommandId command, void *data) { - // Abstract: subclasses must define - return false; - } - virtual bool onButton(uint8_t button_id) { - // Abstract: subclasses must define - return false; - } + virtual bool onCommand(CommandId command, void *data) = 0; + virtual bool onButton(uint8_t button_id) = 0; }; class LightNode { @@ -174,7 +168,7 @@ class LightNode { } } - void printMessage(const NodeMessage* message, signed int rssi) { + void printMessage(const NodeMessage* message, signed int rssi) const { Serial.printf("%03X/%03X %s", message->header.id, message->header.uplinkId, @@ -187,20 +181,6 @@ class LightNode { } void onPeerData(const uint8_t* address, const NodeMessage* message, uint8_t len, signed int rssi, bool broadcast) { - // Ignore this message if it isn't a valid message payload. - if (len != sizeof(*message)) - return; - - // Ignore this message if it's the wrong version. - if (message->header.version != header.version) { -#ifdef NODE_DEBUGGING - Serial.print(" -- !version "); - printMessage(message, rssi); - Serial.println(); -#endif - return; - } - // Track that another node exists, updating this node's understanding of the mesh. onPeerPing(message->header); @@ -350,6 +330,7 @@ class LightNode { delay(2000); #endif + espnowBroadcast.registerFilter(onEspNowFilter); espnowBroadcast.registerCallback(onEspNowMessage); Serial.println("setup: ok"); @@ -358,7 +339,7 @@ class LightNode { void update() { //process any wifi events to turn on/off ESPNode - checkESPNowState(); + updateESPNowState(); // Check the last time we heard from the uplink node if (isFollowing() && uplinkTimer.ended()) { @@ -400,19 +381,19 @@ class LightNode { onMeshChange(); } - bool isFollowing() { + bool isFollowing() const { return header.uplinkId != 0; } protected: - void checkESPNowState() { + void updateESPNowState() { auto state = espnowBroadcast.getState(); static auto prev = espnowBroadcast.STOPPED; switch(state) { case ESPNOWBroadcast::STOPPED: if (NODE_STATUS_QUIET != status) { - Serial.printf("checkESPNowState() - %d node_status:%s\n", state, status_code()); + Serial.printf("updateESPNowState() - %d node_status:%s\n", state, status_code()); status = NODE_STATUS_QUIET; rebroadcastTimer.stop(); Serial.printf("LightNode %s\n", status_code()); @@ -420,12 +401,12 @@ class LightNode { break; case ESPNOWBroadcast::STARTING: {} if ( state != prev ) { - Serial.printf("checkESPNowState() - %d node_status:%s\n", state, status_code()); + Serial.printf("updateESPNowState() - %d node_status:%s\n", state, status_code()); } break; case ESPNOWBroadcast::STARTED: if (NODE_STATUS_QUIET == status) { - Serial.printf("checkESPNowState() - %d node_status:%s\n", state, status_code()); + Serial.printf("updateESPNowState() - %d node_status:%s\n", state, status_code()); status = NODE_STATUS_RECEIVING; statusTimer.start(STATUS_TIMEOUT_BASE - header.id / 2); Serial.printf("LightNode %s\n", status_code()); @@ -452,10 +433,6 @@ class LightNode { } wizmote_message; void onWizmote(const uint8_t* address, const wizmote_message* data, uint8_t len) { - // First make sure this is a WizMote message. - if (len != sizeof(wizmote_message) || data->byte8 != 1 || data->byte9 != 100 || data->byte5 != 32) - return; - static uint32_t last_seq = 0; uint32_t cur_seq = data->seq[0] | (data->seq[1] << 8) | (data->seq[2] << 16) | (data->seq[3] << 24); if (cur_seq == last_seq) @@ -466,6 +443,7 @@ class LightNode { } static void onEspNowMessage(const uint8_t *address, const uint8_t *msg, uint8_t len, int8_t rssi) { + // basic length and field checking has been done in onEspNowFilter if (msg) { if(len == sizeof(NodeMessage)) { instance->onPeerData(address, (const NodeMessage*)msg, len, rssi, true); @@ -479,6 +457,15 @@ class LightNode { } } + static bool onEspNowFilter(const uint8_t *address, const uint8_t *msg, uint8_t len, int8_t rssi) { + if (len == sizeof(NodeMessage)) { + return ((const NodeMessage*)msg)->header.version == instance->header.version; + } else if (len == sizeof(wizmote_message)) { + auto wizmote = (const wizmote_message*)msg; + return !( wizmote->byte8 != 1 || wizmote->byte9 != 100 || wizmote->byte5 != 32); + } + return false; + } }; LightNode* LightNode::instance = nullptr; diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index 946745e16e..fe0b0c5427 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -33,7 +33,7 @@ ESP_EVENT_DEFINE_BASE(SYSTEM_EVENT); #endif //#define ESPNOW_DEBUGGING -//#define ESNOW_CALLBACK_DEBUGGING // Serial is called from multiple threads +//#define ESPNOW_CALLBACK_DEBUGGING // Serial is called from multiple threads #define BROADCAST_ADDR_ARRAY_INITIALIZER {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} #define WLED_ESPNOW_WIFI_CHANNEL 1 @@ -57,7 +57,7 @@ class ESPNOWBroadcastImpl : public ESPNOWBroadcast { friend ESPNOWBroadcast; std::atomic _state {STOPPED}; - STATE getState() { + STATE getState() const { return _state.load(); } @@ -71,6 +71,8 @@ class ESPNOWBroadcastImpl : public ESPNOWBroadcast { static void onESPNowRxCallback(const uint8_t *mac_addr, const uint8_t *data, int len); + receive_filter_t _rxFilter = nullptr; + class QueuedNetworkRingBuffer { protected: //QueuedNetworkMessage messages[WLED_ESPNOW_MAX_QUEUED_MESSAGES]; @@ -103,7 +105,7 @@ ESPNOWBroadcastImpl espnowBroadcastImpl {}; ESPNOWBroadcast espnowBroadcast {}; -ESPNOWBroadcast::STATE ESPNOWBroadcast::getState() { +ESPNOWBroadcast::STATE ESPNOWBroadcast::getState() const { #ifdef ESP32 return espnowBroadcastImpl.getState(); #else @@ -251,6 +253,13 @@ bool ESPNOWBroadcast::removeCallback( ESPNOWBroadcast::receive_callback_t callba } +ESPNOWBroadcast::receive_filter_t ESPNOWBroadcast::registerFilter( ESPNOWBroadcast::receive_filter_t filter ) { + auto old = espnowBroadcastImpl._rxFilter; + espnowBroadcastImpl._rxFilter = filter; + return old; +} + + #ifdef ESP32 void ESPNOWBroadcastImpl::start() { @@ -398,7 +407,13 @@ void ESPNOWBroadcastImpl::onESPNowRxCallback(const uint8_t *mac, const uint8_t * rssi = 0; } - if (!espnowBroadcastImpl.queuedNetworkRingBuffer.push(mac, data, len, rssi)) { + if (espnowBroadcastImpl._rxFilter) { + if (!espnowBroadcastImpl._rxFilter(mac, data, len, rssi)) { + return; + } + } + + if(!espnowBroadcastImpl.queuedNetworkRingBuffer.push(mac, data, len, rssi)) { Serial.printf("Failed to queue message (%d bytes) to ring buffer. Dropping message\n", len); } else { #ifdef ESPNOW_CALLBACK_DEBUGGING diff --git a/wled00/espnow_broadcast.h b/wled00/espnow_broadcast.h index ae23b9ee3c..d14786065f 100644 --- a/wled00/espnow_broadcast.h +++ b/wled00/espnow_broadcast.h @@ -3,7 +3,7 @@ #ifndef WLED_DISABLE_ESPNOW_NEW -#include "const.h" +//#include "const.h" #ifndef WLED_ESPNOW_MAX_QUEUED_MESSAGES #define WLED_ESPNOW_MAX_QUEUED_MESSAGES 6 @@ -14,6 +14,9 @@ #endif #ifndef WLED_ESPNOW_MAX_REGISTERED_CALLBACKS + #ifndef WLED_MAX_USERMODS + #define WLED_MAX_USERMODS 1 + #endif #define WLED_ESPNOW_MAX_REGISTERED_CALLBACKS WLED_MAX_USERMODS+1 #endif @@ -31,6 +34,15 @@ class ESPNOWBroadcast { bool registerCallback( receive_callback_t callback ); bool removeCallback( receive_callback_t callback ); + // the receive filter happens from the WiFi task and this should not do any lengthly processing + // additionally thread synchronization may need to be done with the main application task thread + // only a single filter may be register at a given time + // The filter should return false if the received network message should be ignored and not + // processed by future callbacks + typedef bool (*receive_filter_t)(const uint8_t *sender, const uint8_t *data, uint8_t len, int8_t rssi); + receive_filter_t registerFilter( receive_filter_t filter = nullptr ); + + enum STATE { STOPPED = 0, STARTING, @@ -38,12 +50,15 @@ class ESPNOWBroadcast { MAX }; - STATE getState(); + STATE getState() const; + + bool isStarted() const { + return STATE::STARTED == getState(); + } protected: receive_callback_t _rxCallbacks[WLED_ESPNOW_MAX_REGISTERED_CALLBACKS] = {0}; static constexpr size_t _rxCallbacksSize = sizeof(_rxCallbacks)/sizeof(_rxCallbacks[0]); - }; extern ESPNOWBroadcast espnowBroadcast; From 594a08cb3be38fc9f64745270fe9e67c4c5a4a72 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Sun, 18 Aug 2024 17:53:04 -0700 Subject: [PATCH 27/50] fix esp8266 build --- wled00/espnow_broadcast.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index fe0b0c5427..818e2725c9 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -254,9 +254,13 @@ bool ESPNOWBroadcast::removeCallback( ESPNOWBroadcast::receive_callback_t callba } ESPNOWBroadcast::receive_filter_t ESPNOWBroadcast::registerFilter( ESPNOWBroadcast::receive_filter_t filter ) { +#ifdef ESP32 auto old = espnowBroadcastImpl._rxFilter; espnowBroadcastImpl._rxFilter = filter; return old; +#else + return nullptr; +#endif } From 6d7a769e9a9c6afada134e8eb1dc6dca79b989d5 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Sun, 18 Aug 2024 22:32:31 -0700 Subject: [PATCH 28/50] add debug counters to espnow --- wled00/espnow_broadcast.cpp | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index 818e2725c9..f6cfc1f397 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -34,6 +34,7 @@ ESP_EVENT_DEFINE_BASE(SYSTEM_EVENT); //#define ESPNOW_DEBUGGING //#define ESPNOW_CALLBACK_DEBUGGING // Serial is called from multiple threads +#define ESPNOW_DEBUG_COUNTERS #define BROADCAST_ADDR_ARRAY_INITIALIZER {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} #define WLED_ESPNOW_WIFI_CHANNEL 1 @@ -73,6 +74,12 @@ class ESPNOWBroadcastImpl : public ESPNOWBroadcast { receive_filter_t _rxFilter = nullptr; +#ifdef ESPNOW_DEBUG_COUNTERS + std::atomic _received {0}; + std::atomic _processed {0}; + std::atomic _loop {0}; +#endif + class QueuedNetworkRingBuffer { protected: //QueuedNetworkMessage messages[WLED_ESPNOW_MAX_QUEUED_MESSAGES]; @@ -182,16 +189,21 @@ bool ESPNOWBroadcastImpl::setupWiFi() { void ESPNOWBroadcast::loop(size_t maxMessagesToProcess /*= 1*/) { #ifdef ESP32 +#ifdef ESPNOW_DEBUG_COUNTERS + espnowBroadcastImpl._loop++; +#endif switch (espnowBroadcastImpl._state.load()) { case ESPNOWBroadcast::STARTING: // if WiFI is in starting state, actually stat ESPNow from our main task thread. espnowBroadcastImpl.start(); break; case ESPNOWBroadcast::STARTED: { - auto ndx = maxMessagesToProcess; - while(ndx-- > 0) { + while(maxMessagesToProcess-- > 0) { auto *msg = espnowBroadcastImpl.queuedNetworkRingBuffer.pop(); if (msg) { +#ifdef ESPNOW_DEBUG_COUNTERS + espnowBroadcastImpl._processed++; +#endif auto callback = _rxCallbacks; while( *callback ) { (*callback)(msg->mac, msg->data, msg->len, msg->rssi); @@ -229,6 +241,10 @@ bool ESPNOWBroadcast::registerCallback( ESPNOWBroadcast::receive_callback_t call // last element is always null size_t ndx; for (ndx = 0; ndx < _rxCallbacksSize-1; ndx++) { + // already registered + if (callback == _rxCallbacks[ndx]) { + break; + } if (nullptr == _rxCallbacks[ndx]) { _rxCallbacks[ndx] = callback; break; @@ -417,8 +433,22 @@ void ESPNOWBroadcastImpl::onESPNowRxCallback(const uint8_t *mac, const uint8_t * } } +#ifdef ESPNOW_DEBUG_COUNTERS + espnowBroadcastImpl._received++; +#endif if(!espnowBroadcastImpl.queuedNetworkRingBuffer.push(mac, data, len, rssi)) { - Serial.printf("Failed to queue message (%d bytes) to ring buffer. Dropping message\n", len); + Serial.printf("Failed to queue message (%d bytes) to ring buffer. Dropping message\n" +#ifdef ESPNOW_DEBUG_COUNTERS + "\tState: %d\t loop:0x%x\t recv:0x%x\t processed:0x%x\n" +#endif + , len +#ifdef ESPNOW_DEBUG_COUNTERS + , espnowBroadcastImpl.getState(), + espnowBroadcastImpl._loop.load(), + espnowBroadcastImpl._received.load(), + espnowBroadcastImpl._processed.load() +#endif + ); } else { #ifdef ESPNOW_CALLBACK_DEBUGGING char buf[128]; From 30b4b236104eabd97c6145cee8a6a0c68def4f7e Mon Sep 17 00:00:00 2001 From: Craig Link Date: Sun, 18 Aug 2024 22:16:09 -0700 Subject: [PATCH 29/50] re-enable serial input accidently disabled by merge - https://github.com/Aircoookie/WLED/commit/d03ad1f01c6b428dc3eb5674a8aa1dbf2bc7cdeb also current version of Espressif Ardunio SDK seems to break it as well --- platformio_tubes.ini | 4 +++- wled00/wled.cpp | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 75d8d20f6b..629f5fa374 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -7,7 +7,8 @@ ; For devices with those inputs use the [tubes] settings ; which adds those back in platform = espressif32@6.8.1 -platform_packages = ;framework-arduinoespressif32 @ 3.20017.0 +platform_packages = framework-arduinoespressif32 @ 3.20014.231204 +;platform_packages = ;framework-arduinoespressif32 @ 3.20017.0 build_unflags = -D LOROL_LITTLEFS -D CONFIG_ASYNC_TCP_USE_WDT @@ -30,6 +31,7 @@ build_flags = -D WLED_DISABLE_WEBSOCKETS -D WLED_DISABLE_ADALIGHT -D WLED_DISABLE_ESPNOW + -D WLED_DISABLE_SERIAL -D IRTYPE=0 lib_ignore = ESPAsyncTCP diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 5c64aa3b46..657339b11c 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -58,7 +58,9 @@ void WLED::loop() #ifndef WLED_DISABLE_ESPNOW handleRemote(); #endif + #ifndef WLED_DISABLE_SERIAL handleSerial(); + #endif handleImprovWifiScan(); handleNotifications(); handleTransitions(); From 00dc3382b6deeaa566502e2841d42d3e9dcea024 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Sun, 18 Aug 2024 23:38:17 -0700 Subject: [PATCH 30/50] add const to appropriate read-only functions --- usermods/Tubes/beats.h | 4 ++-- usermods/Tubes/controller.h | 8 +++---- usermods/Tubes/global_state.h | 40 +++++++++++++--------------------- usermods/Tubes/particle.h | 6 ++--- usermods/Tubes/virtual_strip.h | 14 ++++++------ 5 files changed, 31 insertions(+), 41 deletions(-) diff --git a/usermods/Tubes/beats.h b/usermods/Tubes/beats.h index d540ef46b5..617872e910 100644 --- a/usermods/Tubes/beats.h +++ b/usermods/Tubes/beats.h @@ -1,5 +1,5 @@ #pragma once - +#include "wled.h" #include "timer.h" #define DEFAULT_BPM 120 @@ -60,7 +60,7 @@ class BeatController { accum = 0; } - void print_bpm() { + void print_bpm() const { Serial.print(bpm >> 8); uint8_t frac = scale8(100, bpm & 0xFF); Serial.print(F(".")); diff --git a/usermods/Tubes/controller.h b/usermods/Tubes/controller.h index d760d11b66..8211a05029 100644 --- a/usermods/Tubes/controller.h +++ b/usermods/Tubes/controller.h @@ -592,7 +592,7 @@ class PatternController : public MessageReceiver { background_changed(); } - bool isShowingWled() { + bool isShowingWled() const { return current_state.pattern_id >= numInternalPatterns; } @@ -756,7 +756,7 @@ class PatternController : public MessageReceiver { set_wled_palette(background.palette_id); } - bool isUnderWledControl() { + bool isUnderWledControl() const { return paletteOverride || patternOverride; } @@ -891,7 +891,7 @@ class PatternController : public MessageReceiver { effects.update(first_strip, beat_frame, (BeatPulse)beat_pulse); } - CRGB getBlendedPixelColor(int32_t pos) { + CRGB getBlendedPixelColor(int32_t pos) const { // Calculate the color of the pixel at position i by blending the colors of the virtual strips CRGB color = CRGB::Black; @@ -947,7 +947,7 @@ class PatternController : public MessageReceiver { } } - accum88 parse_number(char *s) { + accum88 parse_number(char *s) const { uint16_t n=0, d=0; while (*s == ' ') diff --git a/usermods/Tubes/global_state.h b/usermods/Tubes/global_state.h index 1677b74de9..5042d41d62 100644 --- a/usermods/Tubes/global_state.h +++ b/usermods/Tubes/global_state.h @@ -23,32 +23,22 @@ class TubeState { void print() { uint16_t phrase = beat_frame >> 12; - Serial.print(F("[")); - Serial.print(phrase); - Serial.print(F(".")); - Serial.print((beat_frame >> 8) % 16); - Serial.print(F(" P")); - Serial.print(pattern_id); - Serial.print(F(",")); - Serial.print(pattern_sync_id); - Serial.print(F(" C")); - Serial.print(palette_id); - Serial.print(F(" E")); - Serial.print(effect_params.effect); - Serial.print(F(",")); - Serial.print(effect_params.pen); - Serial.print(F(",")); - Serial.print(effect_params.beat); - Serial.print(F(",")); - Serial.print(effect_params.chance); - Serial.print(F(" ")); - Serial.print(bpm >> 8); uint8_t frac = scale8(100, bpm & 0xFF); - Serial.print(F(".")); - if (frac < 10) - Serial.print(F("0")); - Serial.print(frac); - Serial.print(F("bpm]")); + char buf[128]; + sprintf(buf, "[%d.%d P%d,%d C%d E%d,%d,%d,%d %d.%02dbpm]", + phrase, + (beat_frame >> 8) % 16, + pattern_id, + pattern_sync_id, + palette_id, + effect_params.effect, + effect_params.pen, + effect_params.beat, + effect_params.chance, + bpm >> 8, + frac + ); + Serial.print(buf); } }; diff --git a/usermods/Tubes/particle.h b/usermods/Tubes/particle.h index db4f773f83..01e1399a04 100644 --- a/usermods/Tubes/particle.h +++ b/usermods/Tubes/particle.h @@ -60,7 +60,7 @@ class Particle { velocity = delta16(velocity, gravity); } - uint16_t age_frac16(BeatFrame_24_8 age) + uint16_t age_frac16(BeatFrame_24_8 age) const { if (age >= lifetime) return 65535; @@ -68,7 +68,7 @@ class Particle { return a / lifetime; } - uint16_t udelta16(uint16_t x, int16_t dx) + uint16_t udelta16(uint16_t x, int16_t dx) const { if (dx > 0 && 65535-x < dx) return 65335; @@ -77,7 +77,7 @@ class Particle { return x + dx; } - int16_t delta16(int16_t x, int16_t dx) + int16_t delta16(int16_t x, int16_t dx) const { if (dx > 0 && 32767-x < dx) return 32767; diff --git a/usermods/Tubes/virtual_strip.h b/usermods/Tubes/virtual_strip.h index 74731047b1..032599053f 100644 --- a/usermods/Tubes/virtual_strip.h +++ b/usermods/Tubes/virtual_strip.h @@ -66,7 +66,7 @@ class VirtualStrip { fade = Dead; } - int32_t length() { + int32_t length() const { // Try to be the same as the main segment, but not if it's too big auto len = strip.getMainSegment().length(); if (len > MAX_VIRTUAL_LEDS) @@ -83,7 +83,7 @@ class VirtualStrip { brightness = DEF_BRIGHT; } - bool isWled() { + bool isWled() const { return background.wled_fx_id != 0; } @@ -169,27 +169,27 @@ class VirtualStrip { } } - CRGB palette_color(uint8_t c, uint8_t offset=0, uint8_t brightness=255) { + CRGB palette_color(uint8_t c, uint8_t offset=0, uint8_t brightness=255) const { Segment& segment = strip.getMainSegment(); uint32_t color = segment.color_from_palette(c + offset, false, true, 255, brightness); return CRGB(color); } - CRGB hue_color(uint8_t offset=0, uint8_t saturation=255, uint8_t value=192) { + CRGB hue_color(uint8_t offset=0, uint8_t saturation=255, uint8_t value=192) const { return CHSV(hue + offset, saturation, value); } - uint8_t bpm_sin16( uint16_t lowest=0, uint16_t highest=65535 ) + uint8_t bpm_sin16( uint16_t lowest=0, uint16_t highest=65535 ) const { return scaled16to8(sin16( frame << 7 ) + 32768, lowest, highest); } - uint8_t bpm_cos16( uint16_t lowest=0, uint16_t highest=65535 ) + uint8_t bpm_cos16( uint16_t lowest=0, uint16_t highest=65535 ) const { return scaled16to8(cos16( frame << 7 ) + 32768, lowest, highest); } - CRGB getPixelColor(int32_t pos) { + CRGB getPixelColor(int32_t pos) const { return leds[pos % length()]; } From 3cf9edf591709a15512a4ce171bfbfa41693115f Mon Sep 17 00:00:00 2001 From: Craig Link Date: Mon, 19 Aug 2024 08:21:49 -0700 Subject: [PATCH 31/50] add exit counter for espnow loop --- wled00/espnow_broadcast.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index f6cfc1f397..0e0f6cd2a9 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -78,6 +78,7 @@ class ESPNOWBroadcastImpl : public ESPNOWBroadcast { std::atomic _received {0}; std::atomic _processed {0}; std::atomic _loop {0}; + std::atomic _exit {0}; #endif class QueuedNetworkRingBuffer { @@ -219,6 +220,9 @@ void ESPNOWBroadcast::loop(size_t maxMessagesToProcess /*= 1*/) { default: break; } +#ifdef ESPNOW_DEBUG_COUNTERS + espnowBroadcastImpl._exit++; +#endif #endif // ESP32 } @@ -439,12 +443,13 @@ void ESPNOWBroadcastImpl::onESPNowRxCallback(const uint8_t *mac, const uint8_t * if(!espnowBroadcastImpl.queuedNetworkRingBuffer.push(mac, data, len, rssi)) { Serial.printf("Failed to queue message (%d bytes) to ring buffer. Dropping message\n" #ifdef ESPNOW_DEBUG_COUNTERS - "\tState: %d\t loop:0x%x\t recv:0x%x\t processed:0x%x\n" + "\tState: %d\t loop:0x%x\t exit:0x%x recv:0x%x\t processed:0x%x\n" #endif , len #ifdef ESPNOW_DEBUG_COUNTERS , espnowBroadcastImpl.getState(), espnowBroadcastImpl._loop.load(), + espnowBroadcastImpl._exit.load(), espnowBroadcastImpl._received.load(), espnowBroadcastImpl._processed.load() #endif From f293d540dda60f4d682104130f0916b44efc106a Mon Sep 17 00:00:00 2001 From: Craig Link Date: Mon, 19 Aug 2024 08:58:04 -0700 Subject: [PATCH 32/50] add yield to espnow loop for good measure --- usermods/Tubes/debug.h | 8 +++++++- wled00/espnow_broadcast.cpp | 9 +++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/usermods/Tubes/debug.h b/usermods/Tubes/debug.h index afdb0bc910..3e9cf19f79 100644 --- a/usermods/Tubes/debug.h +++ b/usermods/Tubes/debug.h @@ -93,13 +93,19 @@ class DebugController { } Serial.println(); - Serial.printf("=== firmware: v%d from SSID %s %u.%u.%u.%u OTA=%d\n\n", + Serial.printf("=== firmware: v%d " +#ifdef TUBES_AUTOUPDATER + "from SSID %s %u.%u.%u.%u " +#endif + "OTA=%d\n\n", controller.updater.current_version.version, +#ifdef TUBES_AUTOUPDATER controller.updater.current_version.ssid, controller.updater.current_version.host[0], controller.updater.current_version.ssid[1], controller.updater.current_version.ssid[2], controller.updater.current_version.ssid[3], +#endif controller.updater.status ); diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index 0e0f6cd2a9..984d0ddca7 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -205,15 +205,16 @@ void ESPNOWBroadcast::loop(size_t maxMessagesToProcess /*= 1*/) { #ifdef ESPNOW_DEBUG_COUNTERS espnowBroadcastImpl._processed++; #endif - auto callback = _rxCallbacks; - while( *callback ) { - (*callback)(msg->mac, msg->data, msg->len, msg->rssi); - callback++; + for( auto ndx = 0; ndx < (sizeof(_rxCallbacks)/sizeof(_rxCallbacks[0]))-1; ndx++) { + if(_rxCallbacks[ndx]) { + _rxCallbacks[0](msg->mac, msg->data, msg->len, msg->rssi); + } } espnowBroadcastImpl.queuedNetworkRingBuffer.popComplete(msg); } else { break; } + yield(); } break; } From 473115bc3d04b49af401019e2fdca172d0d1ead3 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Mon, 19 Aug 2024 09:00:00 -0700 Subject: [PATCH 33/50] add yield to espnow loop for good measure --- wled00/espnow_broadcast.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index 984d0ddca7..6700bb5672 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -207,7 +207,7 @@ void ESPNOWBroadcast::loop(size_t maxMessagesToProcess /*= 1*/) { #endif for( auto ndx = 0; ndx < (sizeof(_rxCallbacks)/sizeof(_rxCallbacks[0]))-1; ndx++) { if(_rxCallbacks[ndx]) { - _rxCallbacks[0](msg->mac, msg->data, msg->len, msg->rssi); + _rxCallbacks[ndx](msg->mac, msg->data, msg->len, msg->rssi); } } espnowBroadcastImpl.queuedNetworkRingBuffer.popComplete(msg); From 00b20b2f2d9ada8d337c841f6a3335eea66f1bcf Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Mon, 19 Aug 2024 09:57:31 -0700 Subject: [PATCH 34/50] Remove infinite loops from pattern generators; add some more debugging --- usermods/Tubes/debug.h | 6 +++++ usermods/Tubes/node.h | 16 +++++++++---- usermods/Tubes/pattern.h | 42 +++++++++++++++++----------------- usermods/Tubes/virtual_strip.h | 23 ++++++++++--------- 4 files changed, 50 insertions(+), 37 deletions(-) diff --git a/usermods/Tubes/debug.h b/usermods/Tubes/debug.h index 3e9cf19f79..ba5d234801 100644 --- a/usermods/Tubes/debug.h +++ b/usermods/Tubes/debug.h @@ -64,6 +64,12 @@ class DebugController { if (controller.sound.active) { Serial.print("SOUND "); } + if (controller.node.isLeading()) { + Serial.print("LEADING "); + } + if (controller.node.isFollowing()) { + Serial.print("FOLLLOWING "); + } Serial.printf("role=%d power_save=%d\n", controller.role, controller.power_save diff --git a/usermods/Tubes/node.h b/usermods/Tubes/node.h index 2c44f4861d..c22b3af92c 100644 --- a/usermods/Tubes/node.h +++ b/usermods/Tubes/node.h @@ -161,9 +161,10 @@ class LightNode { // If a message indicates that another node is following this one, or // should be (it's not following anything, but this node's ID is higher) // enter or continue re-broadcasting mode. - if (node.uplinkId == header.id - || (node.uplinkId == 0 && node.id < header.id)) { - Serial.printf(" %03X/%03X is following me", node.id, node.uplinkId); + if (node.uplinkId == header.id || (node.uplinkId == 0 && node.id < header.id)) { + if (!isLeading()) { + Serial.printf(" LEADING because %03X/%03X is following me\n", node.id, node.uplinkId); + } rebroadcastTimer.start(REBROADCAST_TIME); } } @@ -240,7 +241,7 @@ class LightNode { } // Re-broadcast the message if appropriate - if (!rebroadcastTimer.ended() && message->recipients != RECIPIENTS_INFO) { + if (isLeading() && message->recipients != RECIPIENTS_INFO) { static NodeMessage msg; memcpy(&msg, &message, len); msg.header = header; @@ -345,7 +346,6 @@ class LightNode { if (isFollowing() && uplinkTimer.ended()) { follow(NULL); } - } void reset(MeshId id = 0) { @@ -384,6 +384,12 @@ class LightNode { bool isFollowing() const { return header.uplinkId != 0; } + bool isLeading() const { + // For now, leading mode is defined as being in re-broadcast mode for any reason. + // Any node that thinks it has the highest ID is leading, but so are any nodes that + // have seen another node that should be following the leader it is following. + return !rebroadcastTimer.ended(); + } protected: diff --git a/usermods/Tubes/pattern.h b/usermods/Tubes/pattern.h index be940c87d9..0bc32f35a8 100644 --- a/usermods/Tubes/pattern.h +++ b/usermods/Tubes/pattern.h @@ -6,14 +6,14 @@ void rainbow(VirtualStrip *strip) { // FastLED's built-in rainbow generator - fill_rainbow( strip->leds, strip->length(), strip->hue, 3); + fill_rainbow( strip->leds, strip->num_leds, strip->hue, 3); } void palette_wave(VirtualStrip *strip) { // FastLED's built-in rainbow generator uint8_t hue = strip->hue; - for (uint8_t i=0; i < strip->length(); i++) { + for (auto i=0; i < strip->num_leds; i++) { CRGB c = strip->palette_color(i, hue); nscale8x3(c.r, c.g, c.b, sin8(hue*8)); strip->leds[i] = c; @@ -23,35 +23,35 @@ void palette_wave(VirtualStrip *strip) void particleTest(VirtualStrip *strip) { - fill_solid( strip->leds, strip->length(), CRGB::Black); + fill_solid( strip->leds, strip->num_leds, CRGB::Black); fill_solid( strip->leds, 2, strip->palette_color(0, strip->hue)); } void solidBlack(VirtualStrip *strip) { - fill_solid( strip->leds, strip->length(), CRGB::Black); + strip->fill(CRGB::Black); } -void solidWhite(VirtualStrip *strip) +void solidWhite(VirtualStrip *strip) { - fill_solid( strip->leds, strip->length(), CRGB::White); + strip->fill(CRGB::White); } void solidRed(VirtualStrip *strip) { - fill_solid( strip->leds, strip->length(), CRGB::Red); + strip->fill(CRGB::Red); } void solidBlue(VirtualStrip *strip) { - fill_solid( strip->leds, strip->length(), CRGB::Blue); + strip->fill(CRGB::Blue); } void confetti(VirtualStrip *strip) { strip->darken(2); - int pos = random16(strip->length()); + int pos = random16(strip->num_leds); strip->leds[pos] += strip->palette_color(random8(64), strip->hue); } @@ -65,8 +65,8 @@ void biwave(VirtualStrip *strip) uint16_t r = strip->frame * 32; r = cos16( r + random_offset ) + 32768; - uint8_t p1 = scaled16to8(l, 0, strip->length()-1); - uint8_t p2 = scaled16to8(r, 0, strip->length()-1); + uint8_t p1 = scaled16to8(l, 0, strip->num_leds-1); + uint8_t p2 = scaled16to8(r, 0, strip->num_leds-1); if (p2 < p1) { uint16_t t = p1; @@ -90,14 +90,14 @@ void sinelon(VirtualStrip *strip) // a colored dot sweeping back and forth, with fading trails strip->darken(30); - int pos = scale16(sin16( strip->frame << 5 ) + 32768, strip->length()-1); // beatsin16 re-implemented + int pos = scale16(sin16( strip->frame << 5 ) + 32768, strip->num_leds-1); // beatsin16 re-implemented strip->leds[pos] += strip->hue_color(); } void bpm_palette(VirtualStrip *strip) { uint8_t beat = strip->bpm_sin16(64, 255); - for (int i = 0; i < strip->length(); i++) { + for (auto i = 0; i < strip->num_leds; i++) { CRGB c = strip->palette_color(i*2, strip->hue, beat-strip->hue+(i*10)); strip->leds[i] = c; } @@ -109,7 +109,7 @@ void bpm(VirtualStrip *strip) CRGBPalette16 palette = PartyColors_p; uint8_t beat = strip->bpm_sin16(64, 255); - for (int i = 0; i < strip->length(); i++) { + for (auto i = 0; i < strip->num_leds; i++) { strip->leds[i] = ColorFromPalette(palette, strip->hue+(i*2), beat-strip->hue+(i*10)); } } @@ -120,17 +120,17 @@ void juggle(VirtualStrip *strip) strip->darken(5); byte dothue = 0; - for( int i = 0; i < 8; i++) { + for (auto i = 0; i < 8; i++) { CRGB c = strip->palette_color(dothue + strip->hue); // c = CHSV(dothue, 200, 255); - strip->leds[beatsin16( i+7, 0, strip->length()-1 )] |= c; + strip->leds[beatsin16( i+7, 0, strip->num_leds-1 )] |= c; dothue += 32; } } -uint8_t noise[MAX_VIRTUAL_LEDS]; +uint8_t noise[MAX_VIRTUAL_LEDS] = {0}; -void fillnoise8(uint32_t frame, uint8_t num_leds) { +void fillnoise8(uint32_t frame, int32_t num_leds) { uint16_t scale = 17; uint8_t dataSmoothing = 240; @@ -139,7 +139,7 @@ void fillnoise8(uint32_t frame, uint8_t num_leds) { num_leds = max_leds; } - for (int i = 0; i < num_leds; i++) { + for (auto i = 0; i < num_leds; i++) { uint8_t data = inoise8(i * scale, frame>>2); // The range of the inoise8 function is roughly 16-238. @@ -156,9 +156,9 @@ void fillnoise8(uint32_t frame, uint8_t num_leds) { void drawNoise(VirtualStrip *strip) { // generate noise data - fillnoise8(strip->frame >> 2, strip->length()); + fillnoise8(strip->frame >> 2, strip->num_leds); - for(int i = 0; i < strip->length(); i++) { + for (auto i = 0; i < strip->num_leds; i++) { CRGB color = strip->palette_color(noise[i], strip->hue); strip->leds[i] = color; } diff --git a/usermods/Tubes/virtual_strip.h b/usermods/Tubes/virtual_strip.h index 032599053f..13498bd709 100644 --- a/usermods/Tubes/virtual_strip.h +++ b/usermods/Tubes/virtual_strip.h @@ -45,6 +45,7 @@ class VirtualStrip { public: CRGB leds[MAX_VIRTUAL_LEDS]; + uint16_t num_leds = 1; // only temporary until the first loop uint8_t brightness; // Fade in/out @@ -66,14 +67,7 @@ class VirtualStrip { fade = Dead; } - int32_t length() const { - // Try to be the same as the main segment, but not if it's too big - auto len = strip.getMainSegment().length(); - if (len > MAX_VIRTUAL_LEDS) - return MAX_VIRTUAL_LEDS; - return len; - } - + void load(Background &b, uint8_t fs=DEFAULT_FADE_SPEED) { background = b; @@ -97,12 +91,12 @@ class VirtualStrip { void darken(uint8_t amount=10) { - fadeToBlackBy( leds, length(), amount); + fadeToBlackBy( leds, num_leds, amount); } void fill(CRGB crgb) { - fill_solid( leds, length(), crgb); + fill_solid( leds, num_leds, crgb); } void update(BeatFrame_24_8 fr, uint8_t bp) @@ -112,6 +106,13 @@ class VirtualStrip { frame = fr; + // Try to keep our number of LEDs as the same as the main segment, + // but not if it's too big for the buffer array. + auto len = strip.getMainSegment().length(); + if (len > MAX_VIRTUAL_LEDS) + len = MAX_VIRTUAL_LEDS; + num_leds = len; + switch (this->background.sync) { case All: break; @@ -190,7 +191,7 @@ class VirtualStrip { } CRGB getPixelColor(int32_t pos) const { - return leds[pos % length()]; + return leds[pos % num_leds]; } }; From fcee6ab6139732498a17256152bdc191b12b7810 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Mon, 19 Aug 2024 10:33:59 -0700 Subject: [PATCH 35/50] some basic constructor cleanup intialize struct variables remove double initialization disabled espnow debug counters --- usermods/Tubes/options.h | 4 ++-- usermods/Tubes/virtual_strip.h | 8 ++++---- wled00/espnow_broadcast.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/usermods/Tubes/options.h b/usermods/Tubes/options.h index 6daac941f8..0c4b28e7ea 100644 --- a/usermods/Tubes/options.h +++ b/usermods/Tubes/options.h @@ -28,8 +28,8 @@ typedef struct ControlParameters { ControlParameters(Duration d=MediumDuration, Energy e=Chill) : duration(d), energy(e) {}; public: - Duration duration=MediumDuration; - Energy energy=Chill; + Duration duration; + Energy energy; } ControlParams; typedef enum PenMode: uint8_t { diff --git a/usermods/Tubes/virtual_strip.h b/usermods/Tubes/virtual_strip.h index 13498bd709..4e4232d18d 100644 --- a/usermods/Tubes/virtual_strip.h +++ b/usermods/Tubes/virtual_strip.h @@ -16,10 +16,10 @@ typedef void (*BackgroundFn)(VirtualStrip *strip); class Background { public: - BackgroundFn animate; - uint8_t wled_fx_id; - uint8_t palette_id; - SyncMode sync=All; + BackgroundFn animate {nullptr}; + uint8_t wled_fx_id {0}; + uint8_t palette_id {0}; + SyncMode sync {All}; }; typedef enum VirtualStripFade { diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index 6700bb5672..68d5593f87 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -34,7 +34,7 @@ ESP_EVENT_DEFINE_BASE(SYSTEM_EVENT); //#define ESPNOW_DEBUGGING //#define ESPNOW_CALLBACK_DEBUGGING // Serial is called from multiple threads -#define ESPNOW_DEBUG_COUNTERS +//#define ESPNOW_DEBUG_COUNTERS #define BROADCAST_ADDR_ARRAY_INITIALIZER {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} #define WLED_ESPNOW_WIFI_CHANNEL 1 From eb87f63a61f9f8936485342152fac75fc65aa2b7 Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Mon, 19 Aug 2024 19:27:08 -0700 Subject: [PATCH 36/50] Revert to 5.3.0 IDF for now --- platformio_tubes.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 629f5fa374..352e7bce95 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -6,8 +6,8 @@ ; -- ir remotes ; For devices with those inputs use the [tubes] settings ; which adds those back in -platform = espressif32@6.8.1 -platform_packages = framework-arduinoespressif32 @ 3.20014.231204 +platform = espressif32@5.3.0 +platform_packages = ;platform_packages = ;framework-arduinoespressif32 @ 3.20017.0 build_unflags = -D LOROL_LITTLEFS From 7713d411adee05a571cfdb8c2b88bd3cb85cae13 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Mon, 19 Aug 2024 20:39:22 -0700 Subject: [PATCH 37/50] restart ESPNOW after WiFi AP stopped --- usermods/Tubes/controller.h | 9 ++++++++- wled00/espnow_broadcast.cpp | 11 ++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/usermods/Tubes/controller.h b/usermods/Tubes/controller.h index 8211a05029..4be21d0cce 100644 --- a/usermods/Tubes/controller.h +++ b/usermods/Tubes/controller.h @@ -1009,7 +1009,14 @@ class PatternController : public MessageReceiver { } setBrightness(arg >> 8); return; - + case 'a': + Serial.println("Turning on WiFi access point."); + WLED::instance().initAP(true); + return; + case 'q': + Serial.println("Turning off WiFi access point."); + WiFi.disconnect(true); + return; case 'b': if (arg < 60*256) { Serial.println(F("nope")); diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index 68d5593f87..450355c7ee 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -2,7 +2,7 @@ #ifndef WLED_DISABLE_ESPNOW_NEW #include #include - +#include #if defined ESP32 #include #include @@ -143,6 +143,7 @@ bool ESPNOWBroadcast::setup() { Serial.printf("esp_event_loop_create_default() err %d\n", err); return false; } + err = esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_START, ESPNOWBroadcastImpl::onWiFiEvent, nullptr, nullptr); if ( ESP_OK != err ) { Serial.printf("esp_event_handler_instance_register(WIFI_EVENT_STA_START) err %d\n", err); @@ -158,6 +159,12 @@ bool ESPNOWBroadcast::setup() { Serial.printf("esp_event_handler_instance_register(WIFI_EVENT_AP_START) err %d\n", err); return false; } + + // err = esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, ESPNOWBroadcastImpl::onWiFiEvent, nullptr, nullptr); + // if ( ESP_OK != err ) { + // Serial.printf("esp_event_handler_instance_register(ESP_EVENT_ANY_ID) err %d\n", err); + // return false; + // } #endif setup = espnowBroadcastImpl.setupWiFi(); @@ -382,6 +389,8 @@ void ESPNOWBroadcastImpl::onWiFiEvent(void* arg, esp_event_base_t event_base, in } case WIFI_EVENT_STA_STOP: + lastReconnectAttempt = 0; + // fall thru case WIFI_EVENT_AP_START: { ESPNOWBroadcast::STATE started {ESPNOWBroadcast::STARTED}; ESPNOWBroadcast::STATE starting {ESPNOWBroadcast::STARTING}; From 3976a57de2af2f160b41f34d238a0587caad9533 Mon Sep 17 00:00:00 2001 From: Craig Link Date: Tue, 20 Aug 2024 08:55:06 -0700 Subject: [PATCH 38/50] athom-c3 fixes --- platformio_tubes.ini | 21 +++++++++++++-------- wled00/espnow_broadcast.cpp | 29 +++++++++++++++++++---------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 352e7bce95..1faf04fc72 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -62,6 +62,7 @@ lib_ignore = ${env:esp32_quinled_diguno.lib_ignore} lib_deps = ${env:esp32_quinled_diguno.lib_deps} IRremoteESP8266 @ 2.8.6 + [env:esp32_quinled_dig2go_tubes] extends = env:esp32_quinled_dig2go platform = ${tubes.platform} @@ -69,7 +70,7 @@ platform_packages = ${tubes.platform_packages} build_unflags = ${tubes.build_unflags} ${env:esp32_quinled_dig2go} -build_flags = +build_flags = -D WLED_RELEASE_NAME=DIG2GO_TUBES ${tubes.build_flags} ${env:esp32_quinled_dig2go.build_flags} -D FASTLED_ESP32_SPI_BUS=HSPI @@ -96,7 +97,7 @@ build_unflags = ${env:esp32s3dev_8MB_PSRAM_opi.build_unflags} -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MSC_ON_BOOT=0 -D ARDUINO_DFU_ON_BOOT=0 -build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=esp32-s3-matrix-m1 +build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32_S3_MATRIX_M1 -D WLED_WATCHDOG_TIMEOUT=0 -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 @@ -111,8 +112,10 @@ lib_ignore = ${env:esp32s3dev_8MB_PSRAM_opi.lib_ignore} [env:esp32-s3-matrix-m1_tubes] extends = env:esp32-s3-matrix-m1 -platform = ${tubes.platform} -platform_packages = ${tubes.platform_packages} +platform = espressif32@6.8.1 +platform_packages = +;platform = ${tubes.platform} +;platform_packages = ${tubes.platform_packages} board_build.partitions = tools/WLED_ESP32_4MB_noOTA.csv build_unflags = ${env:esp32-s3-matrix-m1.build_unflags} ${tubes_no_mic.build_unflags} @@ -142,17 +145,19 @@ build_flags = ${env:esp32c3dev.build_flags} [env:esp32-c3-athom_tubes] extends = env:esp32-c3-athom -platform = ${tubes_no_mic.platform} -platform_packages = ${tubes_no_mic.platform_packages} +platform = espressif32@6.8.1 +platform_packages = +;platform = ${tubes_no_mic.platform} +;platform_packages = ${tubes_no_mic.platform_packages} build_unflags = ${env:esp32-c3-athom.build_unflags} ${tubes_no_mic.build_unflags} -build_flags = +build_flags = ${common.build_flags} -D WLED_RELEASE_NAME=ESP32_C3_ATHOM_TUBES ${tubes_no_mic.build_flags} - -D WLED_WATCHDOG_TIMEOUT=0 -D LEDPIN=10 -D BTNPIN=9 -D FASTLED_ESP32_SPI_BUS=HSPI -D NUM_STRIPS=1 -D DEFAULT_LED_COUNT=150 + ;-D WLED_WIFI_POWER_SETTING=WIFI_POWER_8_5dBm lib_ignore = ${env:esp32-c3-athom.lib_ignore} ${tubes_no_mic.lib_ignore} lib_deps = diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index 450355c7ee..f145d1debd 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -34,13 +34,14 @@ ESP_EVENT_DEFINE_BASE(SYSTEM_EVENT); //#define ESPNOW_DEBUGGING //#define ESPNOW_CALLBACK_DEBUGGING // Serial is called from multiple threads +//#define ESPNOW_EVENT_DEBUGGING //#define ESPNOW_DEBUG_COUNTERS #define BROADCAST_ADDR_ARRAY_INITIALIZER {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} #define WLED_ESPNOW_WIFI_CHANNEL 1 #ifndef WLED_WIFI_POWER_SETTING -#define WLED_WIFI_POWER_SETTING WIFI_POWER_15dBm +#define WLED_WIFI_POWER_SETTING WIFI_POWER_18_5dBm #endif typedef struct { @@ -144,6 +145,13 @@ bool ESPNOWBroadcast::setup() { return false; } + #ifdef ESPNOW_EVENT_DEBUGGING + err = esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, ESPNOWBroadcastImpl::onWiFiEvent, nullptr, nullptr); + if ( ESP_OK != err ) { + Serial.printf("esp_event_handler_instance_register(ESP_EVENT_ANY_ID) err %d\n", err); + return false; + } + #else err = esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_START, ESPNOWBroadcastImpl::onWiFiEvent, nullptr, nullptr); if ( ESP_OK != err ) { Serial.printf("esp_event_handler_instance_register(WIFI_EVENT_STA_START) err %d\n", err); @@ -159,13 +167,8 @@ bool ESPNOWBroadcast::setup() { Serial.printf("esp_event_handler_instance_register(WIFI_EVENT_AP_START) err %d\n", err); return false; } - - // err = esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, ESPNOWBroadcastImpl::onWiFiEvent, nullptr, nullptr); - // if ( ESP_OK != err ) { - // Serial.printf("esp_event_handler_instance_register(ESP_EVENT_ANY_ID) err %d\n", err); - // return false; - // } -#endif + #endif // ESPNOW_EVENT_DEBUGGING +#endif ESP_IDF_VERSION setup = espnowBroadcastImpl.setupWiFi(); #endif //ESP32 @@ -190,6 +193,7 @@ bool ESPNOWBroadcastImpl::setupWiFi() { return false; } + yield(); return true; } #endif //ESP32 @@ -302,11 +306,13 @@ void ESPNOWBroadcastImpl::start() { auto status = WiFi.status(); if ( status >= WL_DISCONNECTED ) { if (esp_wifi_start() == ESP_OK) { + yield(); if (!WiFi.setTxPower(WLED_WIFI_POWER_SETTING)) { auto power = WiFi.getTxPower(); Serial.printf("setTxPower(%d) failed. getTX: %d\n", WLED_WIFI_POWER_SETTING, power); } if (esp_now_init() == ESP_OK) { + yield(); if (esp_now_register_recv_cb(ESPNOWBroadcastImpl::onESPNowRxCallback) == ESP_OK) { static esp_now_peer_info_t peer = { BROADCAST_ADDR_ARRAY_INITIALIZER, @@ -376,9 +382,9 @@ void ESPNOWBroadcastImpl::onWiFiEvent(void* arg, esp_event_base_t event_base, in #ifdef ESPNOW_DEBUGGING #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0) - Serial.printf("WiFiEvent( %d )\n", event_id ); + Serial.printf("WiFiEvent( %d )\n", event_id ); #else - Serial.printf("WiFiEvent( %s )\n", WiFi.eventName((arduino_event_id_t)event_id) ); + Serial.printf("WiFiEvent( %s )\n", WiFi.eventName((arduino_event_id_t)event_id) ); #endif #endif switch (event_id) { @@ -443,6 +449,9 @@ void ESPNOWBroadcastImpl::onESPNowRxCallback(const uint8_t *mac, const uint8_t * if (espnowBroadcastImpl._rxFilter) { if (!espnowBroadcastImpl._rxFilter(mac, data, len, rssi)) { +#ifdef ESPNOW_CALLBACK_DEBUGGING + Serial.printf("Filtering message of len %d\n", len); +#endif return; } } From 95ced63eb0db65c8ad63e1804ca6c95fa93a4d9a Mon Sep 17 00:00:00 2001 From: Craig Link Date: Tue, 20 Aug 2024 08:58:10 -0700 Subject: [PATCH 39/50] out WLED_RELEASE_NAME macro to info json --- wled00/json.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wled00/json.cpp b/wled00/json.cpp index af8ed89ef6..9e835d1382 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -609,6 +609,9 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme } } +#define _MACRO_TO_STR(x) #x +#define MACRO_TO_STR(x) _MACRO_TO_STR(x) + void serializeInfo(JsonObject root) { root[F("ver")] = versionString; @@ -791,6 +794,7 @@ void serializeInfo(JsonObject root) root[F("brand")] = "WLED"; root[F("product")] = F("FOSS"); + root[F("release")] = MACRO_TO_STR(WLED_RELEASE_NAME); root["mac"] = escapedMac; char s[16] = ""; if (Network.isConnected()) From 85709057808ce2c6a3bdf0cef8f58c766550faae Mon Sep 17 00:00:00 2001 From: Craig Link Date: Tue, 20 Aug 2024 11:36:13 -0700 Subject: [PATCH 40/50] yield for c3 network startup --- platformio_tubes.ini | 7 ++++--- wled00/espnow_broadcast.cpp | 4 ++-- wled00/wled.cpp | 14 +++++++++++++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 1faf04fc72..6491a724f2 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -70,6 +70,7 @@ platform_packages = ${tubes.platform_packages} build_unflags = ${tubes.build_unflags} ${env:esp32_quinled_dig2go} + -D WLED_RELEASE_NAME build_flags = -D WLED_RELEASE_NAME=DIG2GO_TUBES ${tubes.build_flags} ${env:esp32_quinled_dig2go.build_flags} @@ -97,7 +98,7 @@ build_unflags = ${env:esp32s3dev_8MB_PSRAM_opi.build_unflags} -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MSC_ON_BOOT=0 -D ARDUINO_DFU_ON_BOOT=0 -build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32_S3_MATRIX_M1 +build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_MATRIX_M1 -D WLED_WATCHDOG_TIMEOUT=0 -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 @@ -151,13 +152,13 @@ platform_packages = ;platform_packages = ${tubes_no_mic.platform_packages} build_unflags = ${env:esp32-c3-athom.build_unflags} ${tubes_no_mic.build_unflags} -build_flags = ${common.build_flags} -D WLED_RELEASE_NAME=ESP32_C3_ATHOM_TUBES +build_flags = ${common.build_flags} -D WLED_RELEASE_NAME=ESP32-C3_ATHOM_TUBES ${tubes_no_mic.build_flags} -D LEDPIN=10 -D BTNPIN=9 -D FASTLED_ESP32_SPI_BUS=HSPI -D NUM_STRIPS=1 -D DEFAULT_LED_COUNT=150 - ;-D WLED_WIFI_POWER_SETTING=WIFI_POWER_8_5dBm + -D WLED_WIFI_POWER_SETTING=WIFI_POWER_15dBm lib_ignore = ${env:esp32-c3-athom.lib_ignore} ${tubes_no_mic.lib_ignore} lib_deps = diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index f145d1debd..842b22fd1d 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -168,7 +168,7 @@ bool ESPNOWBroadcast::setup() { return false; } #endif // ESPNOW_EVENT_DEBUGGING -#endif ESP_IDF_VERSION +#endif // ESP_IDF_VERSION setup = espnowBroadcastImpl.setupWiFi(); #endif //ESP32 @@ -381,7 +381,7 @@ void ESPNOWBroadcastImpl::onWiFiEvent(void* arg, esp_event_base_t event_base, in if ( event_base == WIFI_EVENT ) { #ifdef ESPNOW_DEBUGGING - #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 0, 0) + #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0) Serial.printf("WiFiEvent( %d )\n", event_id ); #else Serial.printf("WiFiEvent( %s )\n", WiFi.eventName((arduino_event_id_t)event_id) ); diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 657339b11c..98ba39426f 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -542,8 +542,9 @@ void WLED::beginStrip() void WLED::initAP(bool resetAP) { - if (apBehavior == AP_BEHAVIOR_BUTTON_ONLY && !resetAP) + if (apBehavior == AP_BEHAVIOR_BUTTON_ONLY && !resetAP) { return; + } if (resetAP) { WLED_SET_AP_SSID(); @@ -557,10 +558,17 @@ void WLED::initAP(bool resetAP) WiFi.setTxPower(WIFI_POWER_8_5dBm); #endif + Serial.printf("WLED::initAP - apActive: %s", apActive ? "true" : "false"); + if (!apActive) // start captive portal if AP active { + yield(); + Serial.println("WLED::initAP - starting captive portal"); + DEBUG_PRINTLN(F("Init AP interfaces")); server.begin(); + yield(); + if (udpPort > 0 && udpPort != ntpLocalPort) { udpConnected = notifierUdp.begin(udpPort); } @@ -570,9 +578,13 @@ void WLED::initAP(bool resetAP) if (udpPort2 > 0 && udpPort2 != ntpLocalPort && udpPort2 != udpPort && udpPort2 != udpRgbPort) { udp2Connected = notifier2Udp.begin(udpPort2); } + yield(); + e131.begin(false, e131Port, e131Universe, E131_MAX_UNIVERSE_COUNT); ddp.begin(false, DDP_DEFAULT_PORT); + yield(); + dnsServer.setErrorReplyCode(DNSReplyCode::NoError); dnsServer.start(53, "*", WiFi.softAPIP()); } From 1520f7986b8ec078a37e4d35a4a6920946dd858c Mon Sep 17 00:00:00 2001 From: Craig Link Date: Tue, 20 Aug 2024 13:39:10 -0700 Subject: [PATCH 41/50] update base on board variant and reset the wifi after update --- usermods/Tubes/firmware.sh | 38 +++++++++++++++--- usermods/Tubes/firmware_test.sh | 68 +++++++++++++++++++++++++++++++++ wled00/espnow_broadcast.cpp | 2 +- wled00/json.cpp | 4 -- wled00/wled.cpp | 10 +++-- 5 files changed, 109 insertions(+), 13 deletions(-) create mode 100644 usermods/Tubes/firmware_test.sh diff --git a/usermods/Tubes/firmware.sh b/usermods/Tubes/firmware.sh index 20a8a544cb..a8bd246411 100755 --- a/usermods/Tubes/firmware.sh +++ b/usermods/Tubes/firmware.sh @@ -40,11 +40,39 @@ update_config() { } update_firmware() { - echo "Updating firmware via OTA" - curl -s -F "update=@../../build_output/firmware/tubes.bin" -H "Connection: close" --no-keepalive $1/update >/dev/null - echo "Updated; wait..." - sleep 5 - update_config $1 + echo "Getting info" + json=$( curl -s http://$1/json/si ) + + arch=$(echo "$json" | jq -r '.["info"].arch') + name=$(echo "$json" | jq -r '.["info"].name') + echo "arch: $arch name: $name" + + firmware= + + if [ ! -z "$name" ]; then + if [ "dig2go" == "$name" ]; then + firmware="esp32_quinled_dig2go_tubes.bin" + fi + fi + + if [ -z "$firmware" ] && [ ! -z "$arch" ]; then + if [ "ESP32-C3" == "$arch" ]; then + firmware="esp32-c3-athom_tubes.bin" + elif [ "esp32" == "$arch" ]; then + firmware="esp32_quinled_dig2go_tubes.bin" + fi + fi + + if [ -z "$firmware" ]; then + echo "firmware not set - not updating OTA" + curl -s http://$1/reset -H "Connection: close" >/dev/null + else + echo "Updating $firmware firmware via OTA" + curl -s -F "update=@../../build_output/firmware/$firmware" -H "Connection: close" --no-keepalive $1/update >/dev/null + echo "Updated; wait..." + sleep 5 + update_config $1 + fi } connect() { diff --git a/usermods/Tubes/firmware_test.sh b/usermods/Tubes/firmware_test.sh new file mode 100644 index 0000000000..bdfcd3462f --- /dev/null +++ b/usermods/Tubes/firmware_test.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# Updates new boards (which start as broadcasting on WLED-AP) to custom firmware +# Will update as many boards as are plugged in, one at a time. + + +# Two ways to use it: +# 1) ./firmware.sh +# This will update all boards with open APs named WLED-AP +# 2) ./firmware.sh batch +# This will update all boards with open APs named WLED-AP or WLED-UPDATE +# This is useful for updating a batch of boards at once +# To put a board in this mode, send it a V## command with a version higher than the current one +# There's also: +# 3) ./firmware.sh upload +# This will upload the firmware to the internet server, but not update any boards +# Internet upload is not working 100% yet, so this is not recommended + + +WLEDPATH=../../build_output/firmware +ESPPATH=~/.platformio/packages/framework-arduinoespressif32/tools + +update_config() { + # No longer update configs? comment this + # return; + + echo "Updating configuration via OTA" +# curl -s http://$1/upload -F "data=@default_config.json;filename=/cfg.json" -H "Connection: close" --no-keepalive + echo "Configured; wait..." +# curl -s http://$1/reset -H "Connection: close" >/dev/null +} + + +update_firmware() { + + echo "Getting info" + json=$( curl -s http://$1/json/si ) + + arch=$(echo "$json" | jq -r '.["info"].arch') + name=$(echo "$json" | jq -r '.["info"].name') + echo "$arch $name" + + firmware= + + if [ ! -z "$name" ]; then + if [ "dig2go" == "$name" ]; then + firmware="esp32_quinled_dig2go_tubes.bin" + fi + fi + + if [ -z "$firmware" ] && [ ! -z "$arch" ]; then + if [ "ESP32-C3" == "$arch" ]; then + firmware="esp32-c3-athom_tubes.bin" + elif [ "esp32" == "$arch" ]; then + firmware="esp32_quinled_dig2go_tubes.bin" + fi + fi + + if [ -z "$firmware" ]; then + echo "firmware not set - not updating OTA" + curl -s http://$1/reset -H "Connection: close" >/dev/null + else + echo "Updating $firmware firmware via OTA" + curl -s -F "update=@../../build_output/firmware/$firmware" -H "Connection: close" --no-keepalive $1/update >/dev/null + fi +} + +update_firmware $1 diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index 842b22fd1d..b7bb9f4afe 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -381,7 +381,7 @@ void ESPNOWBroadcastImpl::onWiFiEvent(void* arg, esp_event_base_t event_base, in if ( event_base == WIFI_EVENT ) { #ifdef ESPNOW_DEBUGGING - #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0) + #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 4, 4) Serial.printf("WiFiEvent( %d )\n", event_id ); #else Serial.printf("WiFiEvent( %s )\n", WiFi.eventName((arduino_event_id_t)event_id) ); diff --git a/wled00/json.cpp b/wled00/json.cpp index 9e835d1382..af8ed89ef6 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -609,9 +609,6 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme } } -#define _MACRO_TO_STR(x) #x -#define MACRO_TO_STR(x) _MACRO_TO_STR(x) - void serializeInfo(JsonObject root) { root[F("ver")] = versionString; @@ -794,7 +791,6 @@ void serializeInfo(JsonObject root) root[F("brand")] = "WLED"; root[F("product")] = F("FOSS"); - root[F("release")] = MACRO_TO_STR(WLED_RELEASE_NAME); root["mac"] = escapedMac; char s[16] = ""; if (Network.isConnected()) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 98ba39426f..ce9e00169a 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -30,6 +30,13 @@ void WLED::reset() } applyBri(); DEBUG_PRINTLN(F("WLED RESET")); + + WiFi.softAPdisconnect(true); + WiFi.disconnect(true); + yield(); + + lastReconnectAttempt = 0; + apActive = false; ESP.restart(); } @@ -558,12 +565,9 @@ void WLED::initAP(bool resetAP) WiFi.setTxPower(WIFI_POWER_8_5dBm); #endif - Serial.printf("WLED::initAP - apActive: %s", apActive ? "true" : "false"); - if (!apActive) // start captive portal if AP active { yield(); - Serial.println("WLED::initAP - starting captive portal"); DEBUG_PRINTLN(F("Init AP interfaces")); server.begin(); From 0304ca7780102b4fc3f89e80b9c40c99acd21f5e Mon Sep 17 00:00:00 2001 From: Craig Link Date: Tue, 20 Aug 2024 18:28:18 -0700 Subject: [PATCH 42/50] reduced attenna power seems to make c3 more stable --- platformio_tubes.ini | 5 +++-- usermods/Tubes/firmware_test.sh | 1 + usermods/Tubes/node.h | 4 ++++ wled00/espnow_broadcast.cpp | 2 +- wled00/wled.cpp | 1 - 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 6491a724f2..3a27881cc2 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -152,13 +152,14 @@ platform_packages = ;platform_packages = ${tubes_no_mic.platform_packages} build_unflags = ${env:esp32-c3-athom.build_unflags} ${tubes_no_mic.build_unflags} -build_flags = ${common.build_flags} -D WLED_RELEASE_NAME=ESP32-C3_ATHOM_TUBES +build_flags = ${common.build_flags} ${esp32c3.build_flags} -D WLED_RELEASE_NAME=ESP32-C3_ATHOM_TUBES ${tubes_no_mic.build_flags} -D LEDPIN=10 -D BTNPIN=9 -D FASTLED_ESP32_SPI_BUS=HSPI -D NUM_STRIPS=1 -D DEFAULT_LED_COUNT=150 - -D WLED_WIFI_POWER_SETTING=WIFI_POWER_15dBm + -D WLED_WIFI_POWER_SETTING=WIFI_POWER_8_5dBm + -D LOLIN_WIFI_FIX lib_ignore = ${env:esp32-c3-athom.lib_ignore} ${tubes_no_mic.lib_ignore} lib_deps = diff --git a/usermods/Tubes/firmware_test.sh b/usermods/Tubes/firmware_test.sh index bdfcd3462f..ed284f8dde 100644 --- a/usermods/Tubes/firmware_test.sh +++ b/usermods/Tubes/firmware_test.sh @@ -62,6 +62,7 @@ update_firmware() { else echo "Updating $firmware firmware via OTA" curl -s -F "update=@../../build_output/firmware/$firmware" -H "Connection: close" --no-keepalive $1/update >/dev/null + curl -s http://$1/reset -H "Connection: close" >/dev/null fi } diff --git a/usermods/Tubes/node.h b/usermods/Tubes/node.h index c22b3af92c..690b75ec69 100644 --- a/usermods/Tubes/node.h +++ b/usermods/Tubes/node.h @@ -350,7 +350,11 @@ class LightNode { void reset(MeshId id = 0) { if (id == 0) { +#if defined(LOLIN_WIFI_FIX) && (defined(ARDUINO_ARCH_ESP32C3) || defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32S3)) + id = random(10, 255); // Leave room at bottom and top of 12 bits +#else id = random(256, 4000); // Leave room at bottom and top of 12 bits +#endif } header.id = id; follow(NULL); diff --git a/wled00/espnow_broadcast.cpp b/wled00/espnow_broadcast.cpp index b7bb9f4afe..c0c789f85e 100644 --- a/wled00/espnow_broadcast.cpp +++ b/wled00/espnow_broadcast.cpp @@ -384,7 +384,7 @@ void ESPNOWBroadcastImpl::onWiFiEvent(void* arg, esp_event_base_t event_base, in #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 4, 4) Serial.printf("WiFiEvent( %d )\n", event_id ); #else - Serial.printf("WiFiEvent( %s )\n", WiFi.eventName((arduino_event_id_t)event_id) ); + Serial.printf("WiFiEvent %d ( %s )\n", event_id, WiFi.eventName((arduino_event_id_t)event_id) ); #endif #endif switch (event_id) { diff --git a/wled00/wled.cpp b/wled00/wled.cpp index ce9e00169a..8e35f00af7 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -567,7 +567,6 @@ void WLED::initAP(bool resetAP) if (!apActive) // start captive portal if AP active { - yield(); DEBUG_PRINTLN(F("Init AP interfaces")); server.begin(); From 0166dae8186a47acd3987e7ce77888d63583f521 Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Tue, 26 Nov 2024 22:59:48 -0800 Subject: [PATCH 43/50] default power save off; better help/debugging --- usermods/Tubes/controller.h | 9 +++++++-- usermods/Tubes/debug.h | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/usermods/Tubes/controller.h b/usermods/Tubes/controller.h index 4be21d0cce..b655f96c53 100644 --- a/usermods/Tubes/controller.h +++ b/usermods/Tubes/controller.h @@ -114,7 +114,7 @@ class PatternController : public MessageReceiver { uint8_t patternOverride = 0; uint16_t wled_fader = 0; ControllerRole role; - bool power_save = true; // Power save ALWAYS starts on. Some roles just ignore it + bool power_save = false; // Default to power save mode OFF but 3 sec press turns it on uint8_t flashColor = 0; AutoUpdater updater = AutoUpdater(); @@ -986,7 +986,7 @@ class PatternController : public MessageReceiver { case '~': doReboot = true; break; - case '@': + case '_': togglePowerSave(); break; @@ -1078,6 +1078,7 @@ class PatternController : public MessageReceiver { case '*': case '(': case ')': + case '@': case 'G': case 'A': case 'W': @@ -1125,6 +1126,7 @@ class PatternController : public MessageReceiver { Serial.println(F("m### - sync mode")); Serial.println(F("c### - colors")); Serial.println(F("e### - effects")); + Serial.println(F("n - force next")); Serial.println(); Serial.println(F("i### - set ID")); Serial.println(F("d - toggle debugging")); @@ -1133,6 +1135,9 @@ class PatternController : public MessageReceiver { Serial.println("U - begin auto-update"); Serial.println("P - toggle all power saves"); Serial.println("O - toggle all sound overlays"); + Serial.println("==== wifi ===="); + Serial.println("a - turn on access point"); + Serial.println("q - turn off access point"); Serial.println("==== global actions ===="); Serial.println("* - enter select mode (double-click to Ready)"); Serial.println("A - turn on access point (Ready to update)"); diff --git a/usermods/Tubes/debug.h b/usermods/Tubes/debug.h index ba5d234801..b4af3920f3 100644 --- a/usermods/Tubes/debug.h +++ b/usermods/Tubes/debug.h @@ -81,7 +81,8 @@ class DebugController { auto seg = strip.getMainSegment(); extractModeName(seg.mode, JSON_mode_names, mode_name, 50); extractModeName(seg.palette, JSON_palette_names, palette_name, 50); - Serial.printf("=== WLED: %s(%u) %s(%u) speed:%u intensity:%u", + Serial.printf("=== WLED: %d LEDs, %s(%u) %s(%u) speed:%u intensity:%u", + strip.getLengthTotal(), mode_name, seg.mode, palette_name, From 077377eab9efebf793a99cf129a4221d723a8907 Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Sat, 1 Feb 2025 16:04:17 -0800 Subject: [PATCH 44/50] Create RUBY mode --- usermods/Tubes/controller.h | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/usermods/Tubes/controller.h b/usermods/Tubes/controller.h index b655f96c53..d98e27f58d 100644 --- a/usermods/Tubes/controller.h +++ b/usermods/Tubes/controller.h @@ -161,7 +161,7 @@ class PatternController : public MessageReceiver { } bool isMasterRole() const { -#if defined(GOLDEN) || defined(CHRISTMAS) +#if defined(GOLDEN) || defined(CHRISTMAS) || defined(RUBY) return true; #endif return role >= MasterRole; @@ -214,7 +214,7 @@ class PatternController : public MessageReceiver { } else { options.brightness = DEFAULT_TUBE_BRIGHTNESS; } -#if defined(GOLDEN) || defined(CHRISTMAS) +#if defined(GOLDEN) || defined(CHRISTMAS) || defined(RUBY) node.reset(0xFFF); #endif options.debugging = false; @@ -446,7 +446,29 @@ class PatternController : public MessageReceiver { uint8_t r = blend8(c.r, color2.r, fader); uint8_t g = blend8(c.g, color2.g, fader); uint8_t b = blend8(c.b, color2.b, fader); +#ifdef RUBY + // Simple average brightness for a "luminosity" measure + uint8_t brightness = (uint16_t)(r + g + b) / 3; + + // Check if it's near white (all channels fairly similar and somewhat bright) + // You can tweak thresholds to taste. + bool isNearWhite = (abs(r - g) < 20 && abs(g - b) < 20 && (r + g + b) > 200); + + // Force everything into a shade of red: + uint8_t redLevel = brightness; + uint8_t greenLevel = 0; + uint8_t blueLevel = 0; + + // If it’s near white, add a little G/B so it’s not pure red. + if(isNearWhite) { + greenLevel = brightness / 2; + blueLevel = brightness / 2; + } + + c = CRGB(redLevel, greenLevel, blueLevel); +#else c = CRGB(r,g,b); +#endif } strip.setPixelColor(i, c); } @@ -678,6 +700,13 @@ class PatternController : public MessageReceiver { /*best yes:*/25, 34, 34, 61, 63, 81, 112, /*maybe:*/81, 28, 107}; next_state.palette_id = colors[r]; +#elif defined(RUBY) // 81, 107 are too bright + uint r = random8(0, 20); + uint colors[20] = {/*gold:*/, + /*yes:*/21, + /*best yes:*/, + /*maybe:*/33, 35, 44, 81, 93, 107; + next_state.palette_id = colors[r]; #else // Don't select the built-in palettes next_state.palette_id = random8(6, gGradientPaletteCount); From 247b940b80eeac16167adf467e45c3894b89a494 Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Sun, 27 Jul 2025 13:55:31 -0700 Subject: [PATCH 45/50] Pin certain libs, since their projects have moved on for 15 and we're not there yet --- platformio_tubes.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 3a27881cc2..68df165991 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -40,7 +40,7 @@ lib_ignore = lib_deps = fastled/FastLED @ ^3.7.0 makuna/NeoPixelBus @ ^2.7.8 - https://github.com/Aircoookie/ESPAsyncWebServer.git @ 2.2.1 + https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.2.1 [tubes] extends = tubes_no_mic @@ -49,7 +49,7 @@ build_flags = ${esp32.AR_build_flags} lib_deps = ${tubes_no_mic.lib_deps} IRremoteESP8266 @ ^2.8.6 - https://github.com/kosme/arduinoFFT @ 2.0.2 ; ${esp32.AR_LIB_deps} + https://github.com/kosme/arduinoFFT#v2.0.2 [env:esp32_quinled_dig2go] From e1796ca60748979dc6230facbf730c5b48523151 Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Tue, 12 Aug 2025 21:19:28 -0700 Subject: [PATCH 46/50] override WLED and check in platformio_override.ini since everyone needs it --- .gitignore | 1 - platformio_override.ini | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 platformio_override.ini diff --git a/.gitignore b/.gitignore index c85fae0c22..b687696b95 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ .vscode esp01-update.sh -platformio_override.ini replace_fs.py wled-update.sh diff --git a/platformio_override.ini b/platformio_override.ini new file mode 100644 index 0000000000..0ff991f78f --- /dev/null +++ b/platformio_override.ini @@ -0,0 +1,17 @@ +[platformio] +default_envs = esp32dev +extra_configs = + platformio_tubes.ini + +[env:golden] +extends = env:esp32_quinled_dig2go_tubes +build_flags = ${env:tubes.build_flags} -D GOLDEN + +[env:christmas] +extends = env:esp32_quinled_dig2go_tubes +build_flags = ${env:tubes.build_flags} -D CHRISTMAS + +[env:ruby] +extends = env:esp32_quinled_dig2go_tubes +build_flags = ${env:tubes.build_flags} -D RUBY + From a80fe811a864b2169c3ae83391555d526d952384 Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Fri, 20 Feb 2026 10:45:11 -0800 Subject: [PATCH 47/50] Enable CHRISTMAS mode and weight holiday palette selection --- platformio_tubes.ini | 1 + usermods/Tubes/controller.h | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 68df165991..3b1bb26811 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -76,6 +76,7 @@ build_flags = -D WLED_RELEASE_NAME=DIG2GO_TUBES ${env:esp32_quinled_dig2go.build_flags} -D FASTLED_ESP32_SPI_BUS=HSPI -D NUM_STRIPS=1 -D DEFAULT_LED_COUNT=150 + -D CHRISTMAS # REMOVE lib_ignore = ESPAsyncTCP ESPAsyncUDP diff --git a/usermods/Tubes/controller.h b/usermods/Tubes/controller.h index d98e27f58d..aca749f21a 100644 --- a/usermods/Tubes/controller.h +++ b/usermods/Tubes/controller.h @@ -694,9 +694,10 @@ class PatternController : public MessageReceiver { uint colors[4] = {18, 58, 71, 111}; next_state.palette_id = colors[r]; #elif defined(CHRISTMAS) // 81, 107 are too bright - uint r = random8(0, 20); - uint colors[20] = {/*gold:*/18, 58, 71, 111, + uint r = random8(0, 26); + uint colors[26] = {/*gold:*/18, 58, 71, 111, /*yes:*/25, 34, 61, 63, 81, 112, + /*yesx2:*/25, 34, 61, 63, 81, 112, /*best yes:*/25, 34, 34, 61, 63, 81, 112, /*maybe:*/81, 28, 107}; next_state.palette_id = colors[r]; From 3ee799f88c67399f5618f29c60aa064a76a23041 Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Fri, 20 Feb 2026 10:45:16 -0800 Subject: [PATCH 48/50] Remove explicit ATHOM C3 pin overrides in tubes env --- platformio_tubes.ini | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 3b1bb26811..cad94a37a8 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -153,10 +153,8 @@ platform_packages = ;platform_packages = ${tubes_no_mic.platform_packages} build_unflags = ${env:esp32-c3-athom.build_unflags} ${tubes_no_mic.build_unflags} -build_flags = ${common.build_flags} ${esp32c3.build_flags} -D WLED_RELEASE_NAME=ESP32-C3_ATHOM_TUBES +build_flags = ${env:esp32-c3-athom.build_flags} -D WLED_RELEASE_NAME=ESP32-C3_ATHOM_TUBES ${tubes_no_mic.build_flags} - -D LEDPIN=10 - -D BTNPIN=9 -D FASTLED_ESP32_SPI_BUS=HSPI -D NUM_STRIPS=1 -D DEFAULT_LED_COUNT=150 -D WLED_WIFI_POWER_SETTING=WIFI_POWER_8_5dBm From b8fb0f0095d843bdbede3adda2fe3d9e8fdc222f Mon Sep 17 00:00:00 2001 From: Steve Eisner Date: Fri, 20 Feb 2026 10:45:29 -0800 Subject: [PATCH 49/50] Add ESP32 GLEDOPTO and tubes build environments --- platformio_tubes.ini | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index cad94a37a8..5917d8a0b7 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -163,3 +163,39 @@ lib_ignore = ${env:esp32-c3-athom.lib_ignore} ${tubes_no_mic.lib_ignore} lib_deps = ${tubes_no_mic.lib_deps} + + +# ------------------------------------------------------------------------------ +# ESP32 GLEDOPTO +# +# LEDs: GRB @ pin 16 +# Button: GPIO 0 +# SR: i2S SD 26, WS 5, SCK 21, MCLK unused +# ------------------------------------------------------------------------------ +[env:esp32-gledopto] +extends = env:esp32dev +lib_ignore = IRremoteESP8266 + ${env:esp32c3dev.lib_ignore} ; ok to keep this line if it exists, harmless +build_flags = + -D LEDPIN=16 + -D BTNPIN=0 + -D WLED_DISABLE_INFRARED + -D IRTYPE=0 + +[env:esp32-gledopto_tubes] +extends = env:esp32-gledopto +platform = platformio/espressif32 @ 6.7.0 +platform_packages = + framework-arduinoespressif32@3.20016.0 ; Arduino-ESP32 2.0.16 +build_unflags = ${env:esp32-gledopto.build_unflags} + ${tubes_no_mic.build_unflags} +build_flags = ${env:esp32-gledopto.build_flags} + ${tubes_no_mic.build_flags} + -D FASTLED_ESP32_SPI_BUS=HSPI + -D NUM_STRIPS=1 -D DEFAULT_LED_COUNT=150 + -D WLED_WIFI_POWER_SETTING=WIFI_POWER_8_5dBm + -D LOLIN_WIFI_FIX +lib_ignore = ${env:esp32-gledopto.lib_ignore} + ${tubes_no_mic.lib_ignore} +lib_deps = ${env:esp32-gledopto.lib_deps} + ${tubes_no_mic.lib_deps} From ad862cc43f06164bb1b2c246acca6cdc81ee748b Mon Sep 17 00:00:00 2001 From: Craig Link Date: Thu, 22 Aug 2024 07:26:41 -0700 Subject: [PATCH 50/50] fastled bug fixes --- platformio_tubes.ini | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platformio_tubes.ini b/platformio_tubes.ini index 5917d8a0b7..39b499cff4 100644 --- a/platformio_tubes.ini +++ b/platformio_tubes.ini @@ -38,8 +38,8 @@ lib_ignore = ESPAsyncUDP IRremoteESP8266 lib_deps = - fastled/FastLED @ ^3.7.0 - makuna/NeoPixelBus @ ^2.7.8 + fastled/FastLED @ ^3.7.3 + makuna/NeoPixelBus @ ^2.8.0 https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.2.1 [tubes] @@ -148,6 +148,7 @@ build_flags = ${env:esp32c3dev.build_flags} [env:esp32-c3-athom_tubes] extends = env:esp32-c3-athom platform = espressif32@6.8.1 +upload_speed = 115200 platform_packages = ;platform = ${tubes_no_mic.platform} ;platform_packages = ${tubes_no_mic.platform_packages}