Compare commits
2 Commits
main
...
adjustable
Author | SHA1 | Date | |
---|---|---|---|
|
df174f6d26 | ||
|
d9e576c35c |
35
.gitignore
vendored
35
.gitignore
vendored
@ -1,24 +1,21 @@
|
|||||||
.cache
|
|
||||||
.clang-format
|
|
||||||
.direnv
|
|
||||||
.DS_Store
|
|
||||||
.gitignore
|
|
||||||
.idea
|
|
||||||
.pio
|
.pio
|
||||||
|
.cache
|
||||||
.pioenvs
|
.pioenvs
|
||||||
.piolibdeps
|
.piolibdeps
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
esp01-update.sh
|
|
||||||
platformio_override.ini
|
|
||||||
replace_fs.py
|
|
||||||
wled-update.sh
|
|
||||||
|
|
||||||
/build_output/
|
|
||||||
/node_modules/
|
|
||||||
|
|
||||||
/wled00/extLibs
|
|
||||||
/wled00/LittleFS
|
|
||||||
/wled00/my_config.h
|
|
||||||
/wled00/Release
|
/wled00/Release
|
||||||
/wled00/wled00.ino.cpp
|
/wled00/extLibs
|
||||||
|
/platformio_override.ini
|
||||||
|
/wled00/my_config.h
|
||||||
|
/build_output
|
||||||
|
.DS_Store
|
||||||
|
.gitignore
|
||||||
|
.clang-format
|
||||||
|
node_modules
|
||||||
|
.idea
|
||||||
|
.direnv
|
||||||
|
wled-update.sh
|
||||||
|
esp01-update.sh
|
||||||
|
/wled00/LittleFS
|
||||||
|
replace_fs.py
|
||||||
|
wled00/wled00.ino.cpp
|
||||||
|
33
CHANGELOG.md
33
CHANGELOG.md
@ -1,32 +1,5 @@
|
|||||||
## WLED changelog
|
## WLED changelog
|
||||||
|
|
||||||
#### Build 2310010, build 2310130
|
|
||||||
- Release of WLED version 0.14.0 "Hoshi"
|
|
||||||
- Bugfixes for #3400, #3403, #3405
|
|
||||||
- minor HTML optimizations
|
|
||||||
- audioreactive: bugfix for UDP sound sync (partly initialized packets)
|
|
||||||
|
|
||||||
#### Build 2309240
|
|
||||||
- Release of WLED beta version 0.14.0-b6 "Hoshi"
|
|
||||||
- Effect bugfixes and improvements (Meteor, Meteor Smooth, Scrolling Text)
|
|
||||||
- audioreactive: bugfixes for ES8388 and ES7243 init; minor improvements for analog inputs
|
|
||||||
|
|
||||||
#### Build 2309100
|
|
||||||
- Release of WLED beta version 0.14.0-b5 "Hoshi"
|
|
||||||
- New standard esp32 build with audioreactive
|
|
||||||
- Effect blending bugfixes, and minor optimizations
|
|
||||||
|
|
||||||
#### Build 2309050
|
|
||||||
- Effect blending (#3311) (finally effect transitions!)
|
|
||||||
*WARNING*: May not work well with ESP8266, with plenty of segments or usermods (low RAM condition)!!!
|
|
||||||
- Added receive and send sync groups to JSON API (#3317) (you can change sync groups using preset)
|
|
||||||
- Internal temperature usermod (#3246)
|
|
||||||
- MQTT server and topic length overrides (#3354) (new build flags)
|
|
||||||
- Animated Staircase usermod enhancement (#3348) (on/off toggle/relay control)
|
|
||||||
- Added local time info to Info page (#3351)
|
|
||||||
- New effect: Rolling Balls (a.k.a. linear bounce) (#1039)
|
|
||||||
- Various bug fixes and enhancements.
|
|
||||||
|
|
||||||
#### Build 2308110
|
#### Build 2308110
|
||||||
- Release of WLED beta version 0.14.0-b4 "Hoshi"
|
- Release of WLED beta version 0.14.0-b4 "Hoshi"
|
||||||
- Reset effect data immediately upon mode change
|
- Reset effect data immediately upon mode change
|
||||||
@ -46,7 +19,7 @@
|
|||||||
- Preset cycle bugfix (#3262)
|
- Preset cycle bugfix (#3262)
|
||||||
- Rotary encoder ALT fix for large LED count (#3276)
|
- Rotary encoder ALT fix for large LED count (#3276)
|
||||||
- effect updates (2D Plasmaball), `blur()` speedup
|
- effect updates (2D Plasmaball), `blur()` speedup
|
||||||
- On/Off toggle from nodes view (may show unknown device type on older versions) (#3291)
|
- On/Off toggle from nodes view (may show unknow device type on older versions) (#3291)
|
||||||
- various fixes and improvements (ABL, crashes when changing presets with different segments)
|
- various fixes and improvements (ABL, crashes when changing presets with different segments)
|
||||||
|
|
||||||
#### Build 2306270
|
#### Build 2306270
|
||||||
@ -59,7 +32,7 @@
|
|||||||
|
|
||||||
#### Build 2306210
|
#### Build 2306210
|
||||||
- 0.14.0-b3 release
|
- 0.14.0-b3 release
|
||||||
- respect global I2C in all usermods (no local initialization of I2C bus)
|
- respect global I2C in all usermods (no local initilaisation of I2C bus)
|
||||||
- Multi relay usermod compile-time enabled option (-D MULTI_RELAY_ENABLED=true|false)
|
- Multi relay usermod compile-time enabled option (-D MULTI_RELAY_ENABLED=true|false)
|
||||||
|
|
||||||
#### Build 2306180
|
#### Build 2306180
|
||||||
@ -85,7 +58,7 @@
|
|||||||
|
|
||||||
#### Build 2306020
|
#### Build 2306020
|
||||||
- Support for segment sets (PR #3171)
|
- Support for segment sets (PR #3171)
|
||||||
- Reduce sound simulation modes to 2 to facilitate segment sets
|
- Reduce sound simulation modes to 2 to facilitiate segment sets
|
||||||
- Trigger button immediately on press if all configured presets are the same (PR #3226)
|
- Trigger button immediately on press if all configured presets are the same (PR #3226)
|
||||||
- Changes for allowing Alexa to change light color to White when auto-calculating from RGB (PR #3211)
|
- Changes for allowing Alexa to change light color to White when auto-calculating from RGB (PR #3211)
|
||||||
|
|
||||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "wled",
|
"name": "wled",
|
||||||
"version": "0.14.0",
|
"version": "0.14.0-b4",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "wled",
|
"name": "wled",
|
||||||
"version": "0.14.0",
|
"version": "0.14.0-b4",
|
||||||
"description": "Tools for WLED project",
|
"description": "Tools for WLED project",
|
||||||
"main": "tools/cdata.js",
|
"main": "tools/cdata.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
# CI binaries
|
# CI binaries
|
||||||
; default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth # ESP32 variant builds are temporarily excluded from CI due to toolchain issues on the GitHub Actions Linux environment
|
; default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth # ESP32 variant builds are temporarily excluded from CI due to toolchain issues on the GitHub Actions Linux environment
|
||||||
default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, esp32dev_audioreactive, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB, esp32s3dev_8MB_PSRAM_opi
|
default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB, esp32s3dev_8MB_PSRAM_opi
|
||||||
|
|
||||||
# Release binaries
|
# Release binaries
|
||||||
; default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB
|
; default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB
|
||||||
@ -87,13 +87,11 @@ platform_packages = platformio/framework-arduinoespressif8266
|
|||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# FLAGS: DEBUG
|
# FLAGS: DEBUG
|
||||||
# esp8266 : see https://docs.platformio.org/en/latest/platforms/espressif8266.html#debug-level
|
#
|
||||||
# esp32 : see https://docs.platformio.org/en/latest/platforms/espressif32.html#debug-level
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
debug_flags = -D DEBUG=1 -D WLED_DEBUG
|
debug_flags = -D DEBUG=1 -D WLED_DEBUG -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_TLS_MEM
|
||||||
-DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_TLS_MEM ;; for esp8266
|
#if needed (for memleaks etc) also add; -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h"
|
||||||
# if needed (for memleaks etc) also add; -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h"
|
#-DDEBUG_ESP_CORE is not working right now
|
||||||
# -DDEBUG_ESP_CORE is not working right now
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# FLAGS: ldscript (available ldscripts at https://github.com/esp8266/Arduino/tree/master/tools/sdk/ld)
|
# FLAGS: ldscript (available ldscripts at https://github.com/esp8266/Arduino/tree/master/tools/sdk/ld)
|
||||||
@ -216,9 +214,6 @@ build_flags =
|
|||||||
-DVTABLES_IN_FLASH
|
-DVTABLES_IN_FLASH
|
||||||
; restrict to minimal mime-types
|
; restrict to minimal mime-types
|
||||||
-DMIMETYPE_MINIMAL
|
-DMIMETYPE_MINIMAL
|
||||||
; other special-purpose framework flags (see https://docs.platformio.org/en/latest/platforms/espressif8266.html)
|
|
||||||
; -D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48 ;; in case of linker errors like "section `.text1' will not fit in region `iram1_0_seg'"
|
|
||||||
; -D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED ;; (experimental) adds some extra heap, but may cause slowdown
|
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
#https://github.com/lorol/LITTLEFS.git
|
#https://github.com/lorol/LITTLEFS.git
|
||||||
@ -229,7 +224,9 @@ lib_deps =
|
|||||||
[esp32]
|
[esp32]
|
||||||
#platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.3/platform-espressif32-2.0.2.3.zip
|
#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 = espressif32@3.5.0
|
||||||
|
|
||||||
platform_packages = framework-arduinoespressif32 @ https://github.com/Aircoookie/arduino-esp32.git#1.0.6.4
|
platform_packages = framework-arduinoespressif32 @ https://github.com/Aircoookie/arduino-esp32.git#1.0.6.4
|
||||||
|
|
||||||
build_flags = -g
|
build_flags = -g
|
||||||
-DARDUINO_ARCH_ESP32
|
-DARDUINO_ARCH_ESP32
|
||||||
#-DCONFIG_LITTLEFS_FOR_IDF_3_2
|
#-DCONFIG_LITTLEFS_FOR_IDF_3_2
|
||||||
@ -237,14 +234,14 @@ build_flags = -g
|
|||||||
#use LITTLEFS library by lorol in ESP32 core 1.x.x instead of built-in in 2.x.x
|
#use LITTLEFS library by lorol in ESP32 core 1.x.x instead of built-in in 2.x.x
|
||||||
-D LOROL_LITTLEFS
|
-D LOROL_LITTLEFS
|
||||||
; -DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3
|
; -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
|
default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
https://github.com/lorol/LITTLEFS.git
|
https://github.com/lorol/LITTLEFS.git
|
||||||
https://github.com/pbolduc/AsyncTCP.git @ 1.2.0
|
https://github.com/pbolduc/AsyncTCP.git @ 1.2.0
|
||||||
${env.lib_deps}
|
${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#develop @ ^1.9.2
|
|
||||||
|
|
||||||
[esp32_idf_V4]
|
[esp32_idf_V4]
|
||||||
;; experimental build environment for ESP32 using ESP-IDF 4.4.x / arduino-esp32 v2.0.5
|
;; experimental build environment for ESP32 using ESP-IDF 4.4.x / arduino-esp32 v2.0.5
|
||||||
@ -352,7 +349,6 @@ platform_packages = ${common.platform_packages}
|
|||||||
board_build.ldscript = ${common.ldscript_1m128k}
|
board_build.ldscript = ${common.ldscript_1m128k}
|
||||||
build_unflags = ${common.build_unflags}
|
build_unflags = ${common.build_unflags}
|
||||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01 -D WLED_DISABLE_OTA
|
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01 -D WLED_DISABLE_OTA
|
||||||
; -D WLED_USE_UNREAL_MATH ;; may cause wrong sunset/sunrise times, but saves 7064 bytes FLASH and 975 bytes RAM
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
[env:esp07]
|
[env:esp07]
|
||||||
@ -403,20 +399,6 @@ lib_deps = ${esp32.lib_deps}
|
|||||||
monitor_filters = esp32_exception_decoder
|
monitor_filters = esp32_exception_decoder
|
||||||
board_build.partitions = ${esp32.default_partitions}
|
board_build.partitions = ${esp32.default_partitions}
|
||||||
|
|
||||||
[env:esp32dev_audioreactive]
|
|
||||||
board = esp32dev
|
|
||||||
platform = ${esp32.platform}
|
|
||||||
platform_packages = ${esp32.platform_packages}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_audioreactive #-D WLED_DISABLE_BROWNOUT_DET
|
|
||||||
${esp32.AR_build_flags}
|
|
||||||
lib_deps = ${esp32.lib_deps}
|
|
||||||
${esp32.AR_lib_deps}
|
|
||||||
monitor_filters = esp32_exception_decoder
|
|
||||||
board_build.partitions = ${esp32.default_partitions}
|
|
||||||
; board_build.f_flash = 80000000L
|
|
||||||
; board_build.flash_mode = dio
|
|
||||||
|
|
||||||
[env:esp32dev_qio80]
|
[env:esp32dev_qio80]
|
||||||
board = esp32dev
|
board = esp32dev
|
||||||
platform = ${esp32.platform}
|
platform = ${esp32.platform}
|
||||||
@ -606,7 +588,6 @@ build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=
|
|||||||
-DARDUINO_USB_DFU_ON_BOOT=0
|
-DARDUINO_USB_DFU_ON_BOOT=0
|
||||||
-DLOLIN_WIFI_FIX ; seems to work much better with this
|
-DLOLIN_WIFI_FIX ; seems to work much better with this
|
||||||
-D WLED_USE_PSRAM
|
-D WLED_USE_PSRAM
|
||||||
; -D WLED_USE_UNREAL_MATH ;; may cause wrong sunset/sunrise times, but saves 6792 bytes FLASH
|
|
||||||
-D WLED_WATCHDOG_TIMEOUT=0
|
-D WLED_WATCHDOG_TIMEOUT=0
|
||||||
-D CONFIG_ASYNC_TCP_USE_WDT=0
|
-D CONFIG_ASYNC_TCP_USE_WDT=0
|
||||||
-D LEDPIN=16
|
-D LEDPIN=16
|
||||||
|
168
readme.md
168
readme.md
@ -1,84 +1,84 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="/images/wled_logo_akemi.png">
|
<img src="/images/wled_logo_akemi.png">
|
||||||
<a href="https://github.com/Aircoookie/WLED/releases"><img src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square"></a>
|
<a href="https://github.com/Aircoookie/WLED/releases"><img src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square"></a>
|
||||||
<a href="https://raw.githubusercontent.com/Aircoookie/WLED/master/LICENSE"><img src="https://img.shields.io/github/license/Aircoookie/wled?color=blue&style=flat-square"></a>
|
<a href="https://raw.githubusercontent.com/Aircoookie/WLED/master/LICENSE"><img src="https://img.shields.io/github/license/Aircoookie/wled?color=blue&style=flat-square"></a>
|
||||||
<a href="https://wled.discourse.group"><img src="https://img.shields.io/discourse/topics?colorB=blue&label=forum&server=https%3A%2F%2Fwled.discourse.group%2F&style=flat-square"></a>
|
<a href="https://wled.discourse.group"><img src="https://img.shields.io/discourse/topics?colorB=blue&label=forum&server=https%3A%2F%2Fwled.discourse.group%2F&style=flat-square"></a>
|
||||||
<a href="https://discord.gg/QAh7wJHrRM"><img src="https://img.shields.io/discord/473448917040758787.svg?colorB=blue&label=discord&style=flat-square"></a>
|
<a href="https://discord.gg/KuqP7NE"><img src="https://img.shields.io/discord/473448917040758787.svg?colorB=blue&label=discord&style=flat-square"></a>
|
||||||
<a href="https://kno.wled.ge"><img src="https://img.shields.io/badge/quick_start-wiki-blue.svg?style=flat-square"></a>
|
<a href="https://kno.wled.ge"><img src="https://img.shields.io/badge/quick_start-wiki-blue.svg?style=flat-square"></a>
|
||||||
<a href="https://github.com/Aircoookie/WLED-App"><img src="https://img.shields.io/badge/app-wled-blue.svg?style=flat-square"></a>
|
<a href="https://github.com/Aircoookie/WLED-App"><img src="https://img.shields.io/badge/app-wled-blue.svg?style=flat-square"></a>
|
||||||
<a href="https://gitpod.io/#https://github.com/Aircoookie/WLED"><img src="https://img.shields.io/badge/Gitpod-ready--to--code-blue?style=flat-square&logo=gitpod"></a>
|
<a href="https://gitpod.io/#https://github.com/Aircoookie/WLED"><img src="https://img.shields.io/badge/Gitpod-ready--to--code-blue?style=flat-square&logo=gitpod"></a>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
# Welcome to my project WLED! ✨
|
# Welcome to my project WLED! ✨
|
||||||
|
|
||||||
A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812) LEDs or also SPI based chipsets like the WS2801 and APA102!
|
A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812) LEDs or also SPI based chipsets like the WS2801 and APA102!
|
||||||
|
|
||||||
## ⚙️ Features
|
## ⚙️ Features
|
||||||
- WS2812FX library with more than 100 special effects
|
- WS2812FX library with more than 100 special effects
|
||||||
- FastLED noise effects and 50 palettes
|
- FastLED noise effects and 50 palettes
|
||||||
- Modern UI with color, effect and segment controls
|
- Modern UI with color, effect and segment controls
|
||||||
- Segments to set different effects and colors to user defined parts of the LED string
|
- Segments to set different effects and colors to user defined parts of the LED string
|
||||||
- Settings page - configuration via the network
|
- Settings page - configuration via the network
|
||||||
- Access Point and station mode - automatic failsafe AP
|
- Access Point and station mode - automatic failsafe AP
|
||||||
- Up to 10 LED outputs per instance
|
- Up to 10 LED outputs per instance
|
||||||
- Support for RGBW strips
|
- Support for RGBW strips
|
||||||
- Up to 250 user presets to save and load colors/effects easily, supports cycling through them.
|
- Up to 250 user presets to save and load colors/effects easily, supports cycling through them.
|
||||||
- Presets can be used to automatically execute API calls
|
- Presets can be used to automatically execute API calls
|
||||||
- Nightlight function (gradually dims down)
|
- Nightlight function (gradually dims down)
|
||||||
- Full OTA software updatability (HTTP + ArduinoOTA), password protectable
|
- Full OTA software updatability (HTTP + ArduinoOTA), password protectable
|
||||||
- Configurable analog clock (Cronixie, 7-segment and EleksTube IPS clock support via usermods)
|
- Configurable analog clock (Cronixie, 7-segment and EleksTube IPS clock support via usermods)
|
||||||
- Configurable Auto Brightness limit for safe operation
|
- Configurable Auto Brightness limit for safe operation
|
||||||
- Filesystem-based config for easier backup of presets and settings
|
- Filesystem-based config for easier backup of presets and settings
|
||||||
|
|
||||||
## 💡 Supported light control interfaces
|
## 💡 Supported light control interfaces
|
||||||
- WLED app for [Android](https://play.google.com/store/apps/details?id=com.aircoookie.WLED) and [iOS](https://apps.apple.com/us/app/wled/id1475695033)
|
- WLED app for [Android](https://play.google.com/store/apps/details?id=com.aircoookie.WLED) and [iOS](https://apps.apple.com/us/app/wled/id1475695033)
|
||||||
- JSON and HTTP request APIs
|
- JSON and HTTP request APIs
|
||||||
- MQTT
|
- MQTT
|
||||||
- E1.31, Art-Net, DDP and TPM2.net
|
- E1.31, Art-Net, DDP and TPM2.net
|
||||||
- [diyHue](https://github.com/diyhue/diyHue) (Wled is supported by diyHue, including Hue Sync Entertainment under udp. Thanks to [Gregory Mallios](https://github.com/gmallios))
|
- [diyHue](https://github.com/diyhue/diyHue) (Wled is supported by diyHue, including Hue Sync Entertainment under udp. Thanks to [Gregory Mallios](https://github.com/gmallios))
|
||||||
- [Hyperion](https://github.com/hyperion-project/hyperion.ng)
|
- [Hyperion](https://github.com/hyperion-project/hyperion.ng)
|
||||||
- UDP realtime
|
- UDP realtime
|
||||||
- Alexa voice control (including dimming and color)
|
- Alexa voice control (including dimming and color)
|
||||||
- Sync to Philips hue lights
|
- Sync to Philips hue lights
|
||||||
- Adalight (PC ambilight via serial) and TPM2
|
- Adalight (PC ambilight via serial) and TPM2
|
||||||
- Sync color of multiple WLED devices (UDP notifier)
|
- Sync color of multiple WLED devices (UDP notifier)
|
||||||
- Infrared remotes (24-key RGB, receiver required)
|
- Infrared remotes (24-key RGB, receiver required)
|
||||||
- Simple timers/schedules (time from NTP, timezones/DST supported)
|
- Simple timers/schedules (time from NTP, timezones/DST supported)
|
||||||
|
|
||||||
## 📲 Quick start guide and documentation
|
## 📲 Quick start guide and documentation
|
||||||
|
|
||||||
See the [documentation on our official site](https://kno.wled.ge)!
|
See the [documentation on our official site](https://kno.wled.ge)!
|
||||||
|
|
||||||
[On this page](https://kno.wled.ge/basics/tutorials/) you can find excellent tutorials and tools to help you get your new project up and running!
|
[On this page](https://kno.wled.ge/basics/tutorials/) you can find excellent tutorials and tools to help you get your new project up and running!
|
||||||
|
|
||||||
## 🖼️ User interface
|
## 🖼️ User interface
|
||||||
<img src="images/macbook-pro-space-gray-on-the-wooden-table.jpg" width="50%"><img src="images/walking-with-iphone-x.jpg" width="50%">
|
<img src="/images/macbook-pro-space-gray-on-the-wooden-table.jpg" width="50%"><img src="/images/walking-with-iphone-x.jpg" width="50%">
|
||||||
|
|
||||||
## 💾 Compatible hardware
|
## 💾 Compatible hardware
|
||||||
|
|
||||||
See [here](https://kno.wled.ge/basics/compatible-hardware)!
|
See [here](https://kno.wled.ge/basics/compatible-hardware)!
|
||||||
|
|
||||||
## ✌️ Other
|
## ✌️ Other
|
||||||
|
|
||||||
Licensed under the MIT license
|
Licensed under the MIT license
|
||||||
Credits [here](https://kno.wled.ge/about/contributors/)!
|
Credits [here](https://kno.wled.ge/about/contributors/)!
|
||||||
|
|
||||||
Join the Discord server to discuss everything about WLED!
|
Join the Discord server to discuss everything about WLED!
|
||||||
|
|
||||||
<a href="https://discord.gg/QAh7wJHrRM"><img src="https://discordapp.com/api/guilds/473448917040758787/widget.png?style=banner2" width="25%"></a>
|
<a href="https://discord.gg/KuqP7NE"><img src="https://discordapp.com/api/guilds/473448917040758787/widget.png?style=banner2" width="25%"></a>
|
||||||
|
|
||||||
Check out the WLED [Discourse forum](https://wled.discourse.group)!
|
Check out the WLED [Discourse forum](https://wled.discourse.group)!
|
||||||
|
|
||||||
You can also send me mails to [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com), but please, only do so if you want to talk to me privately.
|
You can also send me mails to [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com), but please, only do so if you want to talk to me privately.
|
||||||
|
|
||||||
If WLED really brightens up your day, you can [![](https://img.shields.io/badge/send%20me%20a%20small%20gift-paypal-blue.svg?style=flat-square)](https://paypal.me/aircoookie)
|
If WLED really brightens up your day, you can [![](https://img.shields.io/badge/send%20me%20a%20small%20gift-paypal-blue.svg?style=flat-square)](https://paypal.me/aircoookie)
|
||||||
|
|
||||||
|
|
||||||
*Disclaimer:*
|
*Disclaimer:*
|
||||||
|
|
||||||
If you are prone to photosensitive epilepsy, we recommended you do **not** use this software.
|
If you are prone to photosensitive epilepsy, we recommended you do **not** use this software.
|
||||||
If you still want to try, don't use strobe, lighting or noise modes or high effect speed settings.
|
If you still want to try, don't use strobe, lighting or noise modes or high effect speed settings.
|
||||||
|
|
||||||
As per the MIT license, I assume no liability for any damage to you or any other person or equipment.
|
As per the MIT license, I assume no liability for any damage to you or any other person or equipment.
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ class Animated_Staircase : public Usermod {
|
|||||||
bool useUSSensorBottom = false; // using PIR or UltraSound sensor?
|
bool useUSSensorBottom = false; // using PIR or UltraSound sensor?
|
||||||
unsigned int topMaxDist = 50; // default maximum measured distance in cm, top
|
unsigned int topMaxDist = 50; // default maximum measured distance in cm, top
|
||||||
unsigned int bottomMaxDist = 50; // default maximum measured distance in cm, bottom
|
unsigned int bottomMaxDist = 50; // default maximum measured distance in cm, bottom
|
||||||
bool togglePower = false; // toggle power on/off with staircase on/off
|
|
||||||
|
|
||||||
/* runtime variables */
|
/* runtime variables */
|
||||||
bool initDone = false;
|
bool initDone = false;
|
||||||
@ -91,8 +90,7 @@ class Animated_Staircase : public Usermod {
|
|||||||
static const char _bottomEcho_pin[];
|
static const char _bottomEcho_pin[];
|
||||||
static const char _topEchoCm[];
|
static const char _topEchoCm[];
|
||||||
static const char _bottomEchoCm[];
|
static const char _bottomEchoCm[];
|
||||||
static const char _togglePower[];
|
|
||||||
|
|
||||||
void publishMqtt(bool bottom, const char* state) {
|
void publishMqtt(bool bottom, const char* state) {
|
||||||
#ifndef WLED_DISABLE_MQTT
|
#ifndef WLED_DISABLE_MQTT
|
||||||
//Check if MQTT Connected, otherwise it will crash the 8266
|
//Check if MQTT Connected, otherwise it will crash the 8266
|
||||||
@ -198,7 +196,6 @@ class Animated_Staircase : public Usermod {
|
|||||||
if (on) {
|
if (on) {
|
||||||
lastSensor = topSensorRead;
|
lastSensor = topSensorRead;
|
||||||
} else {
|
} else {
|
||||||
if (togglePower && onIndex == offIndex && offMode) toggleOnOff(); // toggle power on if off
|
|
||||||
// If the bottom sensor triggered, we need to swipe up, ON
|
// If the bottom sensor triggered, we need to swipe up, ON
|
||||||
swipe = bottomSensorRead;
|
swipe = bottomSensorRead;
|
||||||
|
|
||||||
@ -252,10 +249,7 @@ class Animated_Staircase : public Usermod {
|
|||||||
offIndex = MAX(onIndex, offIndex - 1);
|
offIndex = MAX(onIndex, offIndex - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (oldOn != onIndex || oldOff != offIndex) {
|
if (oldOn != onIndex || oldOff != offIndex) updateSegments(); // reduce the number of updates to necessary ones
|
||||||
updateSegments(); // reduce the number of updates to necessary ones
|
|
||||||
if (togglePower && onIndex == offIndex && !offMode && !on) toggleOnOff(); // toggle power off for all segments off
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +295,6 @@ class Animated_Staircase : public Usermod {
|
|||||||
strip.setTransition(segment_delay_ms/100);
|
strip.setTransition(segment_delay_ms/100);
|
||||||
strip.trigger();
|
strip.trigger();
|
||||||
} else {
|
} else {
|
||||||
if (togglePower && !on && offMode) toggleOnOff(); // toggle power on if off
|
|
||||||
// Restore segment options
|
// Restore segment options
|
||||||
for (int i = 0; i <= strip.getLastActiveSegmentId(); i++) {
|
for (int i = 0; i <= strip.getLastActiveSegmentId(); i++) {
|
||||||
Segment &seg = strip.getSegment(i);
|
Segment &seg = strip.getSegment(i);
|
||||||
@ -451,7 +444,6 @@ class Animated_Staircase : public Usermod {
|
|||||||
staircase[FPSTR(_bottomEcho_pin)] = useUSSensorBottom ? bottomEchoPin : -1;
|
staircase[FPSTR(_bottomEcho_pin)] = useUSSensorBottom ? bottomEchoPin : -1;
|
||||||
staircase[FPSTR(_topEchoCm)] = topMaxDist;
|
staircase[FPSTR(_topEchoCm)] = topMaxDist;
|
||||||
staircase[FPSTR(_bottomEchoCm)] = bottomMaxDist;
|
staircase[FPSTR(_bottomEchoCm)] = bottomMaxDist;
|
||||||
staircase[FPSTR(_togglePower)] = togglePower;
|
|
||||||
DEBUG_PRINTLN(F("Staircase config saved."));
|
DEBUG_PRINTLN(F("Staircase config saved."));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,8 +488,6 @@ class Animated_Staircase : public Usermod {
|
|||||||
bottomMaxDist = top[FPSTR(_bottomEchoCm)] | bottomMaxDist;
|
bottomMaxDist = top[FPSTR(_bottomEchoCm)] | bottomMaxDist;
|
||||||
bottomMaxDist = min(150,max(30,(int)bottomMaxDist)); // max distance ~1.5m (a lag of 9ms may be expected)
|
bottomMaxDist = min(150,max(30,(int)bottomMaxDist)); // max distance ~1.5m (a lag of 9ms may be expected)
|
||||||
|
|
||||||
togglePower = top[FPSTR(_togglePower)] | togglePower; // staircase toggles power on/off
|
|
||||||
|
|
||||||
DEBUG_PRINT(FPSTR(_name));
|
DEBUG_PRINT(FPSTR(_name));
|
||||||
if (!initDone) {
|
if (!initDone) {
|
||||||
// first run: reading from cfg.json
|
// first run: reading from cfg.json
|
||||||
@ -521,7 +511,7 @@ class Animated_Staircase : public Usermod {
|
|||||||
if (changed) setup();
|
if (changed) setup();
|
||||||
}
|
}
|
||||||
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
||||||
return !top[FPSTR(_togglePower)].isNull();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -561,4 +551,3 @@ const char Animated_Staircase::_bottomPIRorTrigger_pin[] PROGMEM = "bottomPIR
|
|||||||
const char Animated_Staircase::_bottomEcho_pin[] PROGMEM = "bottomEcho_pin";
|
const char Animated_Staircase::_bottomEcho_pin[] PROGMEM = "bottomEcho_pin";
|
||||||
const char Animated_Staircase::_topEchoCm[] PROGMEM = "top-dist-cm";
|
const char Animated_Staircase::_topEchoCm[] PROGMEM = "top-dist-cm";
|
||||||
const char Animated_Staircase::_bottomEchoCm[] PROGMEM = "bottom-dist-cm";
|
const char Animated_Staircase::_bottomEchoCm[] PROGMEM = "bottom-dist-cm";
|
||||||
const char Animated_Staircase::_togglePower[] PROGMEM = "toggle-on-off";
|
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
# Internal Temperature Usermod
|
|
||||||
This usermod adds the temperature readout to the Info tab and also publishes that over the topic `mcutemp` topic.
|
|
||||||
|
|
||||||
## Important
|
|
||||||
A shown temp of 53,33°C might indicate that the internal temp is not supported.
|
|
||||||
|
|
||||||
ESP8266 does not have a internal temp sensor
|
|
||||||
|
|
||||||
ESP32S2 seems to crash on reading the sensor -> disabled
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
Add a build flag `-D USERMOD_INTERNAL_TEMPERATURE` to your `platformio.ini` (or `platformio_override.ini`).
|
|
||||||
|
|
||||||
## Authors
|
|
||||||
Soeren Willrodt [@lost-hope](https://github.com/lost-hope)
|
|
||||||
|
|
||||||
Dimitry Zhemkov [@dima-zhemkov](https://github.com/dima-zhemkov)
|
|
@ -1,117 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "wled.h"
|
|
||||||
|
|
||||||
class InternalTemperatureUsermod : public Usermod
|
|
||||||
{
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned long loopInterval = 10000;
|
|
||||||
unsigned long lastTime = 0;
|
|
||||||
bool isEnabled = false;
|
|
||||||
float temperature = 0;
|
|
||||||
|
|
||||||
static const char _name[];
|
|
||||||
static const char _enabled[];
|
|
||||||
static const char _loopInterval[];
|
|
||||||
|
|
||||||
// any private methods should go here (non-inline methosd should be defined out of class)
|
|
||||||
void publishMqtt(const char *state, bool retain = false); // example for publishing MQTT message
|
|
||||||
|
|
||||||
public:
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
// if usermod is disabled or called during strip updating just exit
|
|
||||||
// NOTE: on very long strips strip.isUpdating() may always return true so update accordingly
|
|
||||||
if (!isEnabled || strip.isUpdating() || millis() - lastTime <= loopInterval)
|
|
||||||
return;
|
|
||||||
|
|
||||||
lastTime = millis();
|
|
||||||
|
|
||||||
#ifdef ESP8266 // ESP8266
|
|
||||||
// does not seem possible
|
|
||||||
temperature = -1;
|
|
||||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2) // ESP32S2
|
|
||||||
temperature = -1;
|
|
||||||
#else // ESP32 ESP32S3 and ESP32C3
|
|
||||||
temperature = roundf(temperatureRead() * 10) / 10;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_MQTT
|
|
||||||
if (WLED_MQTT_CONNECTED)
|
|
||||||
{
|
|
||||||
char array[10];
|
|
||||||
snprintf(array, sizeof(array), "%f", temperature);
|
|
||||||
publishMqtt(array);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void addToJsonInfo(JsonObject &root)
|
|
||||||
{
|
|
||||||
if (!isEnabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// if "u" object does not exist yet wee need to create it
|
|
||||||
JsonObject user = root["u"];
|
|
||||||
if (user.isNull())
|
|
||||||
user = root.createNestedObject("u");
|
|
||||||
|
|
||||||
JsonArray userTempArr = user.createNestedArray(FPSTR(_name));
|
|
||||||
userTempArr.add(temperature);
|
|
||||||
userTempArr.add(F(" °C"));
|
|
||||||
|
|
||||||
// if "sensor" object does not exist yet wee need to create it
|
|
||||||
JsonObject sensor = root[F("sensor")];
|
|
||||||
if (sensor.isNull())
|
|
||||||
sensor = root.createNestedObject(F("sensor"));
|
|
||||||
|
|
||||||
JsonArray sensorTempArr = sensor.createNestedArray(FPSTR(_name));
|
|
||||||
sensorTempArr.add(temperature);
|
|
||||||
sensorTempArr.add(F("°C"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void addToConfig(JsonObject &root)
|
|
||||||
{
|
|
||||||
JsonObject top = root.createNestedObject(FPSTR(_name));
|
|
||||||
top[FPSTR(_enabled)] = isEnabled;
|
|
||||||
top[FPSTR(_loopInterval)] = loopInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool readFromConfig(JsonObject &root)
|
|
||||||
{
|
|
||||||
JsonObject top = root[FPSTR(_name)];
|
|
||||||
bool configComplete = !top.isNull();
|
|
||||||
configComplete &= getJsonValue(top[FPSTR(_enabled)], isEnabled);
|
|
||||||
configComplete &= getJsonValue(top[FPSTR(_loopInterval)], loopInterval);
|
|
||||||
|
|
||||||
return configComplete;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t getId()
|
|
||||||
{
|
|
||||||
return USERMOD_ID_INTERNAL_TEMPERATURE;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const char InternalTemperatureUsermod::_name[] PROGMEM = "Internal Temperature";
|
|
||||||
const char InternalTemperatureUsermod::_enabled[] PROGMEM = "Enabled";
|
|
||||||
const char InternalTemperatureUsermod::_loopInterval[] PROGMEM = "Loop Interval";
|
|
||||||
|
|
||||||
void InternalTemperatureUsermod::publishMqtt(const char *state, bool retain)
|
|
||||||
{
|
|
||||||
#ifndef WLED_DISABLE_MQTT
|
|
||||||
// Check if MQTT Connected, otherwise it will crash the 8266
|
|
||||||
if (WLED_MQTT_CONNECTED)
|
|
||||||
{
|
|
||||||
char subuf[64];
|
|
||||||
strcpy(subuf, mqttDeviceTopic);
|
|
||||||
strcat_P(subuf, PSTR("/mcutemp"));
|
|
||||||
mqtt->publish(subuf, 0, retain, state);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
@ -20,12 +20,6 @@
|
|||||||
* ....
|
* ....
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(FFTTASK_PRIORITY)
|
|
||||||
#define FFTTASK_PRIORITY 1 // standard: looptask prio
|
|
||||||
//#define FFTTASK_PRIORITY 2 // above looptask, below asyc_tcp
|
|
||||||
//#define FFTTASK_PRIORITY 4 // above asyc_tcp
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Comment/Uncomment to toggle usb serial debugging
|
// Comment/Uncomment to toggle usb serial debugging
|
||||||
// #define MIC_LOGGER // MIC sampling & sound input debugging (serial plotter)
|
// #define MIC_LOGGER // MIC sampling & sound input debugging (serial plotter)
|
||||||
// #define FFT_SAMPLING_LOG // FFT result debugging
|
// #define FFT_SAMPLING_LOG // FFT result debugging
|
||||||
@ -110,7 +104,7 @@ static float sampleAgc = 0.0f; // Smoothed AGC sample
|
|||||||
|
|
||||||
// peak detection
|
// peak detection
|
||||||
static bool samplePeak = false; // Boolean flag for peak - used in effects. Responding routine may reset this flag. Auto-reset after strip.getMinShowDelay()
|
static bool samplePeak = false; // Boolean flag for peak - used in effects. Responding routine may reset this flag. Auto-reset after strip.getMinShowDelay()
|
||||||
static uint8_t maxVol = 31; // Reasonable value for constant volume for 'peak detector', as it won't always trigger (deprecated)
|
static uint8_t maxVol = 10; // Reasonable value for constant volume for 'peak detector', as it won't always trigger (deprecated)
|
||||||
static uint8_t binNum = 8; // Used to select the bin for FFT based beat detection (deprecated)
|
static uint8_t binNum = 8; // Used to select the bin for FFT based beat detection (deprecated)
|
||||||
static bool udpSamplePeak = false; // Boolean flag for peak. Set at the same tiem as samplePeak, but reset by transmitAudioData
|
static bool udpSamplePeak = false; // Boolean flag for peak. Set at the same tiem as samplePeak, but reset by transmitAudioData
|
||||||
static unsigned long timeOfPeak = 0; // time of last sample peak detection.
|
static unsigned long timeOfPeak = 0; // time of last sample peak detection.
|
||||||
@ -179,18 +173,13 @@ static float windowWeighingFactors[samplesFFT] = {0.0f};
|
|||||||
|
|
||||||
// Create FFT object
|
// Create FFT object
|
||||||
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
|
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
|
||||||
// lib_deps += https://github.com/kosme/arduinoFFT#develop @ 1.9.2
|
// lib_deps += https://github.com/kosme/arduinoFFT#develop @ 1.9.2
|
||||||
// these options actually cause slow-downs on all esp32 processors, don't use them.
|
#define FFT_SPEED_OVER_PRECISION // enables use of reciprocals (1/x etc), and an a few other speedups
|
||||||
// #define FFT_SPEED_OVER_PRECISION // enables use of reciprocals (1/x etc) - not faster on ESP32
|
#define FFT_SQRT_APPROXIMATION // enables "quake3" style inverse sqrt
|
||||||
// #define FFT_SQRT_APPROXIMATION // enables "quake3" style inverse sqrt - slower on ESP32
|
#define sqrt(x) sqrtf(x) // little hack that reduces FFT time by 50% on ESP32 (as alternative to FFT_SQRT_APPROXIMATION)
|
||||||
// Below options are forcing ArduinoFFT to use sqrtf() instead of sqrt()
|
|
||||||
#define sqrt(x) sqrtf(x) // little hack that reduces FFT time by 10-50% on ESP32
|
|
||||||
#define sqrt_internal sqrtf // see https://github.com/kosme/arduinoFFT/pull/83
|
|
||||||
#else
|
#else
|
||||||
// around 40% slower on -S2
|
// lib_deps += https://github.com/blazoncek/arduinoFFT.git
|
||||||
// lib_deps += https://github.com/blazoncek/arduinoFFT.git
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <arduinoFFT.h>
|
#include <arduinoFFT.h>
|
||||||
|
|
||||||
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
|
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
|
||||||
@ -422,7 +411,7 @@ static void runMicFilter(uint16_t numSamples, float *sampleBuffer) // p
|
|||||||
//constexpr float beta1 = 0.8285f; // 18Khz
|
//constexpr float beta1 = 0.8285f; // 18Khz
|
||||||
constexpr float beta1 = 0.85f; // 20Khz
|
constexpr float beta1 = 0.85f; // 20Khz
|
||||||
|
|
||||||
constexpr float beta2 = (1.0f - beta1) / 2.0f;
|
constexpr float beta2 = (1.0f - beta1) / 2.0;
|
||||||
static float last_vals[2] = { 0.0f }; // FIR high freq cutoff filter
|
static float last_vals[2] = { 0.0f }; // FIR high freq cutoff filter
|
||||||
static float lowfilt = 0.0f; // IIR low frequency cutoff filter
|
static float lowfilt = 0.0f; // IIR low frequency cutoff filter
|
||||||
|
|
||||||
@ -475,17 +464,17 @@ static void postProcessFFTResults(bool noiseGateOpen, int numberOfChannels) // p
|
|||||||
switch (FFTScalingMode) {
|
switch (FFTScalingMode) {
|
||||||
case 1:
|
case 1:
|
||||||
// Logarithmic scaling
|
// Logarithmic scaling
|
||||||
currentResult *= 0.42f; // 42 is the answer ;-)
|
currentResult *= 0.42; // 42 is the answer ;-)
|
||||||
currentResult -= 8.0f; // this skips the lowest row, giving some room for peaks
|
currentResult -= 8.0; // this skips the lowest row, giving some room for peaks
|
||||||
if (currentResult > 1.0f) currentResult = logf(currentResult); // log to base "e", which is the fastest log() function
|
if (currentResult > 1.0) currentResult = logf(currentResult); // log to base "e", which is the fastest log() function
|
||||||
else currentResult = 0.0f; // special handling, because log(1) = 0; log(0) = undefined
|
else currentResult = 0.0; // special handling, because log(1) = 0; log(0) = undefined
|
||||||
currentResult *= 0.85f + (float(i)/18.0f); // extra up-scaling for high frequencies
|
currentResult *= 0.85f + (float(i)/18.0f); // extra up-scaling for high frequencies
|
||||||
currentResult = mapf(currentResult, 0, LOG_256, 0, 255); // map [log(1) ... log(255)] to [0 ... 255]
|
currentResult = mapf(currentResult, 0, LOG_256, 0, 255); // map [log(1) ... log(255)] to [0 ... 255]
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
// Linear scaling
|
// Linear scaling
|
||||||
currentResult *= 0.30f; // needs a bit more damping, get stay below 255
|
currentResult *= 0.30f; // needs a bit more damping, get stay below 255
|
||||||
currentResult -= 4.0f; // giving a bit more room for peaks
|
currentResult -= 4.0; // giving a bit more room for peaks
|
||||||
if (currentResult < 1.0f) currentResult = 0.0f;
|
if (currentResult < 1.0f) currentResult = 0.0f;
|
||||||
currentResult *= 0.85f + (float(i)/1.8f); // extra up-scaling for high frequencies
|
currentResult *= 0.85f + (float(i)/1.8f); // extra up-scaling for high frequencies
|
||||||
break;
|
break;
|
||||||
@ -493,8 +482,8 @@ static void postProcessFFTResults(bool noiseGateOpen, int numberOfChannels) // p
|
|||||||
// square root scaling
|
// square root scaling
|
||||||
currentResult *= 0.38f;
|
currentResult *= 0.38f;
|
||||||
currentResult -= 6.0f;
|
currentResult -= 6.0f;
|
||||||
if (currentResult > 1.0f) currentResult = sqrtf(currentResult);
|
if (currentResult > 1.0) currentResult = sqrtf(currentResult);
|
||||||
else currentResult = 0.0f; // special handling, because sqrt(0) = undefined
|
else currentResult = 0.0; // special handling, because sqrt(0) = undefined
|
||||||
currentResult *= 0.85f + (float(i)/4.5f); // extra up-scaling for high frequencies
|
currentResult *= 0.85f + (float(i)/4.5f); // extra up-scaling for high frequencies
|
||||||
currentResult = mapf(currentResult, 0.0, 16.0, 0.0, 255.0); // map [sqrt(1) ... sqrt(256)] to [0 ... 255]
|
currentResult = mapf(currentResult, 0.0, 16.0, 0.0, 255.0); // map [sqrt(1) ... sqrt(256)] to [0 ... 255]
|
||||||
break;
|
break;
|
||||||
@ -522,11 +511,11 @@ static void postProcessFFTResults(bool noiseGateOpen, int numberOfChannels) // p
|
|||||||
// peak detection is called from FFT task when vReal[] contains valid FFT results
|
// peak detection is called from FFT task when vReal[] contains valid FFT results
|
||||||
static void detectSamplePeak(void) {
|
static void detectSamplePeak(void) {
|
||||||
bool havePeak = false;
|
bool havePeak = false;
|
||||||
// softhack007: this code continuously triggers while amplitude in the selected bin is above a certain threshold. So it does not detect peaks - it detects high activity in a frequency bin.
|
|
||||||
// Poor man's beat detection by seeing if sample > Average + some value.
|
// Poor man's beat detection by seeing if sample > Average + some value.
|
||||||
// This goes through ALL of the 255 bins - but ignores stupid settings
|
// This goes through ALL of the 255 bins - but ignores stupid settings
|
||||||
// Then we got a peak, else we don't. The peak has to time out on its own in order to support UDP sound sync.
|
// Then we got a peak, else we don't. The peak has to time out on its own in order to support UDP sound sync.
|
||||||
if ((sampleAvg > 1) && (maxVol > 0) && (binNum > 4) && (vReal[binNum] > maxVol) && ((millis() - timeOfPeak) > 100)) {
|
if ((sampleAvg > 1) && (maxVol > 0) && (binNum > 1) && (vReal[binNum] > maxVol) && ((millis() - timeOfPeak) > 100)) {
|
||||||
havePeak = true;
|
havePeak = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -769,7 +758,7 @@ class AudioReactive : public Usermod {
|
|||||||
if (time_now - last_time > 2) {
|
if (time_now - last_time > 2) {
|
||||||
last_time = time_now;
|
last_time = time_now;
|
||||||
|
|
||||||
if((fabsf(sampleReal) < 2.0f) || (sampleMax < 1.0)) {
|
if((fabsf(sampleReal) < 2.0f) || (sampleMax < 1.0f)) {
|
||||||
// MIC signal is "squelched" - deliver silence
|
// MIC signal is "squelched" - deliver silence
|
||||||
tmpAgc = 0;
|
tmpAgc = 0;
|
||||||
// we need to "spin down" the intgrated error buffer
|
// we need to "spin down" the intgrated error buffer
|
||||||
@ -884,8 +873,8 @@ class AudioReactive : public Usermod {
|
|||||||
// keep "peak" sample, but decay value if current sample is below peak
|
// keep "peak" sample, but decay value if current sample is below peak
|
||||||
if ((sampleMax < sampleReal) && (sampleReal > 0.5f)) {
|
if ((sampleMax < sampleReal) && (sampleReal > 0.5f)) {
|
||||||
sampleMax = sampleMax + 0.5f * (sampleReal - sampleMax); // new peak - with some filtering
|
sampleMax = sampleMax + 0.5f * (sampleReal - sampleMax); // new peak - with some filtering
|
||||||
// another simple way to detect samplePeak - cannot detect beats, but reacts on peak volume
|
// another simple way to detect samplePeak
|
||||||
if (((binNum < 12) || ((maxVol < 1))) && (millis() - timeOfPeak > 80) && (sampleAvg > 1)) {
|
if ((binNum < 10) && (millis() - timeOfPeak > 80) && (sampleAvg > 1)) {
|
||||||
samplePeak = true;
|
samplePeak = true;
|
||||||
timeOfPeak = millis();
|
timeOfPeak = millis();
|
||||||
udpSamplePeak = true;
|
udpSamplePeak = true;
|
||||||
@ -960,8 +949,6 @@ class AudioReactive : public Usermod {
|
|||||||
//DEBUGSR_PRINTLN("Transmitting UDP Mic Packet");
|
//DEBUGSR_PRINTLN("Transmitting UDP Mic Packet");
|
||||||
|
|
||||||
audioSyncPacket transmitData;
|
audioSyncPacket transmitData;
|
||||||
memset(reinterpret_cast<void *>(&transmitData), 0, sizeof(transmitData)); // make sure that the packet - including "invisible" padding bytes added by the compiler - is fully initialized
|
|
||||||
|
|
||||||
strncpy_P(transmitData.header, PSTR(UDP_SYNC_HEADER), 6);
|
strncpy_P(transmitData.header, PSTR(UDP_SYNC_HEADER), 6);
|
||||||
// transmit samples that were not modified by limitSampleDynamics()
|
// transmit samples that were not modified by limitSampleDynamics()
|
||||||
transmitData.sampleRaw = (soundAgc) ? rawSampleAgc: sampleRaw;
|
transmitData.sampleRaw = (soundAgc) ? rawSampleAgc: sampleRaw;
|
||||||
@ -977,10 +964,9 @@ class AudioReactive : public Usermod {
|
|||||||
transmitData.FFT_Magnitude = my_magnitude;
|
transmitData.FFT_Magnitude = my_magnitude;
|
||||||
transmitData.FFT_MajorPeak = FFT_MajorPeak;
|
transmitData.FFT_MajorPeak = FFT_MajorPeak;
|
||||||
|
|
||||||
if (fftUdp.beginMulticastPacket() != 0) { // beginMulticastPacket returns 0 in case of error
|
fftUdp.beginMulticastPacket();
|
||||||
fftUdp.write(reinterpret_cast<uint8_t *>(&transmitData), sizeof(transmitData));
|
fftUdp.write(reinterpret_cast<uint8_t *>(&transmitData), sizeof(transmitData));
|
||||||
fftUdp.endPacket();
|
fftUdp.endPacket();
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
} // transmitAudioData()
|
} // transmitAudioData()
|
||||||
|
|
||||||
@ -1177,7 +1163,6 @@ class AudioReactive : public Usermod {
|
|||||||
DEBUGSR_PRINTLN(F("AR: Analog Microphone (left channel only)."));
|
DEBUGSR_PRINTLN(F("AR: Analog Microphone (left channel only)."));
|
||||||
audioSource = new I2SAdcSource(SAMPLE_RATE, BLOCK_SIZE);
|
audioSource = new I2SAdcSource(SAMPLE_RATE, BLOCK_SIZE);
|
||||||
delay(100);
|
delay(100);
|
||||||
useBandPassFilter = true; // PDM bandpass filter seems to help for bad quality analog
|
|
||||||
if (audioSource) audioSource->initialize(audioPin);
|
if (audioSource) audioSource->initialize(audioPin);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@ -1287,10 +1272,9 @@ class AudioReactive : public Usermod {
|
|||||||
|
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
// complain when audio userloop has been delayed for long time. Currently we need userloop running between 500 and 1500 times per second.
|
// complain when audio userloop has been delayed for long time. Currently we need userloop running between 500 and 1500 times per second.
|
||||||
// softhack007 disabled temporarily - avoid serial console spam with MANY leds and low FPS
|
if ((userloopDelay > 23) && !disableSoundProcessing && (audioSyncEnabled == 0)) {
|
||||||
//if ((userloopDelay > 65) && !disableSoundProcessing && (audioSyncEnabled == 0)) {
|
DEBUG_PRINTF("[AR userLoop] hickup detected -> was inactive for last %d millis!\n", userloopDelay);
|
||||||
//DEBUG_PRINTF("[AR userLoop] hickup detected -> was inactive for last %d millis!\n", userloopDelay);
|
}
|
||||||
//}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// run filters, and repeat in case of loop delays (hick-up compensation)
|
// run filters, and repeat in case of loop delays (hick-up compensation)
|
||||||
@ -1327,9 +1311,6 @@ class AudioReactive : public Usermod {
|
|||||||
if (millis() - lastTime > delayMs) {
|
if (millis() - lastTime > delayMs) {
|
||||||
have_new_sample = receiveAudioData();
|
have_new_sample = receiveAudioData();
|
||||||
if (have_new_sample) last_UDPTime = millis();
|
if (have_new_sample) last_UDPTime = millis();
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
else fftUdp.flush(); // Flush udp input buffers if we haven't read it - avoids hickups in receive mode. Does not work on 8266.
|
|
||||||
#endif
|
|
||||||
lastTime = millis();
|
lastTime = millis();
|
||||||
}
|
}
|
||||||
if (have_new_sample) syncVolumeSmth = volumeSmth; // remember received sample
|
if (have_new_sample) syncVolumeSmth = volumeSmth; // remember received sample
|
||||||
@ -1348,7 +1329,7 @@ class AudioReactive : public Usermod {
|
|||||||
// Info Page: keep max sample from last 5 seconds
|
// Info Page: keep max sample from last 5 seconds
|
||||||
if ((millis() - sampleMaxTimer) > CYCLE_SAMPLEMAX) {
|
if ((millis() - sampleMaxTimer) > CYCLE_SAMPLEMAX) {
|
||||||
sampleMaxTimer = millis();
|
sampleMaxTimer = millis();
|
||||||
maxSample5sec = (0.15f * maxSample5sec) + 0.85f *((soundAgc) ? sampleAgc : sampleAvg); // reset, and start with some smoothing
|
maxSample5sec = (0.15 * maxSample5sec) + 0.85 *((soundAgc) ? sampleAgc : sampleAvg); // reset, and start with some smoothing
|
||||||
if (sampleAvg < 1) maxSample5sec = 0; // noise gate
|
if (sampleAvg < 1) maxSample5sec = 0; // noise gate
|
||||||
} else {
|
} else {
|
||||||
if ((sampleAvg >= 1)) maxSample5sec = fmaxf(maxSample5sec, (soundAgc) ? rawSampleAgc : sampleRaw); // follow maximum volume
|
if ((sampleAvg >= 1)) maxSample5sec = fmaxf(maxSample5sec, (soundAgc) ? rawSampleAgc : sampleRaw); // follow maximum volume
|
||||||
@ -1392,11 +1373,10 @@ class AudioReactive : public Usermod {
|
|||||||
memset(fftAvg, 0, sizeof(fftAvg));
|
memset(fftAvg, 0, sizeof(fftAvg));
|
||||||
memset(fftResult, 0, sizeof(fftResult));
|
memset(fftResult, 0, sizeof(fftResult));
|
||||||
for(int i=(init?0:1); i<NUM_GEQ_CHANNELS; i+=2) fftResult[i] = 16; // make a tiny pattern
|
for(int i=(init?0:1); i<NUM_GEQ_CHANNELS; i+=2) fftResult[i] = 16; // make a tiny pattern
|
||||||
inputLevel = 128; // reset level slider to default
|
inputLevel = 128; // resset level slider to default
|
||||||
autoResetPeak();
|
autoResetPeak();
|
||||||
|
|
||||||
if (init && FFT_Task) {
|
if (init && FFT_Task) {
|
||||||
delay(25); // give some time for I2S driver to finish sampling before we suspend it
|
|
||||||
vTaskSuspend(FFT_Task); // update is about to begin, disable task to prevent crash
|
vTaskSuspend(FFT_Task); // update is about to begin, disable task to prevent crash
|
||||||
if (udpSyncConnected) { // close UDP sync connection (if open)
|
if (udpSyncConnected) { // close UDP sync connection (if open)
|
||||||
udpSyncConnected = false;
|
udpSyncConnected = false;
|
||||||
@ -1408,14 +1388,15 @@ class AudioReactive : public Usermod {
|
|||||||
vTaskResume(FFT_Task);
|
vTaskResume(FFT_Task);
|
||||||
connected(); // resume UDP
|
connected(); // resume UDP
|
||||||
} else
|
} else
|
||||||
xTaskCreateUniversal( // xTaskCreateUniversal also works on -S2 and -C3 with single core
|
// xTaskCreatePinnedToCore(
|
||||||
|
xTaskCreate( // no need to "pin" this task to core #0
|
||||||
FFTcode, // Function to implement the task
|
FFTcode, // Function to implement the task
|
||||||
"FFT", // Name of the task
|
"FFT", // Name of the task
|
||||||
3592, // Stack size in words // 3592 leaves 800-1024 bytes of task stack free
|
5000, // Stack size in words
|
||||||
NULL, // Task input parameter
|
NULL, // Task input parameter
|
||||||
FFTTASK_PRIORITY, // Priority of the task
|
1, // Priority of the task
|
||||||
&FFT_Task // Task handle
|
&FFT_Task // Task handle
|
||||||
, 0 // Core where the task should run
|
// , 0 // Core where the task should run
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
micDataReal = 0.0f; // just to be sure
|
micDataReal = 0.0f; // just to be sure
|
||||||
@ -1512,7 +1493,7 @@ class AudioReactive : public Usermod {
|
|||||||
infoArr.add(F("I2S digital"));
|
infoArr.add(F("I2S digital"));
|
||||||
}
|
}
|
||||||
// input level or "silence"
|
// input level or "silence"
|
||||||
if (maxSample5sec > 1.0f) {
|
if (maxSample5sec > 1.0) {
|
||||||
float my_usage = 100.0f * (maxSample5sec / 255.0f);
|
float my_usage = 100.0f * (maxSample5sec / 255.0f);
|
||||||
snprintf_P(myStringBuffer, 15, PSTR(" - peak %3d%%"), int(my_usage));
|
snprintf_P(myStringBuffer, 15, PSTR(" - peak %3d%%"), int(my_usage));
|
||||||
infoArr.add(myStringBuffer);
|
infoArr.add(myStringBuffer);
|
||||||
@ -1522,7 +1503,7 @@ class AudioReactive : public Usermod {
|
|||||||
} else {
|
} else {
|
||||||
// error during audio source setup
|
// error during audio source setup
|
||||||
infoArr.add(F("not initialized"));
|
infoArr.add(F("not initialized"));
|
||||||
infoArr.add(F(" - check pin settings"));
|
infoArr.add(F(" - check GPIO config"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1826,9 +1807,7 @@ class AudioReactive : public Usermod {
|
|||||||
const char AudioReactive::_name[] PROGMEM = "AudioReactive";
|
const char AudioReactive::_name[] PROGMEM = "AudioReactive";
|
||||||
const char AudioReactive::_enabled[] PROGMEM = "enabled";
|
const char AudioReactive::_enabled[] PROGMEM = "enabled";
|
||||||
const char AudioReactive::_inputLvl[] PROGMEM = "inputLevel";
|
const char AudioReactive::_inputLvl[] PROGMEM = "inputLevel";
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
|
||||||
const char AudioReactive::_analogmic[] PROGMEM = "analogmic";
|
const char AudioReactive::_analogmic[] PROGMEM = "analogmic";
|
||||||
#endif
|
|
||||||
const char AudioReactive::_digitalmic[] PROGMEM = "digitalmic";
|
const char AudioReactive::_digitalmic[] PROGMEM = "digitalmic";
|
||||||
const char AudioReactive::UDP_SYNC_HEADER[] PROGMEM = "00002"; // new sync header version, as format no longer compatible with previous structure
|
const char AudioReactive::UDP_SYNC_HEADER[] PROGMEM = "00002"; // new sync header version, as format no longer compatible with previous structure
|
||||||
const char AudioReactive::UDP_SYNC_HEADER_v1[] PROGMEM = "00001"; // old sync header version - need to add backwards-compatibility feature
|
const char AudioReactive::UDP_SYNC_HEADER_v1[] PROGMEM = "00001"; // old sync header version - need to add backwards-compatibility feature
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
#include <driver/i2s.h>
|
#include <driver/i2s.h>
|
||||||
#include <driver/adc.h>
|
#include <driver/adc.h>
|
||||||
@ -22,14 +22,14 @@
|
|||||||
|
|
||||||
// see https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/chip-series-comparison.html#related-documents
|
// see https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/chip-series-comparison.html#related-documents
|
||||||
// and https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/i2s.html#overview-of-all-modes
|
// and https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/i2s.html#overview-of-all-modes
|
||||||
#if defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(ESP8266) || defined(ESP8265)
|
#if defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(ESP8266) || defined(ESP8265)
|
||||||
// there are two things in these MCUs that could lead to problems with audio processing:
|
// there are two things in these MCUs that could lead to problems with audio processing:
|
||||||
// * no floating point hardware (FPU) support - FFT uses float calculations. If done in software, a strong slow-down can be expected (between 8x and 20x)
|
// * no floating point hardware (FPU) support - FFT uses float calculations. If done in software, a strong slow-down can be expected (between 8x and 20x)
|
||||||
// * single core, so FFT task might slow down other things like LED updates
|
// * single core, so FFT task might slow down other things like LED updates
|
||||||
#if !defined(SOC_I2S_NUM) || (SOC_I2S_NUM < 1)
|
#if !defined(SOC_I2S_NUM) || (SOC_I2S_NUM < 1)
|
||||||
#error This audio reactive usermod does not support ESP32-C2 or ESP32-C3.
|
#error This audio reactive usermod does not support ESP32-C2, ESP32-C3 or ESP32-S2.
|
||||||
#else
|
#else
|
||||||
#warning This audio reactive usermod does not support ESP32-C2 and ESP32-C3.
|
#warning This audio reactive usermod does not support ESP32-C2, ESP32-C3 or ESP32-S2.
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -71,7 +71,7 @@
|
|||||||
* if you want to receive two channels, one is the actual data from microphone and another channel is suppose to receive 0, it's different data in two channels, you need to choose I2S_CHANNEL_FMT_RIGHT_LEFT in this case.
|
* if you want to receive two channels, one is the actual data from microphone and another channel is suppose to receive 0, it's different data in two channels, you need to choose I2S_CHANNEL_FMT_RIGHT_LEFT in this case.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)) && (ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(4, 4, 4))
|
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)) && (ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(4, 4, 3))
|
||||||
// espressif bug: only_left has no sound, left and right are swapped
|
// espressif bug: only_left has no sound, left and right are swapped
|
||||||
// https://github.com/espressif/esp-idf/issues/9635 I2S mic not working since 4.4 (IDFGH-8138)
|
// https://github.com/espressif/esp-idf/issues/9635 I2S mic not working since 4.4 (IDFGH-8138)
|
||||||
// https://github.com/espressif/esp-idf/issues/8538 I2S channel selection issue? (IDFGH-6918)
|
// https://github.com/espressif/esp-idf/issues/8538 I2S channel selection issue? (IDFGH-6918)
|
||||||
@ -122,7 +122,7 @@ class AudioSource {
|
|||||||
This function needs to take care of anything that needs to be done
|
This function needs to take care of anything that needs to be done
|
||||||
before samples can be obtained from the microphone.
|
before samples can be obtained from the microphone.
|
||||||
*/
|
*/
|
||||||
virtual void initialize(int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) = 0;
|
virtual void initialize(int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) = 0;
|
||||||
|
|
||||||
/* Deinitialize
|
/* Deinitialize
|
||||||
Release all resources and deactivate any functionality that is used
|
Release all resources and deactivate any functionality that is used
|
||||||
@ -191,8 +191,7 @@ class I2SSource : public AudioSource {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void initialize(int8_t i2swsPin = I2S_PIN_NO_CHANGE, int8_t i2ssdPin = I2S_PIN_NO_CHANGE, int8_t i2sckPin = I2S_PIN_NO_CHANGE, int8_t mclkPin = I2S_PIN_NO_CHANGE) {
|
virtual void initialize(int8_t i2swsPin = I2S_PIN_NO_CHANGE, int8_t i2ssdPin = I2S_PIN_NO_CHANGE, int8_t i2sckPin = I2S_PIN_NO_CHANGE, int8_t mclkPin = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
|
||||||
DEBUGSR_PRINTLN("I2SSource:: initialize().");
|
|
||||||
if (i2swsPin != I2S_PIN_NO_CHANGE && i2ssdPin != I2S_PIN_NO_CHANGE) {
|
if (i2swsPin != I2S_PIN_NO_CHANGE && i2ssdPin != I2S_PIN_NO_CHANGE) {
|
||||||
if (!pinManager.allocatePin(i2swsPin, true, PinOwner::UM_Audioreactive) ||
|
if (!pinManager.allocatePin(i2swsPin, true, PinOwner::UM_Audioreactive) ||
|
||||||
!pinManager.allocatePin(i2ssdPin, false, PinOwner::UM_Audioreactive)) { // #206
|
!pinManager.allocatePin(i2ssdPin, false, PinOwner::UM_Audioreactive)) { // #206
|
||||||
@ -413,7 +412,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin) {
|
void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin) {
|
||||||
DEBUGSR_PRINTLN("ES7243:: initialize();");
|
|
||||||
if ((i2sckPin < 0) || (mclkPin < 0)) {
|
if ((i2sckPin < 0) || (mclkPin < 0)) {
|
||||||
DEBUGSR_PRINTF("\nAR: invalid I2S pin: SCK=%d, MCLK=%d\n", i2sckPin, mclkPin);
|
DEBUGSR_PRINTF("\nAR: invalid I2S pin: SCK=%d, MCLK=%d\n", i2sckPin, mclkPin);
|
||||||
return;
|
return;
|
||||||
@ -529,7 +527,7 @@ class ES8388Source : public I2SSource {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin) {
|
void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin) {
|
||||||
DEBUGSR_PRINTLN("ES8388Source:: initialize();");
|
|
||||||
if ((i2sckPin < 0) || (mclkPin < 0)) {
|
if ((i2sckPin < 0) || (mclkPin < 0)) {
|
||||||
DEBUGSR_PRINTF("\nAR: invalid I2S pin: SCK=%d, MCLK=%d\n", i2sckPin, mclkPin);
|
DEBUGSR_PRINTF("\nAR: invalid I2S pin: SCK=%d, MCLK=%d\n", i2sckPin, mclkPin);
|
||||||
return;
|
return;
|
||||||
@ -586,8 +584,7 @@ class I2SAdcSource : public I2SSource {
|
|||||||
/* identify Audiosource type - I2S-ADC*/
|
/* identify Audiosource type - I2S-ADC*/
|
||||||
AudioSourceType getType(void) {return(Type_I2SAdc);}
|
AudioSourceType getType(void) {return(Type_I2SAdc);}
|
||||||
|
|
||||||
void initialize(int8_t audioPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
|
void initialize(int8_t audioPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
|
||||||
DEBUGSR_PRINTLN("I2SAdcSource:: initialize().");
|
|
||||||
_myADCchannel = 0x0F;
|
_myADCchannel = 0x0F;
|
||||||
if(!pinManager.allocatePin(audioPin, false, PinOwner::UM_Audioreactive)) {
|
if(!pinManager.allocatePin(audioPin, false, PinOwner::UM_Audioreactive)) {
|
||||||
DEBUGSR_PRINTF("failed to allocate GPIO for audio analog input: %d\n", audioPin);
|
DEBUGSR_PRINTF("failed to allocate GPIO for audio analog input: %d\n", audioPin);
|
||||||
@ -758,8 +755,7 @@ class SPH0654 : public I2SSource {
|
|||||||
I2SSource(sampleRate, blockSize, sampleScale)
|
I2SSource(sampleRate, blockSize, sampleScale)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t = I2S_PIN_NO_CHANGE) {
|
void initialize(uint8_t i2swsPin, uint8_t i2ssdPin, uint8_t i2sckPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
|
||||||
DEBUGSR_PRINTLN("SPH0654:: initialize();");
|
|
||||||
I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin);
|
I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin);
|
||||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
// these registers are only existing in "classic" ESP32
|
// these registers are only existing in "classic" ESP32
|
||||||
@ -770,4 +766,3 @@ class SPH0654 : public I2SSource {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
|
@ -1081,7 +1081,7 @@ bool FourLineDisplayUsermod::handleButton(uint8_t b) {
|
|||||||
static bool buttonLongPressed = false;
|
static bool buttonLongPressed = false;
|
||||||
static unsigned long buttonPressedTime = 0;
|
static unsigned long buttonPressedTime = 0;
|
||||||
static unsigned long buttonWaitTime = 0;
|
static unsigned long buttonWaitTime = 0;
|
||||||
bool handled = false;
|
bool handled = true;
|
||||||
|
|
||||||
//momentary button logic
|
//momentary button logic
|
||||||
if (isButtonPressed(b)) { //pressed
|
if (isButtonPressed(b)) { //pressed
|
||||||
@ -1090,12 +1090,11 @@ bool FourLineDisplayUsermod::handleButton(uint8_t b) {
|
|||||||
buttonPressedBefore = true;
|
buttonPressedBefore = true;
|
||||||
|
|
||||||
if (now - buttonPressedTime > 600) { //long press
|
if (now - buttonPressedTime > 600) { //long press
|
||||||
|
buttonLongPressed = true;
|
||||||
//TODO: handleButton() handles button 0 without preset in a different way for double click
|
//TODO: handleButton() handles button 0 without preset in a different way for double click
|
||||||
//so we need to override with same behaviour
|
//so we need to override with same behaviour
|
||||||
//DEBUG_PRINTLN(F("4LD action."));
|
longPressAction(0);
|
||||||
//if (!buttonLongPressed) longPressAction(0);
|
//handled = false;
|
||||||
buttonLongPressed = true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (!isButtonPressed(b) && buttonPressedBefore) { //released
|
} else if (!isButtonPressed(b) && buttonPressedBefore) { //released
|
||||||
@ -1127,7 +1126,7 @@ bool FourLineDisplayUsermod::handleButton(uint8_t b) {
|
|||||||
buttonWaitTime = 0;
|
buttonWaitTime = 0;
|
||||||
//TODO: handleButton() handles button 0 without preset in a different way for double click
|
//TODO: handleButton() handles button 0 without preset in a different way for double click
|
||||||
//so we need to override with same behaviour
|
//so we need to override with same behaviour
|
||||||
//shortPressAction(0);
|
shortPressAction(0);
|
||||||
//handled = false;
|
//handled = false;
|
||||||
}
|
}
|
||||||
return handled;
|
return handled;
|
||||||
|
@ -398,14 +398,8 @@ void RotaryEncoderUIUsermod::sortModesAndPalettes() {
|
|||||||
modes_alpha_indexes = re_initIndexArray(strip.getModeCount());
|
modes_alpha_indexes = re_initIndexArray(strip.getModeCount());
|
||||||
re_sortModes(modes_qstrings, modes_alpha_indexes, strip.getModeCount(), MODE_SORT_SKIP_COUNT);
|
re_sortModes(modes_qstrings, modes_alpha_indexes, strip.getModeCount(), MODE_SORT_SKIP_COUNT);
|
||||||
|
|
||||||
palettes_qstrings = re_findModeStrings(JSON_palette_names, strip.getPaletteCount()+strip.customPalettes.size());
|
palettes_qstrings = re_findModeStrings(JSON_palette_names, strip.getPaletteCount());
|
||||||
palettes_alpha_indexes = re_initIndexArray(strip.getPaletteCount()+strip.customPalettes.size());
|
palettes_alpha_indexes = re_initIndexArray(strip.getPaletteCount()); // only use internal palettes
|
||||||
if (strip.customPalettes.size()) {
|
|
||||||
for (int i=0; i<strip.customPalettes.size(); i++) {
|
|
||||||
palettes_alpha_indexes[strip.getPaletteCount()+i] = 255-i;
|
|
||||||
palettes_qstrings[strip.getPaletteCount()+i] = PSTR("~Custom~");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// How many palette names start with '*' and should not be sorted?
|
// How many palette names start with '*' and should not be sorted?
|
||||||
// (Also skipping the first one, 'Default').
|
// (Also skipping the first one, 'Default').
|
||||||
@ -502,7 +496,7 @@ void RotaryEncoderUIUsermod::setup()
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PinManagerPinType pins[3] = { { pinA, false }, { pinB, false }, { pinC, false } };
|
PinManagerPinType pins[3] = { { pinA, false }, { pinB, false }, { pinC, false } };
|
||||||
if (pinA<0 || pinB<0 || !pinManager.allocateMultiplePins(pins, 3, PinOwner::UM_RotaryEncoderUI)) {
|
if (!pinManager.allocateMultiplePins(pins, 3, PinOwner::UM_RotaryEncoderUI)) {
|
||||||
pinA = pinB = pinC = -1;
|
pinA = pinB = pinC = -1;
|
||||||
enabled = false;
|
enabled = false;
|
||||||
return;
|
return;
|
||||||
@ -513,7 +507,7 @@ void RotaryEncoderUIUsermod::setup()
|
|||||||
#endif
|
#endif
|
||||||
pinMode(pinA, USERMOD_ROTARY_ENCODER_GPIO);
|
pinMode(pinA, USERMOD_ROTARY_ENCODER_GPIO);
|
||||||
pinMode(pinB, USERMOD_ROTARY_ENCODER_GPIO);
|
pinMode(pinB, USERMOD_ROTARY_ENCODER_GPIO);
|
||||||
if (pinC>=0) pinMode(pinC, USERMOD_ROTARY_ENCODER_GPIO);
|
pinMode(pinC, USERMOD_ROTARY_ENCODER_GPIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
loopTime = millis();
|
loopTime = millis();
|
||||||
@ -688,25 +682,21 @@ void RotaryEncoderUIUsermod::displayNetworkInfo() {
|
|||||||
void RotaryEncoderUIUsermod::findCurrentEffectAndPalette() {
|
void RotaryEncoderUIUsermod::findCurrentEffectAndPalette() {
|
||||||
DEBUG_PRINTLN(F("Finding current mode and palette."));
|
DEBUG_PRINTLN(F("Finding current mode and palette."));
|
||||||
currentEffectAndPaletteInitialized = true;
|
currentEffectAndPaletteInitialized = true;
|
||||||
|
for (uint8_t i = 0; i < strip.getModeCount(); i++) {
|
||||||
effectCurrentIndex = 0;
|
|
||||||
for (int i = 0; i < strip.getModeCount(); i++) {
|
|
||||||
if (modes_alpha_indexes[i] == effectCurrent) {
|
if (modes_alpha_indexes[i] == effectCurrent) {
|
||||||
effectCurrentIndex = i;
|
effectCurrentIndex = i;
|
||||||
DEBUG_PRINTLN(F("Found current mode."));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DEBUG_PRINTLN(F("Found current mode."));
|
||||||
|
|
||||||
effectPaletteIndex = 0;
|
for (uint8_t i = 0; i < strip.getPaletteCount(); i++) {
|
||||||
DEBUG_PRINTLN(effectPalette);
|
|
||||||
for (uint8_t i = 0; i < strip.getPaletteCount()+strip.customPalettes.size(); i++) {
|
|
||||||
if (palettes_alpha_indexes[i] == effectPalette) {
|
if (palettes_alpha_indexes[i] == effectPalette) {
|
||||||
effectPaletteIndex = i;
|
effectPaletteIndex = i;
|
||||||
DEBUG_PRINTLN(F("Found palette."));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DEBUG_PRINTLN(F("Found palette."));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RotaryEncoderUIUsermod::changeState(const char *stateName, byte markedLine, byte markedCol, byte glyph) {
|
bool RotaryEncoderUIUsermod::changeState(const char *stateName, byte markedLine, byte markedCol, byte glyph) {
|
||||||
@ -741,9 +731,7 @@ void RotaryEncoderUIUsermod::changeBrightness(bool increase) {
|
|||||||
}
|
}
|
||||||
display->updateRedrawTime();
|
display->updateRedrawTime();
|
||||||
#endif
|
#endif
|
||||||
//bri = max(min((increase ? bri+fadeAmount : bri-fadeAmount), 255), 0);
|
bri = max(min((increase ? bri+fadeAmount : bri-fadeAmount), 255), 0);
|
||||||
if (bri < 40) bri = max(min((increase ? bri+fadeAmount/2 : bri-fadeAmount/2), 255), 0); // slower steps when brightness < 16%
|
|
||||||
else bri = max(min((increase ? bri+fadeAmount : bri-fadeAmount), 255), 0);
|
|
||||||
lampUdated();
|
lampUdated();
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||||
display->updateBrightness();
|
display->updateBrightness();
|
||||||
@ -890,7 +878,7 @@ void RotaryEncoderUIUsermod::changePalette(bool increase) {
|
|||||||
}
|
}
|
||||||
display->updateRedrawTime();
|
display->updateRedrawTime();
|
||||||
#endif
|
#endif
|
||||||
effectPaletteIndex = max(min((unsigned)(increase ? effectPaletteIndex+1 : effectPaletteIndex-1), strip.getPaletteCount()+strip.customPalettes.size()-1), 0U);
|
effectPaletteIndex = max(min((increase ? effectPaletteIndex+1 : effectPaletteIndex-1), strip.getPaletteCount()-1), 0);
|
||||||
effectPalette = palettes_alpha_indexes[effectPaletteIndex];
|
effectPalette = palettes_alpha_indexes[effectPaletteIndex];
|
||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
if (applyToAll) {
|
if (applyToAll) {
|
||||||
|
467
wled00/FX.cpp
467
wled00/FX.cpp
File diff suppressed because it is too large
Load Diff
88
wled00/FX.h
88
wled00/FX.h
@ -176,7 +176,7 @@
|
|||||||
#define FX_MODE_FIRE_FLICKER 45
|
#define FX_MODE_FIRE_FLICKER 45
|
||||||
#define FX_MODE_GRADIENT 46
|
#define FX_MODE_GRADIENT 46
|
||||||
#define FX_MODE_LOADING 47
|
#define FX_MODE_LOADING 47
|
||||||
#define FX_MODE_ROLLINGBALLS 48 //was Police before 0.14
|
// #define FX_MODE_POLICE 48 // removed in 0.14!
|
||||||
#define FX_MODE_FAIRY 49 //was Police All prior to 0.13.0-b6 (use "Two Dots" with Red/Blue and full intensity)
|
#define FX_MODE_FAIRY 49 //was Police All prior to 0.13.0-b6 (use "Two Dots" with Red/Blue and full intensity)
|
||||||
#define FX_MODE_TWO_DOTS 50
|
#define FX_MODE_TWO_DOTS 50
|
||||||
#define FX_MODE_FAIRYTWINKLE 51 //was Two Areas prior to 0.13.0-b6 (use "Two Dots" with full intensity)
|
#define FX_MODE_FAIRYTWINKLE 51 //was Two Areas prior to 0.13.0-b6 (use "Two Dots" with full intensity)
|
||||||
@ -381,30 +381,6 @@ typedef struct Segment {
|
|||||||
byte *data; // effect data pointer
|
byte *data; // effect data pointer
|
||||||
static uint16_t maxWidth, maxHeight; // these define matrix width & height (max. segment dimensions)
|
static uint16_t maxWidth, maxHeight; // these define matrix width & height (max. segment dimensions)
|
||||||
|
|
||||||
typedef struct TemporarySegmentData {
|
|
||||||
uint16_t _optionsT;
|
|
||||||
uint32_t _colorT[NUM_COLORS];
|
|
||||||
uint8_t _speedT;
|
|
||||||
uint8_t _intensityT;
|
|
||||||
uint8_t _custom1T, _custom2T; // custom FX parameters/sliders
|
|
||||||
struct {
|
|
||||||
uint8_t _custom3T : 5; // reduced range slider (0-31)
|
|
||||||
bool _check1T : 1; // checkmark 1
|
|
||||||
bool _check2T : 1; // checkmark 2
|
|
||||||
bool _check3T : 1; // checkmark 3
|
|
||||||
};
|
|
||||||
uint16_t _aux0T;
|
|
||||||
uint16_t _aux1T;
|
|
||||||
uint32_t _stepT;
|
|
||||||
uint32_t _callT;
|
|
||||||
uint8_t *_dataT;
|
|
||||||
uint16_t _dataLenT;
|
|
||||||
TemporarySegmentData()
|
|
||||||
: _dataT(nullptr) // just in case...
|
|
||||||
, _dataLenT(0)
|
|
||||||
{}
|
|
||||||
} tmpsegd_t;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
union {
|
union {
|
||||||
uint8_t _capabilities;
|
uint8_t _capabilities;
|
||||||
@ -420,33 +396,43 @@ typedef struct Segment {
|
|||||||
static uint16_t _usedSegmentData;
|
static uint16_t _usedSegmentData;
|
||||||
|
|
||||||
// perhaps this should be per segment, not static
|
// perhaps this should be per segment, not static
|
||||||
static CRGBPalette16 _randomPalette; // actual random palette
|
static CRGBPalette16 _randomPalette;
|
||||||
static CRGBPalette16 _newRandomPalette; // target random palette
|
static CRGBPalette16 _newRandomPalette;
|
||||||
static unsigned long _lastPaletteChange; // last random palette change time in millis()
|
static unsigned long _lastPaletteChange;
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
|
||||||
static bool _modeBlend; // mode/effect blending semaphore
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// transition data, valid only if transitional==true, holds values during transition (72 bytes)
|
// transition data, valid only if transitional==true, holds values during transition (72 bytes)
|
||||||
struct Transition {
|
struct Transition {
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
|
||||||
tmpsegd_t _segT; // previous segment environment
|
|
||||||
uint8_t _modeT; // previous mode/effect
|
|
||||||
#else
|
|
||||||
uint32_t _colorT[NUM_COLORS];
|
uint32_t _colorT[NUM_COLORS];
|
||||||
#endif
|
|
||||||
uint8_t _briT; // temporary brightness
|
uint8_t _briT; // temporary brightness
|
||||||
uint8_t _cctT; // temporary CCT
|
uint8_t _cctT; // temporary CCT
|
||||||
CRGBPalette16 _palT; // temporary palette
|
CRGBPalette16 _palT; // temporary palette
|
||||||
uint8_t _prevPaletteBlends; // number of previous palette blends (there are max 255 belnds possible)
|
uint8_t _prevPaletteBlends; // number of previous palette blends (there are max 255 belnds possible)
|
||||||
unsigned long _start; // must accommodate millis()
|
uint8_t _modeP; // previous mode/effect
|
||||||
|
//uint16_t _aux0, _aux1; // previous mode/effect runtime data
|
||||||
|
//uint32_t _step, _call; // previous mode/effect runtime data
|
||||||
|
//byte *_data; // previous mode/effect runtime data
|
||||||
|
unsigned long _start; // must accommodate millis()
|
||||||
uint16_t _dur;
|
uint16_t _dur;
|
||||||
Transition(uint16_t dur=750)
|
Transition(uint16_t dur=750)
|
||||||
: _palT(CRGBPalette16(CRGB::Black))
|
: _briT(255)
|
||||||
|
, _cctT(127)
|
||||||
|
, _palT(CRGBPalette16(CRGB::Black))
|
||||||
, _prevPaletteBlends(0)
|
, _prevPaletteBlends(0)
|
||||||
|
, _modeP(FX_MODE_STATIC)
|
||||||
, _start(millis())
|
, _start(millis())
|
||||||
, _dur(dur)
|
, _dur(dur)
|
||||||
{}
|
{}
|
||||||
|
Transition(uint16_t d, uint8_t b, uint8_t c, const uint32_t *o)
|
||||||
|
: _briT(b)
|
||||||
|
, _cctT(c)
|
||||||
|
, _palT(CRGBPalette16(CRGB::Black))
|
||||||
|
, _prevPaletteBlends(0)
|
||||||
|
, _modeP(FX_MODE_STATIC)
|
||||||
|
, _start(millis())
|
||||||
|
, _dur(d)
|
||||||
|
{
|
||||||
|
for (size_t i=0; i<NUM_COLORS; i++) _colorT[i] = o[i];
|
||||||
|
}
|
||||||
} *_t;
|
} *_t;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -485,9 +471,6 @@ typedef struct Segment {
|
|||||||
_t(nullptr)
|
_t(nullptr)
|
||||||
{
|
{
|
||||||
//refreshLightCapabilities();
|
//refreshLightCapabilities();
|
||||||
#ifdef WLED_DEBUG
|
|
||||||
//Serial.printf("-- Creating segment: %p\n", this);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Segment(uint16_t sStartX, uint16_t sStopX, uint16_t sStartY, uint16_t sStopY) : Segment(sStartX, sStopX) {
|
Segment(uint16_t sStartX, uint16_t sStopX, uint16_t sStartY, uint16_t sStopY) : Segment(sStartX, sStopX) {
|
||||||
@ -499,14 +482,14 @@ typedef struct Segment {
|
|||||||
Segment(Segment &&orig) noexcept; // move constructor
|
Segment(Segment &&orig) noexcept; // move constructor
|
||||||
|
|
||||||
~Segment() {
|
~Segment() {
|
||||||
#ifdef WLED_DEBUG
|
//#ifdef WLED_DEBUG
|
||||||
//Serial.printf("-- Destroying segment: %p\n", this);
|
//Serial.print(F("Destroying segment:"));
|
||||||
//if (name) Serial.printf(" %s (%p)", name, name);
|
//if (name) Serial.printf(" %s (%p)", name, name);
|
||||||
//if (data) Serial.printf(" %d (%p)", (int)_dataLen, data);
|
//if (data) Serial.printf(" %d (%p)", (int)_dataLen, data);
|
||||||
//Serial.println();
|
//Serial.println();
|
||||||
#endif
|
//#endif
|
||||||
if (name) { delete[] name; name = nullptr; }
|
if (name) { delete[] name; name = nullptr; }
|
||||||
stopTransition();
|
if (_t) { transitional = false; delete _t; _t = nullptr; }
|
||||||
deallocateData();
|
deallocateData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,9 +515,6 @@ typedef struct Segment {
|
|||||||
|
|
||||||
static uint16_t getUsedSegmentData(void) { return _usedSegmentData; }
|
static uint16_t getUsedSegmentData(void) { return _usedSegmentData; }
|
||||||
static void addUsedSegmentData(int len) { _usedSegmentData += len; }
|
static void addUsedSegmentData(int len) { _usedSegmentData += len; }
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
|
||||||
static void modeBlend(bool blend) { _modeBlend = blend; }
|
|
||||||
#endif
|
|
||||||
static void handleRandomPalette();
|
static void handleRandomPalette();
|
||||||
|
|
||||||
void setUp(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1, uint8_t segId = 255);
|
void setUp(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1, uint8_t segId = 255);
|
||||||
@ -562,12 +542,7 @@ typedef struct Segment {
|
|||||||
|
|
||||||
// transition functions
|
// transition functions
|
||||||
void startTransition(uint16_t dur); // transition has to start before actual segment values change
|
void startTransition(uint16_t dur); // transition has to start before actual segment values change
|
||||||
void stopTransition(void);
|
|
||||||
void handleTransition(void);
|
void handleTransition(void);
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
|
||||||
void swapSegenv(tmpsegd_t &tmpSegD);
|
|
||||||
void restoreSegenv(tmpsegd_t &tmpSegD);
|
|
||||||
#endif
|
|
||||||
uint16_t progress(void); //transition progression between 0-65535
|
uint16_t progress(void); //transition progression between 0-65535
|
||||||
uint8_t currentBri(uint8_t briNew, bool useCct = false);
|
uint8_t currentBri(uint8_t briNew, bool useCct = false);
|
||||||
uint8_t currentMode(uint8_t modeNew);
|
uint8_t currentMode(uint8_t modeNew);
|
||||||
@ -629,9 +604,9 @@ typedef struct Segment {
|
|||||||
void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c);
|
void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c);
|
||||||
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c);
|
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c);
|
||||||
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0)); } // automatic inline
|
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0)); } // automatic inline
|
||||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, int8_t rotate = 0);
|
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0);
|
||||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0)); } // automatic inline
|
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0)); } // automatic inline
|
||||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2, int8_t rotate = 0) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0), rotate); } // automatic inline
|
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0)); } // automatic inline
|
||||||
void wu_pixel(uint32_t x, uint32_t y, CRGB c);
|
void wu_pixel(uint32_t x, uint32_t y, CRGB c);
|
||||||
void blur1d(fract8 blur_amount); // blur all rows in 1 dimension
|
void blur1d(fract8 blur_amount); // blur all rows in 1 dimension
|
||||||
void blur2d(fract8 blur_amount) { blur(blur_amount); }
|
void blur2d(fract8 blur_amount) { blur(blur_amount); }
|
||||||
@ -661,9 +636,8 @@ typedef struct Segment {
|
|||||||
void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c) {}
|
void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c) {}
|
||||||
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) {}
|
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) {}
|
||||||
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) {}
|
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) {}
|
||||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t = 0, int8_t = 0) {}
|
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color) {}
|
||||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB color) {}
|
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB color) {}
|
||||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2, int8_t rotate = 0) {}
|
|
||||||
void wu_pixel(uint32_t x, uint32_t y, CRGB c) {}
|
void wu_pixel(uint32_t x, uint32_t y, CRGB c) {}
|
||||||
#endif
|
#endif
|
||||||
} segment;
|
} segment;
|
||||||
|
@ -216,29 +216,23 @@ void /*IRAM_ATTR*/ Segment::setPixelColorXY(int x, int y, uint32_t col)
|
|||||||
y *= groupLength(); // expand to physical pixels
|
y *= groupLength(); // expand to physical pixels
|
||||||
if (x >= width() || y >= height()) return; // if pixel would fall out of segment just exit
|
if (x >= width() || y >= height()) return; // if pixel would fall out of segment just exit
|
||||||
|
|
||||||
uint32_t tmpCol = col;
|
|
||||||
for (int j = 0; j < grouping; j++) { // groupping vertically
|
for (int j = 0; j < grouping; j++) { // groupping vertically
|
||||||
for (int g = 0; g < grouping; g++) { // groupping horizontally
|
for (int g = 0; g < grouping; g++) { // groupping horizontally
|
||||||
uint16_t xX = (x+g), yY = (y+j);
|
uint16_t xX = (x+g), yY = (y+j);
|
||||||
if (xX >= width() || yY >= height()) continue; // we have reached one dimension's end
|
if (xX >= width() || yY >= height()) continue; // we have reached one dimension's end
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
strip.setPixelColorXY(start + xX, startY + yY, col);
|
||||||
// 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);
|
|
||||||
|
|
||||||
if (mirror) { //set the corresponding horizontally mirrored pixel
|
if (mirror) { //set the corresponding horizontally mirrored pixel
|
||||||
if (transpose) strip.setPixelColorXY(start + xX, startY + height() - yY - 1, tmpCol);
|
if (transpose) strip.setPixelColorXY(start + xX, startY + height() - yY - 1, col);
|
||||||
else strip.setPixelColorXY(start + width() - xX - 1, startY + yY, tmpCol);
|
else strip.setPixelColorXY(start + width() - xX - 1, startY + yY, col);
|
||||||
}
|
}
|
||||||
if (mirror_y) { //set the corresponding vertically mirrored pixel
|
if (mirror_y) { //set the corresponding vertically mirrored pixel
|
||||||
if (transpose) strip.setPixelColorXY(start + width() - xX - 1, startY + yY, tmpCol);
|
if (transpose) strip.setPixelColorXY(start + width() - xX - 1, startY + yY, col);
|
||||||
else strip.setPixelColorXY(start + xX, startY + height() - yY - 1, tmpCol);
|
else strip.setPixelColorXY(start + xX, startY + height() - yY - 1, col);
|
||||||
}
|
}
|
||||||
if (mirror_y && mirror) { //set the corresponding vertically AND horizontally mirrored pixel
|
if (mirror_y && mirror) { //set the corresponding vertically AND horizontally mirrored pixel
|
||||||
strip.setPixelColorXY(width() - xX - 1, height() - yY - 1, tmpCol);
|
strip.setPixelColorXY(width() - xX - 1, height() - yY - 1, col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -571,7 +565,7 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
|||||||
|
|
||||||
// draws a raster font character on canvas
|
// draws a raster font character on canvas
|
||||||
// only supports: 4x6=24, 5x8=40, 5x12=60, 6x8=48 and 7x9=63 fonts ATM
|
// only supports: 4x6=24, 5x8=40, 5x12=60, 6x8=48 and 7x9=63 fonts ATM
|
||||||
void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, int8_t rotate) {
|
void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
if (chr < 32 || chr > 126) return; // only ASCII 32-126 supported
|
if (chr < 32 || chr > 126) return; // only ASCII 32-126 supported
|
||||||
chr -= 32; // align with font table entries
|
chr -= 32; // align with font table entries
|
||||||
@ -584,6 +578,9 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w,
|
|||||||
|
|
||||||
//if (w<5 || w>6 || h!=8) return;
|
//if (w<5 || w>6 || h!=8) return;
|
||||||
for (int i = 0; i<h; i++) { // character height
|
for (int i = 0; i<h; i++) { // character height
|
||||||
|
int16_t y0 = y + i;
|
||||||
|
if (y0 < 0) continue; // drawing off-screen
|
||||||
|
if (y0 >= rows) break; // drawing off-screen
|
||||||
uint8_t bits = 0;
|
uint8_t bits = 0;
|
||||||
switch (font) {
|
switch (font) {
|
||||||
case 24: bits = pgm_read_byte_near(&console_font_4x6[(chr * h) + i]); break; // 5x8 font
|
case 24: bits = pgm_read_byte_near(&console_font_4x6[(chr * h) + i]); break; // 5x8 font
|
||||||
@ -595,16 +592,8 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w,
|
|||||||
}
|
}
|
||||||
col = ColorFromPalette(grad, (i+1)*255/h, 255, NOBLEND);
|
col = ColorFromPalette(grad, (i+1)*255/h, 255, NOBLEND);
|
||||||
for (int j = 0; j<w; j++) { // character width
|
for (int j = 0; j<w; j++) { // character width
|
||||||
int x0, y0;
|
int16_t x0 = x + (w-1) - j;
|
||||||
switch (rotate) {
|
if ((x0 >= 0 || x0 < cols) && ((bits>>(j+(8-w))) & 0x01)) { // bit set & drawing on-screen
|
||||||
case -1: x0 = x + (h-1) - i; y0 = y + (w-1) - j; break; // -90 deg
|
|
||||||
case -2:
|
|
||||||
case 2: x0 = x + j; y0 = y + (h-1) - i; break; // 180 deg
|
|
||||||
case 1: x0 = x + i; y0 = y + j; break; // +90 deg
|
|
||||||
default: x0 = x + (w-1) - j; y0 = y + i; break; // no rotation
|
|
||||||
}
|
|
||||||
if (x0 < 0 || x0 >= cols || y0 < 0 || y0 >= rows) continue; // drawing off-screen
|
|
||||||
if (((bits>>(j+(8-w))) & 0x01)) { // bit set
|
|
||||||
setPixelColorXY(x0, y0, col);
|
setPixelColorXY(x0, y0, col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,13 +81,9 @@ CRGBPalette16 Segment::_randomPalette = CRGBPalette16(DEFAULT_COLOR);
|
|||||||
CRGBPalette16 Segment::_newRandomPalette = CRGBPalette16(DEFAULT_COLOR);
|
CRGBPalette16 Segment::_newRandomPalette = CRGBPalette16(DEFAULT_COLOR);
|
||||||
unsigned long Segment::_lastPaletteChange = 0; // perhaps it should be per segment
|
unsigned long Segment::_lastPaletteChange = 0; // perhaps it should be per segment
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
|
||||||
bool Segment::_modeBlend = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// copy constructor
|
// copy constructor
|
||||||
Segment::Segment(const Segment &orig) {
|
Segment::Segment(const Segment &orig) {
|
||||||
//DEBUG_PRINTF("-- Copy segment constructor: %p -> %p\n", &orig, this);
|
//DEBUG_PRINTLN(F("-- Copy segment constructor --"));
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
transitional = false; // copied segment cannot be in transition
|
transitional = false; // copied segment cannot be in transition
|
||||||
name = nullptr;
|
name = nullptr;
|
||||||
@ -96,12 +92,12 @@ Segment::Segment(const Segment &orig) {
|
|||||||
_t = nullptr;
|
_t = nullptr;
|
||||||
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
||||||
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
||||||
//if (orig._t) { _t = new Transition(orig._t->_dur); }
|
//if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// move constructor
|
// move constructor
|
||||||
Segment::Segment(Segment &&orig) noexcept {
|
Segment::Segment(Segment &&orig) noexcept {
|
||||||
//DEBUG_PRINTF("-- Move segment constructor: %p -> %p\n", &orig, this);
|
//DEBUG_PRINTLN(F("-- Move segment constructor --"));
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
orig.transitional = false; // old segment cannot be in transition any more
|
orig.transitional = false; // old segment cannot be in transition any more
|
||||||
orig.name = nullptr;
|
orig.name = nullptr;
|
||||||
@ -112,17 +108,12 @@ Segment::Segment(Segment &&orig) noexcept {
|
|||||||
|
|
||||||
// copy assignment
|
// copy assignment
|
||||||
Segment& Segment::operator= (const Segment &orig) {
|
Segment& Segment::operator= (const Segment &orig) {
|
||||||
//DEBUG_PRINTF("-- Copying segment: %p -> %p\n", &orig, this);
|
//DEBUG_PRINTLN(F("-- Copying segment --"));
|
||||||
if (this != &orig) {
|
if (this != &orig) {
|
||||||
// clean destination
|
// clean destination
|
||||||
transitional = false; // copied segment cannot be in transition
|
transitional = false; // copied segment cannot be in transition
|
||||||
if (name) delete[] name;
|
if (name) delete[] name;
|
||||||
if (_t) {
|
if (_t) delete _t;
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
|
||||||
if (_t->_segT._dataT) free(_t->_segT._dataT);
|
|
||||||
#endif
|
|
||||||
delete _t;
|
|
||||||
}
|
|
||||||
deallocateData();
|
deallocateData();
|
||||||
// copy source
|
// copy source
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
@ -142,18 +133,12 @@ Segment& Segment::operator= (const Segment &orig) {
|
|||||||
|
|
||||||
// move assignment
|
// move assignment
|
||||||
Segment& Segment::operator= (Segment &&orig) noexcept {
|
Segment& Segment::operator= (Segment &&orig) noexcept {
|
||||||
//DEBUG_PRINTF("-- Moving segment: %p -> %p\n", &orig, this);
|
//DEBUG_PRINTLN(F("-- Moving segment --"));
|
||||||
if (this != &orig) {
|
if (this != &orig) {
|
||||||
transitional = false; // just temporary
|
transitional = false; // just temporary
|
||||||
if (name) { delete[] name; name = nullptr; } // free old name
|
if (name) { delete[] name; name = nullptr; } // free old name
|
||||||
deallocateData(); // free old runtime data
|
deallocateData(); // free old runtime data
|
||||||
if (_t) {
|
if (_t) { delete _t; _t = nullptr; }
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
|
||||||
if (_t->_segT._dataT) free(_t->_segT._dataT);
|
|
||||||
#endif
|
|
||||||
delete _t;
|
|
||||||
_t = nullptr;
|
|
||||||
}
|
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
orig.transitional = false; // old segment cannot be in transition
|
orig.transitional = false; // old segment cannot be in transition
|
||||||
orig.name = nullptr;
|
orig.name = nullptr;
|
||||||
@ -166,39 +151,22 @@ Segment& Segment::operator= (Segment &&orig) noexcept {
|
|||||||
|
|
||||||
bool Segment::allocateData(size_t len) {
|
bool Segment::allocateData(size_t len) {
|
||||||
if (data && _dataLen == len) return true; //already allocated
|
if (data && _dataLen == len) return true; //already allocated
|
||||||
//DEBUG_PRINTF("-- Allocating data (%d): %p\n", len, this);
|
|
||||||
deallocateData();
|
deallocateData();
|
||||||
if (len == 0) return(false); // nothing to do
|
if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) return false; //not enough memory
|
||||||
if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) {
|
|
||||||
// not enough memory
|
|
||||||
DEBUG_PRINT(F("!!! Effect RAM depleted: "));
|
|
||||||
DEBUG_PRINTF("%d/%d !!!\n", len, Segment::getUsedSegmentData());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// do not use SPI RAM on ESP32 since it is slow
|
// do not use SPI RAM on ESP32 since it is slow
|
||||||
data = (byte*) malloc(len);
|
data = (byte*) malloc(len);
|
||||||
if (!data) { DEBUG_PRINTLN(F("!!! Allocation failed. !!!")); return false; } //allocation failed
|
if (!data) return false; //allocation failed
|
||||||
Segment::addUsedSegmentData(len);
|
Segment::addUsedSegmentData(len);
|
||||||
//DEBUG_PRINTF("--- Allocated data (%p): %d/%d -> %p\n", this, len, Segment::getUsedSegmentData(), data);
|
|
||||||
_dataLen = len;
|
_dataLen = len;
|
||||||
memset(data, 0, len);
|
memset(data, 0, len);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Segment::deallocateData() {
|
void Segment::deallocateData() {
|
||||||
if (!data) { _dataLen = 0; return; }
|
if (!data) return;
|
||||||
//DEBUG_PRINTF("--- Released data (%p): %d/%d -> %p\n", this, _dataLen, Segment::getUsedSegmentData(), data);
|
free(data);
|
||||||
if ((Segment::getUsedSegmentData() > 0) && (_dataLen > 0)) { // check that we don't have a dangling / inconsistent data pointer
|
|
||||||
free(data);
|
|
||||||
} else {
|
|
||||||
DEBUG_PRINT(F("---- Released data "));
|
|
||||||
DEBUG_PRINTF("(%p): ", this);
|
|
||||||
DEBUG_PRINT(F("inconsistent UsedSegmentData "));
|
|
||||||
DEBUG_PRINTF("(%d/%d)", _dataLen, Segment::getUsedSegmentData());
|
|
||||||
DEBUG_PRINTLN(F(", cowardly refusing to free nothing."));
|
|
||||||
}
|
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
Segment::addUsedSegmentData(_dataLen <= Segment::getUsedSegmentData() ? -_dataLen : -Segment::getUsedSegmentData());
|
Segment::addUsedSegmentData(-_dataLen);
|
||||||
_dataLen = 0;
|
_dataLen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +179,7 @@ void Segment::deallocateData() {
|
|||||||
*/
|
*/
|
||||||
void Segment::resetIfRequired() {
|
void Segment::resetIfRequired() {
|
||||||
if (!reset) return;
|
if (!reset) return;
|
||||||
//DEBUG_PRINTF("-- Segment reset: %p\n", this);
|
|
||||||
deallocateData();
|
deallocateData();
|
||||||
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
||||||
reset = false;
|
reset = false;
|
||||||
@ -247,7 +215,7 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
|||||||
CHSV(random8(), random8(160, 255), random8(128, 255)),
|
CHSV(random8(), random8(160, 255), random8(128, 255)),
|
||||||
CHSV(random8(), random8(160, 255), random8(128, 255)));
|
CHSV(random8(), random8(160, 255), random8(128, 255)));
|
||||||
_lastPaletteChange = millis();
|
_lastPaletteChange = millis();
|
||||||
handleRandomPalette(); // do a 1st pass of blend
|
handleRandomPalette(); // do initial blend
|
||||||
}
|
}
|
||||||
targetPalette = _randomPalette;
|
targetPalette = _randomPalette;
|
||||||
break;}
|
break;}
|
||||||
@ -302,8 +270,11 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
|||||||
|
|
||||||
void Segment::startTransition(uint16_t dur) {
|
void Segment::startTransition(uint16_t dur) {
|
||||||
if (!dur) {
|
if (!dur) {
|
||||||
if (_t) _t->_dur = dur; // this will stop transition in next handleTransisiton()
|
transitional = false;
|
||||||
else transitional = false;
|
if (_t) {
|
||||||
|
delete _t;
|
||||||
|
_t = nullptr;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (transitional && _t) return; // already in transition no need to store anything
|
if (transitional && _t) return; // already in transition no need to store anything
|
||||||
@ -312,165 +283,44 @@ void Segment::startTransition(uint16_t dur) {
|
|||||||
_t = new Transition(dur); // no previous transition running
|
_t = new Transition(dur); // no previous transition running
|
||||||
if (!_t) return; // failed to allocate data
|
if (!_t) return; // failed to allocate data
|
||||||
|
|
||||||
//DEBUG_PRINTF("-- Started transition: %p\n", this);
|
|
||||||
CRGBPalette16 _palT = CRGBPalette16(DEFAULT_COLOR); loadPalette(_palT, palette);
|
CRGBPalette16 _palT = CRGBPalette16(DEFAULT_COLOR); loadPalette(_palT, palette);
|
||||||
_t->_palT = _palT;
|
_t->_briT = on ? opacity : 0;
|
||||||
_t->_briT = on ? opacity : 0;
|
_t->_cctT = cct;
|
||||||
_t->_cctT = cct;
|
_t->_palT = _palT;
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
_t->_modeP = mode;
|
||||||
swapSegenv(_t->_segT);
|
|
||||||
_t->_modeT = mode;
|
|
||||||
_t->_segT._optionsT |= 0b0000000001000000; // mark old segment transitional
|
|
||||||
_t->_segT._dataLenT = 0;
|
|
||||||
_t->_segT._dataT = nullptr;
|
|
||||||
if (_dataLen > 0 && data) {
|
|
||||||
_t->_segT._dataT = (byte *)malloc(_dataLen);
|
|
||||||
if (_t->_segT._dataT) {
|
|
||||||
//DEBUG_PRINTF("-- Allocated duplicate data (%d): %p\n", _dataLen, _t->_segT._dataT);
|
|
||||||
memcpy(_t->_segT._dataT, data, _dataLen);
|
|
||||||
_t->_segT._dataLenT = _dataLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
for (size_t i=0; i<NUM_COLORS; i++) _t->_colorT[i] = colors[i];
|
for (size_t i=0; i<NUM_COLORS; i++) _t->_colorT[i] = colors[i];
|
||||||
#endif
|
|
||||||
transitional = true; // setOption(SEG_OPTION_TRANSITIONAL, true);
|
transitional = true; // setOption(SEG_OPTION_TRANSITIONAL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Segment::stopTransition() {
|
|
||||||
if (!transitional) return;
|
|
||||||
transitional = false; // finish transitioning segment
|
|
||||||
//DEBUG_PRINTF("-- Stopping transition: %p\n", this);
|
|
||||||
if (_t) {
|
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
|
||||||
if (_t->_segT._dataT && _t->_segT._dataLenT > 0) {
|
|
||||||
//DEBUG_PRINTF("-- Released duplicate data (%d): %p\n", _t->_segT._dataLenT, _t->_segT._dataT);
|
|
||||||
free(_t->_segT._dataT);
|
|
||||||
_t->_segT._dataT = nullptr;
|
|
||||||
_t->_segT._dataLenT = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
delete _t;
|
|
||||||
_t = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Segment::handleTransition() {
|
|
||||||
if (!transitional) return;
|
|
||||||
uint16_t _progress = progress();
|
|
||||||
if (_progress == 0xFFFFU) stopTransition();
|
|
||||||
}
|
|
||||||
|
|
||||||
// transition progression between 0-65535
|
// transition progression between 0-65535
|
||||||
uint16_t Segment::progress() {
|
uint16_t Segment::progress() {
|
||||||
if (transitional && _t) {
|
if (!transitional || !_t) return 0xFFFFU;
|
||||||
unsigned long timeNow = millis();
|
unsigned long timeNow = millis();
|
||||||
if (_t->_dur > 0 && timeNow - _t->_start < _t->_dur) return (timeNow - _t->_start) * 0xFFFFU / _t->_dur;
|
if (timeNow - _t->_start > _t->_dur || _t->_dur == 0) return 0xFFFFU;
|
||||||
}
|
return (timeNow - _t->_start) * 0xFFFFU / _t->_dur;
|
||||||
return 0xFFFFU;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
|
||||||
void Segment::swapSegenv(tmpsegd_t &tmpSeg) {
|
|
||||||
//DEBUG_PRINTF("-- Saving temp seg: %p (%p)\n", this, tmpSeg);
|
|
||||||
tmpSeg._optionsT = options;
|
|
||||||
for (size_t i=0; i<NUM_COLORS; i++) tmpSeg._colorT[i] = colors[i];
|
|
||||||
tmpSeg._speedT = speed;
|
|
||||||
tmpSeg._intensityT = intensity;
|
|
||||||
tmpSeg._custom1T = custom1;
|
|
||||||
tmpSeg._custom2T = custom2;
|
|
||||||
tmpSeg._custom3T = custom3;
|
|
||||||
tmpSeg._check1T = check1;
|
|
||||||
tmpSeg._check2T = check2;
|
|
||||||
tmpSeg._check3T = check3;
|
|
||||||
tmpSeg._aux0T = aux0;
|
|
||||||
tmpSeg._aux1T = aux1;
|
|
||||||
tmpSeg._stepT = step;
|
|
||||||
tmpSeg._callT = call;
|
|
||||||
tmpSeg._dataT = data;
|
|
||||||
tmpSeg._dataLenT = _dataLen;
|
|
||||||
if (_t && &tmpSeg != &(_t->_segT)) {
|
|
||||||
// swap SEGENV with transitional data
|
|
||||||
options = _t->_segT._optionsT;
|
|
||||||
for (size_t i=0; i<NUM_COLORS; i++) colors[i] = _t->_segT._colorT[i];
|
|
||||||
speed = _t->_segT._speedT;
|
|
||||||
intensity = _t->_segT._intensityT;
|
|
||||||
custom1 = _t->_segT._custom1T;
|
|
||||||
custom2 = _t->_segT._custom2T;
|
|
||||||
custom3 = _t->_segT._custom3T;
|
|
||||||
check1 = _t->_segT._check1T;
|
|
||||||
check2 = _t->_segT._check2T;
|
|
||||||
check3 = _t->_segT._check3T;
|
|
||||||
aux0 = _t->_segT._aux0T;
|
|
||||||
aux1 = _t->_segT._aux1T;
|
|
||||||
step = _t->_segT._stepT;
|
|
||||||
call = _t->_segT._callT;
|
|
||||||
data = _t->_segT._dataT;
|
|
||||||
_dataLen = _t->_segT._dataLenT;
|
|
||||||
}
|
|
||||||
//DEBUG_PRINTF("-- temp seg data: %p (%d,%p)\n", this, _dataLen, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Segment::restoreSegenv(tmpsegd_t &tmpSeg) {
|
|
||||||
//DEBUG_PRINTF("-- Restoring temp seg: %p (%p)\n", this, tmpSeg);
|
|
||||||
if (_t && &(_t->_segT) != &tmpSeg) {
|
|
||||||
// update possibly changed variables to keep old effect running correctly
|
|
||||||
_t->_segT._aux0T = aux0;
|
|
||||||
_t->_segT._aux1T = aux1;
|
|
||||||
_t->_segT._stepT = step;
|
|
||||||
_t->_segT._callT = call;
|
|
||||||
//if (_t->_segT._dataT != data) DEBUG_PRINTF("--- data re-allocated: (%p) %p -> %p\n", this, _t->_segT._dataT, data);
|
|
||||||
_t->_segT._dataT = data; // sometimes memory gets re-allocated (!! INVESTIGATE WHY !!)
|
|
||||||
_t->_segT._dataLenT = _dataLen; // sometimes memory gets re-allocated (!! INVESTIGATE WHY !!)
|
|
||||||
}
|
|
||||||
options = tmpSeg._optionsT;
|
|
||||||
for (size_t i=0; i<NUM_COLORS; i++) colors[i] = tmpSeg._colorT[i];
|
|
||||||
speed = tmpSeg._speedT;
|
|
||||||
intensity = tmpSeg._intensityT;
|
|
||||||
custom1 = tmpSeg._custom1T;
|
|
||||||
custom2 = tmpSeg._custom2T;
|
|
||||||
custom3 = tmpSeg._custom3T;
|
|
||||||
check1 = tmpSeg._check1T;
|
|
||||||
check2 = tmpSeg._check2T;
|
|
||||||
check3 = tmpSeg._check3T;
|
|
||||||
aux0 = tmpSeg._aux0T;
|
|
||||||
aux1 = tmpSeg._aux1T;
|
|
||||||
step = tmpSeg._stepT;
|
|
||||||
call = tmpSeg._callT;
|
|
||||||
data = tmpSeg._dataT;
|
|
||||||
_dataLen = tmpSeg._dataLenT;
|
|
||||||
//DEBUG_PRINTF("-- temp seg data: %p (%d,%p)\n", this, _dataLen, data);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t Segment::currentBri(uint8_t briNew, bool useCct) {
|
uint8_t Segment::currentBri(uint8_t briNew, bool useCct) {
|
||||||
uint32_t prog = progress();
|
uint32_t prog = progress();
|
||||||
if (prog < 0xFFFFU) {
|
if (transitional && _t && prog < 0xFFFFU) {
|
||||||
if (useCct) return ((briNew * prog) + _t->_cctT * (0xFFFFU - prog)) >> 16;
|
if (useCct) return ((briNew * prog) + _t->_cctT * (0xFFFFU - prog)) >> 16;
|
||||||
else return ((briNew * prog) + _t->_briT * (0xFFFFU - prog)) >> 16;
|
else return ((briNew * prog) + _t->_briT * (0xFFFFU - prog)) >> 16;
|
||||||
|
} else {
|
||||||
|
return briNew;
|
||||||
}
|
}
|
||||||
return briNew;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Segment::currentMode(uint8_t newMode) {
|
uint8_t Segment::currentMode(uint8_t newMode) {
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
return (progress()>32767U) ? newMode : _t->_modeP; // change effect in the middle of transition
|
||||||
uint16_t prog = progress(); // implicit check for transitional & _t in progress()
|
|
||||||
if (prog < 0xFFFFU) return _t->_modeT;
|
|
||||||
#endif
|
|
||||||
return newMode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Segment::currentColor(uint8_t slot, uint32_t colorNew) {
|
uint32_t Segment::currentColor(uint8_t slot, uint32_t colorNew) {
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
|
||||||
return transitional && _t ? color_blend(_t->_segT._colorT[slot], colorNew, progress(), true) : colorNew;
|
|
||||||
#else
|
|
||||||
return transitional && _t ? color_blend(_t->_colorT[slot], colorNew, progress(), true) : colorNew;
|
return transitional && _t ? color_blend(_t->_colorT[slot], colorNew, progress(), true) : colorNew;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CRGBPalette16 &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
CRGBPalette16 &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||||
loadPalette(targetPalette, pal);
|
loadPalette(targetPalette, pal);
|
||||||
if (progress() < 0xFFFFU) {
|
if (transitional && _t && progress() < 0xFFFFU) {
|
||||||
// blend palettes
|
// blend palettes
|
||||||
// there are about 255 blend passes of 48 "blends" to completely blend two palettes (in _dur time)
|
// there are about 255 blend passes of 48 "blends" to completely blend two palettes (in _dur time)
|
||||||
// minimum blend time is 100ms maximum is 65535ms
|
// minimum blend time is 100ms maximum is 65535ms
|
||||||
@ -482,6 +332,18 @@ CRGBPalette16 &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal
|
|||||||
return targetPalette;
|
return targetPalette;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Segment::handleTransition() {
|
||||||
|
if (!transitional) return;
|
||||||
|
uint16_t _progress = progress();
|
||||||
|
if (_progress == 0xFFFFU) transitional = false; // finish transitioning segment
|
||||||
|
if (_t) { // thanks to @nXm AKA https://github.com/NMeirer
|
||||||
|
if (_progress == 0xFFFFU) {
|
||||||
|
delete _t;
|
||||||
|
_t = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// relies on WS2812FX::service() to call it max every 8ms or more (MIN_SHOW_DELAY)
|
// relies on WS2812FX::service() to call it max every 8ms or more (MIN_SHOW_DELAY)
|
||||||
void Segment::handleRandomPalette() {
|
void Segment::handleRandomPalette() {
|
||||||
// just do a blend; if the palettes are identical it will just compare 48 bytes (same as _randomPalette == _newRandomPalette)
|
// just do a blend; if the palettes are identical it will just compare 48 bytes (same as _randomPalette == _newRandomPalette)
|
||||||
@ -564,7 +426,6 @@ void Segment::setCCT(uint16_t k) {
|
|||||||
void Segment::setOpacity(uint8_t o) {
|
void Segment::setOpacity(uint8_t o) {
|
||||||
if (opacity == o) return;
|
if (opacity == o) return;
|
||||||
if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change
|
if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change
|
||||||
DEBUG_PRINT(F("-- Setting opacity: ")); DEBUG_PRINTLN(o);
|
|
||||||
opacity = o;
|
opacity = o;
|
||||||
stateChanged = true; // send UDP/WS broadcast
|
stateChanged = true; // send UDP/WS broadcast
|
||||||
}
|
}
|
||||||
@ -583,6 +444,7 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
|
|||||||
if (fx != mode) {
|
if (fx != mode) {
|
||||||
if (fadeTransition) startTransition(strip.getTransition()); // set effect transitions
|
if (fadeTransition) startTransition(strip.getTransition()); // set effect transitions
|
||||||
mode = fx;
|
mode = fx;
|
||||||
|
|
||||||
// load default values from effect string
|
// load default values from effect string
|
||||||
if (loadDefaults) {
|
if (loadDefaults) {
|
||||||
int16_t sOpt;
|
int16_t sOpt;
|
||||||
@ -763,7 +625,6 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
|||||||
}
|
}
|
||||||
i += start; // starting pixel in a group
|
i += start; // starting pixel in a group
|
||||||
|
|
||||||
uint32_t tmpCol = col;
|
|
||||||
// set all the pixels in the group
|
// set all the pixels in the group
|
||||||
for (int j = 0; j < grouping; j++) {
|
for (int j = 0; j < grouping; j++) {
|
||||||
uint16_t indexSet = i + ((reverse) ? -j : j);
|
uint16_t indexSet = i + ((reverse) ? -j : j);
|
||||||
@ -772,17 +633,11 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
|||||||
uint16_t indexMir = stop - indexSet + start - 1;
|
uint16_t indexMir = stop - indexSet + start - 1;
|
||||||
indexMir += offset; // offset/phase
|
indexMir += offset; // offset/phase
|
||||||
if (indexMir >= stop) indexMir -= len; // wrap
|
if (indexMir >= stop) indexMir -= len; // wrap
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
strip.setPixelColor(indexMir, col);
|
||||||
if (_modeBlend) tmpCol = color_blend(strip.getPixelColor(indexMir), col, 0xFFFFU - progress(), true);
|
|
||||||
#endif
|
|
||||||
strip.setPixelColor(indexMir, tmpCol);
|
|
||||||
}
|
}
|
||||||
indexSet += offset; // offset/phase
|
indexSet += offset; // offset/phase
|
||||||
if (indexSet >= stop) indexSet -= len; // wrap
|
if (indexSet >= stop) indexSet -= len; // wrap
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
strip.setPixelColor(indexSet, col);
|
||||||
if (_modeBlend) tmpCol = color_blend(strip.getPixelColor(indexSet), col, 0xFFFFU - progress(), true);
|
|
||||||
#endif
|
|
||||||
strip.setPixelColor(indexSet, tmpCol);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -988,7 +843,7 @@ void Segment::fade_out(uint8_t rate) {
|
|||||||
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
||||||
|
|
||||||
rate = (255-rate) >> 1;
|
rate = (255-rate) >> 1;
|
||||||
float mappedRate = float(rate) +1.1f;
|
float mappedRate = float(rate) +1.1;
|
||||||
|
|
||||||
uint32_t color = colors[1]; // SEGCOLOR(1); // target color
|
uint32_t color = colors[1]; // SEGCOLOR(1); // target color
|
||||||
int w2 = W(color);
|
int w2 = W(color);
|
||||||
@ -1224,10 +1079,8 @@ void WS2812FX::service() {
|
|||||||
// reset the segment runtime data if needed
|
// reset the segment runtime data if needed
|
||||||
seg.resetIfRequired();
|
seg.resetIfRequired();
|
||||||
|
|
||||||
if (!seg.isActive()) continue;
|
|
||||||
|
|
||||||
// last condition ensures all solid segments are updated at the same time
|
// last condition ensures all solid segments are updated at the same time
|
||||||
if (nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC))
|
if (seg.isActive() && (nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC)))
|
||||||
{
|
{
|
||||||
doShow = true;
|
doShow = true;
|
||||||
uint16_t delay = FRAMETIME;
|
uint16_t delay = FRAMETIME;
|
||||||
@ -1242,25 +1095,10 @@ void WS2812FX::service() {
|
|||||||
if (!cctFromRgb || correctWB) busses.setSegmentCCT(seg.currentBri(seg.cct, true), correctWB);
|
if (!cctFromRgb || correctWB) busses.setSegmentCCT(seg.currentBri(seg.cct, true), correctWB);
|
||||||
for (uint8_t c = 0; c < NUM_COLORS; c++) _colors_t[c] = gamma32(_colors_t[c]);
|
for (uint8_t c = 0; c < NUM_COLORS; c++) _colors_t[c] = gamma32(_colors_t[c]);
|
||||||
|
|
||||||
// Effect blending
|
// effect blending (execute previous effect)
|
||||||
// When two effects are being blended, each may have different segment data, this
|
// actual code may be a bit more involved as effects have runtime data including allocated memory
|
||||||
// data needs to be saved first and then restored before running previous/transitional mode.
|
//if (seg.transitional && seg._modeP) (*_mode[seg._modeP])(progress());
|
||||||
// The blending will largely depend on the effect behaviour since actual output (LEDs) may be
|
delay = (*_mode[seg.currentMode(seg.mode)])();
|
||||||
// overwritten by later effect. To enable seamless blending for every effect, additional LED buffer
|
|
||||||
// would need to be allocated for each effect and then blended together for each pixel.
|
|
||||||
[[maybe_unused]] uint8_t tmpMode = seg.currentMode(seg.mode); // this will return old mode while in transition
|
|
||||||
delay = (*_mode[seg.mode])(); // run new/current mode
|
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
|
||||||
if (seg.mode != tmpMode) {
|
|
||||||
Segment::tmpsegd_t _tmpSegData;
|
|
||||||
Segment::modeBlend(true); // set semaphore
|
|
||||||
seg.swapSegenv(_tmpSegData); // temporarily store new mode state (and swap it with transitional state)
|
|
||||||
uint16_t d2 = (*_mode[tmpMode])(); // run old mode
|
|
||||||
seg.restoreSegenv(_tmpSegData); // restore mode state (will also update transitional state)
|
|
||||||
delay = MIN(delay,d2); // use shortest delay
|
|
||||||
Segment::modeBlend(false); // unset semaphore
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++;
|
if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++;
|
||||||
if (seg.transitional && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition
|
if (seg.transitional && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition
|
||||||
}
|
}
|
||||||
@ -1435,7 +1273,9 @@ void WS2812FX::setMode(uint8_t segid, uint8_t m) {
|
|||||||
if (m >= getModeCount()) m = getModeCount() - 1;
|
if (m >= getModeCount()) m = getModeCount() - 1;
|
||||||
|
|
||||||
if (_segments[segid].mode != m) {
|
if (_segments[segid].mode != m) {
|
||||||
_segments[segid].setMode(m); // do not load defaults
|
_segments[segid].startTransition(_transitionDur); // set effect transitions
|
||||||
|
_segments[segid].markForReset();
|
||||||
|
_segments[segid].mode = m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1573,7 +1413,7 @@ void WS2812FX::purgeSegments(bool force) {
|
|||||||
}
|
}
|
||||||
if (deleted) {
|
if (deleted) {
|
||||||
_segments.shrink_to_fit();
|
_segments.shrink_to_fit();
|
||||||
/*if (_mainSegment >= _segments.size())*/ setMainSegmentId(0);
|
if (_mainSegment >= _segments.size()) setMainSegmentId(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,14 +144,10 @@ void BusDigital::show() {
|
|||||||
c = RGBW32(_data[offset],_data[offset+1],_data[offset+2],(Bus::hasWhite(_type)?_data[offset+3]:0));
|
c = RGBW32(_data[offset],_data[offset+1],_data[offset+2],(Bus::hasWhite(_type)?_data[offset+3]:0));
|
||||||
}
|
}
|
||||||
uint16_t pix = i;
|
uint16_t pix = i;
|
||||||
if (_reversed) pix = _len - pix -1;
|
if (_reversed) pix = _len - pix -1;
|
||||||
pix += _skip;
|
else pix += _skip;
|
||||||
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co);
|
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co);
|
||||||
}
|
}
|
||||||
#if !defined(STATUSLED) || STATUSLED>=0
|
|
||||||
if (_skip) PolyBus::setPixelColor(_busPtr, _iType, 0, 0, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); // paint skipped pixels black
|
|
||||||
#endif
|
|
||||||
for (int i=1; i<_skip; i++) PolyBus::setPixelColor(_busPtr, _iType, i, 0, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); // paint skipped pixels black
|
|
||||||
}
|
}
|
||||||
PolyBus::show(_busPtr, _iType, !_buffering); // faster if buffer consistency is not important
|
PolyBus::show(_busPtr, _iType, !_buffering); // faster if buffer consistency is not important
|
||||||
}
|
}
|
||||||
@ -210,8 +206,8 @@ void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) {
|
|||||||
}
|
}
|
||||||
if (Bus::hasWhite(_type)) _data[offset] = W(c);
|
if (Bus::hasWhite(_type)) _data[offset] = W(c);
|
||||||
} else {
|
} else {
|
||||||
if (_reversed) pix = _len - pix -1;
|
if (_reversed) pix = _len - pix -1;
|
||||||
pix += _skip;
|
else pix += _skip;
|
||||||
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
||||||
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs
|
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs
|
||||||
uint16_t pOld = pix;
|
uint16_t pOld = pix;
|
||||||
@ -241,8 +237,8 @@ uint32_t BusDigital::getPixelColor(uint16_t pix) {
|
|||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
} else {
|
} else {
|
||||||
if (_reversed) pix = _len - pix -1;
|
if (_reversed) pix = _len - pix -1;
|
||||||
pix += _skip;
|
else pix += _skip;
|
||||||
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
||||||
uint32_t c = restoreColorLossy(PolyBus::getPixelColor(_busPtr, _iType, (_type==TYPE_WS2812_1CH_X3) ? IC_INDEX_WS2812_1CH_3X(pix) : pix, co),_bri);
|
uint32_t c = restoreColorLossy(PolyBus::getPixelColor(_busPtr, _iType, (_type==TYPE_WS2812_1CH_X3) ? IC_INDEX_WS2812_1CH_3X(pix) : pix, co),_bri);
|
||||||
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs
|
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs
|
||||||
|
@ -21,7 +21,6 @@ void shortPressAction(uint8_t b)
|
|||||||
case 1: ++effectCurrent %= strip.getModeCount(); stateChanged = true; colorUpdated(CALL_MODE_BUTTON); break;
|
case 1: ++effectCurrent %= strip.getModeCount(); stateChanged = true; colorUpdated(CALL_MODE_BUTTON); break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unloadPlaylist(); // applying a preset unloads the playlist
|
|
||||||
applyPreset(macroButton[b], CALL_MODE_BUTTON_PRESET);
|
applyPreset(macroButton[b], CALL_MODE_BUTTON_PRESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +42,6 @@ void longPressAction(uint8_t b)
|
|||||||
case 1: bri += 8; stateUpdated(CALL_MODE_BUTTON); buttonPressedTime[b] = millis(); break; // repeatable action
|
case 1: bri += 8; stateUpdated(CALL_MODE_BUTTON); buttonPressedTime[b] = millis(); break; // repeatable action
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unloadPlaylist(); // applying a preset unloads the playlist
|
|
||||||
applyPreset(macroLongPress[b], CALL_MODE_BUTTON_PRESET);
|
applyPreset(macroLongPress[b], CALL_MODE_BUTTON_PRESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +63,6 @@ void doublePressAction(uint8_t b)
|
|||||||
case 1: ++effectPalette %= strip.getPaletteCount(); colorUpdated(CALL_MODE_BUTTON); break;
|
case 1: ++effectPalette %= strip.getPaletteCount(); colorUpdated(CALL_MODE_BUTTON); break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unloadPlaylist(); // applying a preset unloads the playlist
|
|
||||||
applyPreset(macroDoublePress[b], CALL_MODE_BUTTON_PRESET);
|
applyPreset(macroDoublePress[b], CALL_MODE_BUTTON_PRESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +153,6 @@ void handleAnalog(uint8_t b)
|
|||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
rawReading = analogRead(A0) << 2; // convert 10bit read to 12bit
|
rawReading = analogRead(A0) << 2; // convert 10bit read to 12bit
|
||||||
#else
|
#else
|
||||||
if ((btnPin[b] < 0) || (digitalPinToAnalogChannel(btnPin[b]) < 0)) return; // pin must support analog ADC - newer esp32 frameworks throw lots of warnings otherwise
|
|
||||||
rawReading = analogRead(btnPin[b]); // collect at full 12bit resolution
|
rawReading = analogRead(btnPin[b]); // collect at full 12bit resolution
|
||||||
#endif
|
#endif
|
||||||
yield(); // keep WiFi task running - analog read may take several millis on ESP8266
|
yield(); // keep WiFi task running - analog read may take several millis on ESP8266
|
||||||
@ -189,7 +185,7 @@ void handleAnalog(uint8_t b)
|
|||||||
if (aRead == 0) {
|
if (aRead == 0) {
|
||||||
briLast = bri;
|
briLast = bri;
|
||||||
bri = 0;
|
bri = 0;
|
||||||
} else {
|
} else{
|
||||||
bri = aRead;
|
bri = aRead;
|
||||||
}
|
}
|
||||||
} else if (macroDoublePress[b] == 249) {
|
} else if (macroDoublePress[b] == 249) {
|
||||||
@ -266,7 +262,7 @@ void handleButton()
|
|||||||
shortPressAction(b);
|
shortPressAction(b);
|
||||||
buttonPressedBefore[b] = true;
|
buttonPressedBefore[b] = true;
|
||||||
buttonPressedTime[b] = now; // continually update (for debouncing to work in release handler)
|
buttonPressedTime[b] = now; // continually update (for debouncing to work in release handler)
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!buttonPressedBefore[b]) buttonPressedTime[b] = now;
|
if (!buttonPressedBefore[b]) buttonPressedTime[b] = now;
|
||||||
@ -287,7 +283,7 @@ void handleButton()
|
|||||||
// released after rising-edge short press action
|
// released after rising-edge short press action
|
||||||
if (macroButton[b] && macroButton[b] == macroLongPress[b] && macroButton[b] == macroDoublePress[b]) {
|
if (macroButton[b] && macroButton[b] == macroLongPress[b] && macroButton[b] == macroDoublePress[b]) {
|
||||||
if (dur > WLED_DEBOUNCE_THRESHOLD) buttonPressedBefore[b] = false; // debounce, blocks button for 50 ms once it has been released
|
if (dur > WLED_DEBOUNCE_THRESHOLD) buttonPressedBefore[b] = false; // debounce, blocks button for 50 ms once it has been released
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dur < WLED_DEBOUNCE_THRESHOLD) {buttonPressedBefore[b] = false; continue;} // too short "press", debounce
|
if (dur < WLED_DEBOUNCE_THRESHOLD) {buttonPressedBefore[b] = false; continue;} // too short "press", debounce
|
||||||
|
@ -442,14 +442,14 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
#ifdef WLED_ENABLE_MQTT
|
#ifdef WLED_ENABLE_MQTT
|
||||||
JsonObject if_mqtt = interfaces["mqtt"];
|
JsonObject if_mqtt = interfaces["mqtt"];
|
||||||
CJSON(mqttEnabled, if_mqtt["en"]);
|
CJSON(mqttEnabled, if_mqtt["en"]);
|
||||||
getStringFromJson(mqttServer, if_mqtt[F("broker")], MQTT_MAX_SERVER_LEN+1);
|
getStringFromJson(mqttServer, if_mqtt[F("broker")], 33);
|
||||||
CJSON(mqttPort, if_mqtt["port"]); // 1883
|
CJSON(mqttPort, if_mqtt["port"]); // 1883
|
||||||
getStringFromJson(mqttUser, if_mqtt[F("user")], 41);
|
getStringFromJson(mqttUser, if_mqtt[F("user")], 41);
|
||||||
getStringFromJson(mqttPass, if_mqtt["psk"], 65); //normally not present due to security
|
getStringFromJson(mqttPass, if_mqtt["psk"], 65); //normally not present due to security
|
||||||
getStringFromJson(mqttClientID, if_mqtt[F("cid")], 41);
|
getStringFromJson(mqttClientID, if_mqtt[F("cid")], 41);
|
||||||
|
|
||||||
getStringFromJson(mqttDeviceTopic, if_mqtt[F("topics")][F("device")], MQTT_MAX_TOPIC_LEN+1); // "wled/test"
|
getStringFromJson(mqttDeviceTopic, if_mqtt[F("topics")][F("device")], 33); // "wled/test"
|
||||||
getStringFromJson(mqttGroupTopic, if_mqtt[F("topics")][F("group")], MQTT_MAX_TOPIC_LEN+1); // ""
|
getStringFromJson(mqttGroupTopic, if_mqtt[F("topics")][F("group")], 33); // ""
|
||||||
CJSON(retainMqttMsg, if_mqtt[F("rtn")]);
|
CJSON(retainMqttMsg, if_mqtt[F("rtn")]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -481,6 +481,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
JsonObject if_ntp = interfaces[F("ntp")];
|
JsonObject if_ntp = interfaces[F("ntp")];
|
||||||
CJSON(ntpEnabled, if_ntp["en"]);
|
CJSON(ntpEnabled, if_ntp["en"]);
|
||||||
getStringFromJson(ntpServerName, if_ntp[F("host")], 33); // "1.wled.pool.ntp.org"
|
getStringFromJson(ntpServerName, if_ntp[F("host")], 33); // "1.wled.pool.ntp.org"
|
||||||
|
CJSON(ntpSyncInterval, if_ntp[F("int")]);
|
||||||
CJSON(currentTimezone, if_ntp[F("tz")]);
|
CJSON(currentTimezone, if_ntp[F("tz")]);
|
||||||
CJSON(utcOffsetSecs, if_ntp[F("offset")]);
|
CJSON(utcOffsetSecs, if_ntp[F("offset")]);
|
||||||
CJSON(useAMPM, if_ntp[F("ampm")]);
|
CJSON(useAMPM, if_ntp[F("ampm")]);
|
||||||
@ -939,6 +940,7 @@ void serializeConfig() {
|
|||||||
JsonObject if_ntp = interfaces.createNestedObject("ntp");
|
JsonObject if_ntp = interfaces.createNestedObject("ntp");
|
||||||
if_ntp["en"] = ntpEnabled;
|
if_ntp["en"] = ntpEnabled;
|
||||||
if_ntp[F("host")] = ntpServerName;
|
if_ntp[F("host")] = ntpServerName;
|
||||||
|
if_ntp[F("int")] = ntpSyncInterval;
|
||||||
if_ntp[F("tz")] = currentTimezone;
|
if_ntp[F("tz")] = currentTimezone;
|
||||||
if_ntp[F("offset")] = utcOffsetSecs;
|
if_ntp[F("offset")] = utcOffsetSecs;
|
||||||
if_ntp[F("ampm")] = useAMPM;
|
if_ntp[F("ampm")] = useAMPM;
|
||||||
|
@ -147,9 +147,8 @@
|
|||||||
#define USERMOD_ID_SD_CARD 37 //Usermod "usermod_sd_card.h"
|
#define USERMOD_ID_SD_CARD 37 //Usermod "usermod_sd_card.h"
|
||||||
#define USERMOD_ID_PWM_OUTPUTS 38 //Usermod "usermod_pwm_outputs.h
|
#define USERMOD_ID_PWM_OUTPUTS 38 //Usermod "usermod_pwm_outputs.h
|
||||||
#define USERMOD_ID_SHT 39 //Usermod "usermod_sht.h
|
#define USERMOD_ID_SHT 39 //Usermod "usermod_sht.h
|
||||||
#define USERMOD_ID_KLIPPER 40 //Usermod Klipper percentage
|
#define USERMOD_ID_KLIPPER 40 // Usermod Klipper percentage
|
||||||
#define USERMOD_ID_WIREGUARD 41 //Usermod "wireguard.h"
|
#define USERMOD_ID_WIREGUARD 41 //Usermod "wireguard.h"
|
||||||
#define USERMOD_ID_INTERNAL_TEMPERATURE 42 //Usermod "usermod_internal_temperature.h"
|
|
||||||
|
|
||||||
//Access point behavior
|
//Access point behavior
|
||||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||||
|
@ -1034,7 +1034,6 @@ textarea {
|
|||||||
/*padding: 1px 0 1px 20px;*/
|
/*padding: 1px 0 1px 20px;*/
|
||||||
display: var(--sgp);
|
display: var(--sgp);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.pname {
|
.pname {
|
||||||
|
@ -683,7 +683,6 @@ ${i.opt&0x100?inforow("Debug","<button class=\"btn btn-xs\" onclick=\"requestJso
|
|||||||
${inforow("Build",i.vid)}
|
${inforow("Build",i.vid)}
|
||||||
${inforow("Signal strength",i.wifi.signal +"% ("+ i.wifi.rssi, " dBm)")}
|
${inforow("Signal strength",i.wifi.signal +"% ("+ i.wifi.rssi, " dBm)")}
|
||||||
${inforow("Uptime",getRuntimeStr(i.uptime))}
|
${inforow("Uptime",getRuntimeStr(i.uptime))}
|
||||||
${inforow("Time",i.time)}
|
|
||||||
${inforow("Free heap",heap," kB")}
|
${inforow("Free heap",heap," kB")}
|
||||||
${i.psram?inforow("Free PSRAM",(i.psram/1024).toFixed(1)," kB"):""}
|
${i.psram?inforow("Free PSRAM",(i.psram/1024).toFixed(1)," kB"):""}
|
||||||
${inforow("Estimated current",pwru)}
|
${inforow("Estimated current",pwru)}
|
||||||
@ -835,7 +834,7 @@ function populateSegments(s)
|
|||||||
}
|
}
|
||||||
if (segCount < 2) {
|
if (segCount < 2) {
|
||||||
gId(`segd${lSeg}`).classList.add("hide");
|
gId(`segd${lSeg}`).classList.add("hide");
|
||||||
if (parseInt(gId("seg0bri").value)==255) gId(`segp0`).classList.add("hide");
|
gId(`segp0`).classList.add("hide");
|
||||||
}
|
}
|
||||||
if (!isM && !noNewSegs && (cfg.comp.seglen?parseInt(gId(`seg${lSeg}s`).value):0)+parseInt(gId(`seg${lSeg}e`).value)<ledCount) gId(`segr${lSeg}`).classList.remove("hide");
|
if (!isM && !noNewSegs && (cfg.comp.seglen?parseInt(gId(`seg${lSeg}s`).value):0)+parseInt(gId(`seg${lSeg}e`).value)<ledCount) gId(`segr${lSeg}`).classList.remove("hide");
|
||||||
gId('segutil2').style.display = (segCount > 1) ? "block":"none"; // rsbtn parent
|
gId('segutil2').style.display = (segCount > 1) ? "block":"none"; // rsbtn parent
|
||||||
@ -1248,7 +1247,7 @@ function updateSelectedPalette(s)
|
|||||||
if (s > 1 && s < 6) {
|
if (s > 1 && s < 6) {
|
||||||
cd[0].classList.remove('hide'); // * Color 1
|
cd[0].classList.remove('hide'); // * Color 1
|
||||||
if (s > 2) cd[1].classList.remove('hide'); // * Color 1 & 2
|
if (s > 2) cd[1].classList.remove('hide'); // * Color 1 & 2
|
||||||
if (s > 3) cd[2].classList.remove('hide'); // all colors
|
if (s == 5) cd[2].classList.remove('hide'); // all colors
|
||||||
} else {
|
} else {
|
||||||
for (let i of cd) if (i.dataset.hide == '1') i.classList.add('hide');
|
for (let i of cd) if (i.dataset.hide == '1') i.classList.add('hide');
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
<title>WLED Settings</title>
|
<title>WLED Settings</title>
|
||||||
<script>
|
<script>
|
||||||
var d=document;
|
var d=document;
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta name="viewport" content="width=500">
|
||||||
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
<title>2D Set-up</title>
|
<title>2D Set-up</title>
|
||||||
<script>
|
<script>
|
||||||
var d=document;
|
var d=document;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta name="viewport" content="width=500">
|
||||||
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>DMX Settings</title>
|
<title>DMX Settings</title>
|
||||||
<script>
|
<script>
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta name="viewport" content="width=500">
|
||||||
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
<title>LED Settings</title>
|
<title>LED Settings</title>
|
||||||
<script>
|
<script>
|
||||||
var d=document,laprev=55,maxB=1,maxV=0,maxM=4000,maxPB=4096,maxL=1333,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
|
var d=document,laprev=55,maxB=1,maxV=0,maxM=4000,maxPB=4096,maxL=1333,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta name="viewport" content="width=500">
|
||||||
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>PIN required</title>
|
<title>PIN required</title>
|
||||||
<script>
|
<script>
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta name="viewport" content="width=500">
|
||||||
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Misc Settings</title>
|
<title>Misc Settings</title>
|
||||||
<script>
|
<script>
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta name="viewport" content="width=500">
|
||||||
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Sync Settings</title>
|
<title>Sync Settings</title>
|
||||||
<script>var d=document;
|
<script>var d=document;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta name="viewport" content="width=500">
|
||||||
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Time Settings</title>
|
<title>Time Settings</title>
|
||||||
<script>
|
<script>
|
||||||
@ -170,6 +171,13 @@
|
|||||||
Get time from NTP server: <input type="checkbox" name="NT"><br>
|
Get time from NTP server: <input type="checkbox" name="NT"><br>
|
||||||
<input type="text" name="NS" maxlength="32"><br>
|
<input type="text" name="NS" maxlength="32"><br>
|
||||||
Use 24h format: <input type="checkbox" name="CF"><br>
|
Use 24h format: <input type="checkbox" name="CF"><br>
|
||||||
|
NTP refresh: <select name="NP">
|
||||||
|
<option value="86400">once</option>
|
||||||
|
<option value="43200" selected>twice</option>
|
||||||
|
<option value="21600">4 times</option>
|
||||||
|
<option value="14400">6 times</option>
|
||||||
|
<option value="10800">8 times</option>
|
||||||
|
</select> per day<br>
|
||||||
Time zone:
|
Time zone:
|
||||||
<select name="TZ">
|
<select name="TZ">
|
||||||
<option value="0" selected>GMT(UTC)</option>
|
<option value="0" selected>GMT(UTC)</option>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html>
|
||||||
<head>
|
<head lang="en">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta name="viewport" content="width=500">
|
||||||
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
<title>UI Settings</title>
|
<title>UI Settings</title>
|
||||||
<script>
|
<script>
|
||||||
var d = document;
|
var d = document;
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html>
|
||||||
<head>
|
<head lang="en">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta name="viewport" content="width=500">
|
||||||
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
<title>Usermod Settings</title>
|
<title>Usermod Settings</title>
|
||||||
<script>
|
<script>
|
||||||
var d = document;
|
var d = document;
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta name="viewport" content="width=500">
|
||||||
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
<title>WiFi Settings</title>
|
<title>WiFi Settings</title>
|
||||||
<script>
|
<script>
|
||||||
var d = document;
|
var d = document;
|
||||||
|
@ -523,7 +523,6 @@ ${urows}
|
|||||||
${inforow("Build",i.vid)}
|
${inforow("Build",i.vid)}
|
||||||
${inforow("Signal strength",i.wifi.signal +"% ("+ i.wifi.rssi, " dBm)")}
|
${inforow("Signal strength",i.wifi.signal +"% ("+ i.wifi.rssi, " dBm)")}
|
||||||
${inforow("Uptime",getRuntimeStr(i.uptime))}
|
${inforow("Uptime",getRuntimeStr(i.uptime))}
|
||||||
${inforow("Time",i.time)}
|
|
||||||
${inforow("Free heap",heap," kB")}
|
${inforow("Free heap",heap," kB")}
|
||||||
${i.psram?inforow("Free PSRAM",(i.psram/1024).toFixed(1)," kB"):""}
|
${i.psram?inforow("Free PSRAM",(i.psram/1024).toFixed(1)," kB"):""}
|
||||||
${inforow("Estimated current",pwru)}
|
${inforow("Estimated current",pwru)}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
// Autogenerated from wled00/data/cpal/cpal.htm, do not edit!!
|
// Autogenerated from wled00/data/cpal/cpal.htm, do not edit!!
|
||||||
const uint16_t PAGE_cpal_L = 4721;
|
const uint16_t PAGE_cpal_L = 4721;
|
||||||
const uint8_t PAGE_cpal[] PROGMEM = {
|
const uint8_t PAGE_cpal[] PROGMEM = {
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xbd, 0x3b, 0x7f, 0x73, 0xdb, 0xb6,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xbd, 0x3b, 0x7f, 0x73, 0xdb, 0xb6,
|
||||||
0x92, 0xff, 0xe7, 0x53, 0x20, 0x4c, 0x5f, 0x42, 0xd6, 0x14, 0x45, 0xd2, 0xb6, 0x64, 0x4b, 0xa2,
|
0x92, 0xff, 0xe7, 0x53, 0x20, 0x4c, 0x5f, 0x42, 0xd6, 0x14, 0x45, 0xd2, 0xb6, 0x64, 0x4b, 0xa2,
|
||||||
0x3b, 0xa9, 0x93, 0x77, 0xce, 0x8d, 0xdd, 0x64, 0x5e, 0x7c, 0x6e, 0x7b, 0x3e, 0xbf, 0x31, 0x4d,
|
0x3b, 0xa9, 0x93, 0x77, 0xce, 0x8d, 0xdd, 0x64, 0x5e, 0x7c, 0x6e, 0x7b, 0x3e, 0xbf, 0x31, 0x4d,
|
||||||
0x42, 0x12, 0x1b, 0x8a, 0xe0, 0x03, 0x21, 0xd9, 0xae, 0xac, 0xef, 0x7e, 0xbb, 0x00, 0x48, 0x91,
|
0x42, 0x12, 0x1b, 0x8a, 0xe0, 0x03, 0x21, 0xd9, 0xae, 0xac, 0xef, 0x7e, 0xbb, 0x00, 0x48, 0x91,
|
||||||
|
@ -41,47 +41,47 @@ const char PAGE_dmxmap[] PROGMEM = R"=====()=====";
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Autogenerated from wled00/data/update.htm, do not edit!!
|
// Autogenerated from wled00/data/update.htm, do not edit!!
|
||||||
const uint16_t PAGE_update_length = 613;
|
const uint16_t PAGE_update_length = 616;
|
||||||
const uint8_t PAGE_update[] PROGMEM = {
|
const uint8_t PAGE_update[] PROGMEM = {
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0x75, 0x53, 0x5d, 0x6f, 0xd4, 0x30,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0x75, 0x53, 0x4d, 0x6f, 0xd4, 0x30,
|
||||||
0x10, 0x7c, 0xcf, 0xaf, 0x70, 0xfd, 0x74, 0x27, 0x51, 0xbb, 0x20, 0x5e, 0x28, 0x49, 0x0a, 0x47,
|
0x10, 0xbd, 0xe7, 0x57, 0x18, 0x9f, 0x76, 0x25, 0xd6, 0x2e, 0x1f, 0x17, 0x4a, 0x92, 0x42, 0x69,
|
||||||
0x2b, 0x54, 0x09, 0xa9, 0x95, 0xda, 0x82, 0x78, 0x42, 0x8e, 0xbd, 0xb9, 0x98, 0x73, 0xec, 0xd4,
|
0x85, 0x2a, 0x21, 0xb5, 0x52, 0x5b, 0x10, 0x27, 0xe4, 0xd8, 0x93, 0x8d, 0x59, 0xc7, 0x4e, 0xed,
|
||||||
0xde, 0xdc, 0xe9, 0x84, 0xfa, 0xdf, 0xd9, 0x38, 0x77, 0x05, 0xf1, 0xf1, 0x12, 0xc5, 0xd9, 0xd9,
|
0xc9, 0xae, 0x56, 0xa8, 0xff, 0x9d, 0x89, 0xb3, 0x5b, 0x10, 0x1f, 0x97, 0x28, 0xce, 0xbc, 0x79,
|
||||||
0xf1, 0xee, 0xcc, 0xa4, 0x3c, 0xb9, 0xbc, 0xf9, 0x70, 0xff, 0xf5, 0xf6, 0x8a, 0x75, 0xd8, 0xbb,
|
0x9e, 0x79, 0xef, 0xa5, 0x7c, 0x76, 0x71, 0xfd, 0xe1, 0xee, 0xeb, 0xcd, 0x25, 0xeb, 0xb0, 0x77,
|
||||||
0xba, 0x3c, 0x3c, 0x41, 0x99, 0xba, 0xec, 0x01, 0x15, 0xd3, 0xc1, 0x23, 0x78, 0xac, 0xf8, 0xce,
|
0x75, 0x79, 0x78, 0x82, 0x32, 0x75, 0xd9, 0x03, 0x2a, 0xa6, 0x83, 0x47, 0xf0, 0x58, 0xf1, 0x9d,
|
||||||
0x1a, 0xec, 0x2a, 0x03, 0x5b, 0xab, 0xe1, 0x34, 0x1f, 0x38, 0xf3, 0xaa, 0x87, 0x8a, 0x6f, 0x2d,
|
0x35, 0xd8, 0x55, 0x06, 0xb6, 0x56, 0xc3, 0x2a, 0x1f, 0x38, 0xf3, 0xaa, 0x87, 0x8a, 0x6f, 0x2d,
|
||||||
0xec, 0x86, 0x10, 0x91, 0xd7, 0x45, 0x89, 0x16, 0x1d, 0xd4, 0x5f, 0x3e, 0x5d, 0x5d, 0xb2, 0x87,
|
0xec, 0x86, 0x10, 0x91, 0xd7, 0x45, 0x89, 0x16, 0x1d, 0xd4, 0x5f, 0x3e, 0x5d, 0x5e, 0xb0, 0xfb,
|
||||||
0xc1, 0x28, 0x84, 0x52, 0xce, 0x9f, 0xca, 0xa4, 0xa3, 0x1d, 0xb0, 0x2e, 0xda, 0xd1, 0x6b, 0xb4,
|
0xc1, 0x28, 0x84, 0x52, 0xce, 0x9f, 0xca, 0xa4, 0xa3, 0x1d, 0xb0, 0x2e, 0xda, 0xd1, 0x6b, 0xb4,
|
||||||
0xc1, 0xb3, 0xd5, 0x62, 0xf9, 0x63, 0x67, 0xbd, 0x09, 0x3b, 0xd1, 0xd9, 0x84, 0x21, 0xee, 0x45,
|
0xc1, 0xb3, 0xf3, 0xc5, 0xf2, 0xc7, 0xce, 0x7a, 0x13, 0x76, 0xa2, 0xb3, 0x09, 0x43, 0xdc, 0x8b,
|
||||||
0xa3, 0xf4, 0x66, 0xb1, 0x7c, 0x7a, 0x86, 0x3c, 0x10, 0xc4, 0x04, 0x3d, 0xf6, 0x34, 0x81, 0x58,
|
0x46, 0xe9, 0xcd, 0x62, 0xf9, 0xf8, 0x04, 0xb9, 0x27, 0x88, 0x09, 0x7a, 0xec, 0x69, 0x02, 0xb1,
|
||||||
0x03, 0x5e, 0x39, 0x98, 0x5e, 0x57, 0xfb, 0x6b, 0xb3, 0xe0, 0x63, 0xcb, 0x97, 0x22, 0xe1, 0xde,
|
0x06, 0xbc, 0x74, 0x30, 0xbd, 0x9e, 0xef, 0xaf, 0xcc, 0x82, 0x8f, 0x2d, 0x5f, 0x8a, 0x84, 0x7b,
|
||||||
0x81, 0x30, 0x36, 0x0d, 0x4e, 0xed, 0x2b, 0xee, 0x83, 0x07, 0xfe, 0xe2, 0xbf, 0x2d, 0x7d, 0x5a,
|
0x07, 0xc2, 0xd8, 0x34, 0x38, 0xb5, 0xaf, 0xb8, 0x0f, 0x1e, 0xf8, 0xf3, 0xff, 0xb6, 0xf4, 0x69,
|
||||||
0xff, 0xdd, 0xd3, 0xb8, 0xa0, 0x37, 0xfc, 0xa9, 0x28, 0xe5, 0x61, 0xc4, 0xc3, 0xa8, 0x2c, 0x45,
|
0xfd, 0x77, 0x4f, 0xe3, 0x82, 0xde, 0xf0, 0xc7, 0xa2, 0x94, 0x87, 0x11, 0x0f, 0xa3, 0xb2, 0x14,
|
||||||
0x5d, 0x71, 0x99, 0x00, 0xd1, 0xfa, 0x75, 0x92, 0x49, 0x7c, 0x4f, 0x17, 0x43, 0xf5, 0x86, 0xd7,
|
0x75, 0xc5, 0x65, 0x02, 0x44, 0xeb, 0xd7, 0x49, 0x26, 0xf1, 0x3d, 0x9d, 0x0d, 0xd5, 0x1b, 0x5e,
|
||||||
0xbf, 0x21, 0x27, 0xaa, 0xba, 0x78, 0x67, 0xfb, 0x49, 0x00, 0x36, 0x46, 0xb7, 0xe0, 0x33, 0xbd,
|
0xff, 0x86, 0x9c, 0xa8, 0xea, 0xe2, 0x9d, 0xed, 0x27, 0x01, 0xd8, 0x18, 0xdd, 0x82, 0xcf, 0xf4,
|
||||||
0x4e, 0x89, 0x2f, 0xdf, 0x12, 0x32, 0x23, 0x4a, 0x39, 0x4b, 0xda, 0x04, 0xb3, 0x67, 0xc1, 0xbb,
|
0x3a, 0x25, 0xbe, 0x7c, 0x4b, 0xc8, 0x8c, 0x28, 0xe5, 0x2c, 0x69, 0x13, 0xcc, 0x9e, 0x05, 0xef,
|
||||||
0xa0, 0x4c, 0xc5, 0x3f, 0x02, 0x7e, 0x5e, 0x2c, 0x89, 0xae, 0x7b, 0x55, 0x17, 0x59, 0xb2, 0xbb,
|
0x82, 0x32, 0x15, 0xff, 0x08, 0xf8, 0x79, 0xb1, 0x24, 0xba, 0xee, 0x65, 0x5d, 0x64, 0xc9, 0x6e,
|
||||||
0xd0, 0xe2, 0x4e, 0x45, 0x78, 0xd6, 0x8e, 0x2a, 0x65, 0x1b, 0x62, 0xcf, 0xc8, 0x8b, 0x2e, 0x50,
|
0x43, 0x8b, 0x3b, 0x15, 0xe1, 0x49, 0x3b, 0xaa, 0x94, 0x6d, 0x88, 0x3d, 0x23, 0x2f, 0xba, 0x40,
|
||||||
0xcf, 0xed, 0xcd, 0xdd, 0x3d, 0x67, 0x2a, 0xcb, 0x53, 0x71, 0x21, 0xc7, 0x0c, 0xe4, 0xcc, 0x52,
|
0x3d, 0x37, 0xd7, 0xb7, 0x77, 0x9c, 0xa9, 0x2c, 0x4f, 0xc5, 0x85, 0x1c, 0x33, 0x90, 0x33, 0x4b,
|
||||||
0x8d, 0x04, 0x61, 0x05, 0x90, 0x74, 0xfb, 0x81, 0x5c, 0xe9, 0x47, 0x87, 0x76, 0x50, 0x11, 0xe5,
|
0x35, 0x12, 0x84, 0x15, 0x40, 0xd2, 0xed, 0x07, 0x72, 0xa5, 0x1f, 0x1d, 0xda, 0x41, 0x45, 0x94,
|
||||||
0x44, 0x70, 0x4a, 0x30, 0xc5, 0xe9, 0xea, 0x34, 0x36, 0xbd, 0x25, 0x3b, 0x1f, 0xa6, 0x9b, 0xaf,
|
0x13, 0xc1, 0x8a, 0x60, 0x8a, 0xd3, 0xd5, 0x69, 0x6c, 0x7a, 0x4b, 0x76, 0xde, 0x4f, 0x37, 0x5f,
|
||||||
0x7d, 0x42, 0xe5, 0x1c, 0x18, 0xb6, 0x85, 0x98, 0x88, 0xf2, 0x9c, 0x95, 0x69, 0x50, 0x9e, 0x15,
|
0xf9, 0x84, 0xca, 0x39, 0x30, 0x6c, 0x0b, 0x31, 0x11, 0xe5, 0x29, 0x2b, 0xd3, 0xa0, 0x3c, 0x2b,
|
||||||
0xda, 0xa9, 0x94, 0x2a, 0x9e, 0xec, 0xc0, 0xeb, 0x33, 0xf1, 0xf2, 0xb5, 0x38, 0xa3, 0x55, 0xa8,
|
0xb4, 0x53, 0x29, 0x55, 0x3c, 0xd9, 0x81, 0xd7, 0x27, 0xe2, 0xc5, 0x6b, 0x71, 0xb2, 0x6a, 0x5e,
|
||||||
0x42, 0x2b, 0xc4, 0xfa, 0x32, 0xec, 0xf2, 0x0a, 0x0c, 0x3b, 0x60, 0x8e, 0xee, 0x4f, 0xc8, 0x1a,
|
0xd1, 0x36, 0x54, 0xa4, 0x2d, 0x62, 0x7d, 0x11, 0x76, 0x79, 0x0b, 0x86, 0x1d, 0x30, 0x47, 0x23,
|
||||||
0xeb, 0x55, 0xdc, 0x53, 0xbf, 0x62, 0x45, 0x17, 0xa1, 0xad, 0x78, 0x87, 0x38, 0xa4, 0x73, 0x29,
|
0x24, 0x64, 0x8d, 0xf5, 0x2a, 0xee, 0x89, 0x42, 0xb1, 0xa2, 0x8b, 0xd0, 0x56, 0xbc, 0x43, 0x1c,
|
||||||
0xd7, 0x16, 0xbb, 0xb1, 0x11, 0x3a, 0xf4, 0xf2, 0xbd, 0x8d, 0x3a, 0x84, 0xb0, 0xb1, 0x20, 0xa7,
|
0xd2, 0xa9, 0x94, 0x6b, 0x8b, 0xdd, 0xd8, 0x08, 0x1d, 0x7a, 0xf9, 0xde, 0x46, 0x1d, 0x42, 0xd8,
|
||||||
0x7d, 0x65, 0x04, 0x07, 0x2a, 0x41, 0xe2, 0x0c, 0x55, 0x24, 0xb3, 0x2a, 0xfe, 0xad, 0x71, 0xca,
|
0x58, 0x90, 0xd3, 0xca, 0x32, 0x82, 0x03, 0x95, 0x20, 0x71, 0x86, 0x2a, 0x92, 0x5f, 0x15, 0xff,
|
||||||
0x6f, 0x48, 0x13, 0xdb, 0xaf, 0x59, 0x91, 0x1d, 0x38, 0xf2, 0xd0, 0x17, 0x91, 0x3a, 0x0b, 0xce,
|
0xd6, 0x38, 0xe5, 0x37, 0x24, 0x8b, 0xed, 0xd7, 0xac, 0xc8, 0x26, 0x1c, 0x79, 0xe8, 0x8b, 0x48,
|
||||||
0x24, 0x61, 0xc3, 0x81, 0xf6, 0x48, 0xf1, 0x27, 0xb5, 0x48, 0xdb, 0xf5, 0x45, 0xd6, 0xbe, 0x6a,
|
0x9d, 0x05, 0x67, 0x92, 0xb0, 0xe1, 0x40, 0x7b, 0xa4, 0xf8, 0x93, 0x5a, 0xa4, 0xed, 0xfa, 0x2c,
|
||||||
0x69, 0xc2, 0xd3, 0xf4, 0x38, 0x92, 0xae, 0x53, 0x42, 0xa5, 0xca, 0x3b, 0x94, 0xd6, 0x0f, 0x23,
|
0xcb, 0x5f, 0xb5, 0x34, 0xe1, 0x2a, 0x3d, 0x8c, 0x24, 0xed, 0x14, 0x52, 0xa9, 0xf2, 0x0e, 0xa5,
|
||||||
0xb2, 0x59, 0xab, 0xd6, 0x3a, 0x38, 0xa6, 0xf9, 0xa8, 0x68, 0x84, 0xc7, 0xd1, 0x46, 0x30, 0x33,
|
0xf5, 0xc3, 0x88, 0x6c, 0x96, 0xab, 0xb5, 0x0e, 0x8e, 0x81, 0x3e, 0x8a, 0x1a, 0xe1, 0x61, 0xb4,
|
||||||
0xba, 0x19, 0x11, 0x29, 0x90, 0x33, 0x7c, 0xd6, 0x90, 0xc8, 0x66, 0x9b, 0x4e, 0x4a, 0x39, 0x97,
|
0x11, 0xcc, 0x8c, 0x6e, 0x46, 0x44, 0xca, 0xe4, 0x0c, 0x9f, 0x65, 0x24, 0xb2, 0xd9, 0xa9, 0x67,
|
||||||
0xff, 0x01, 0x9d, 0x0f, 0x93, 0xf0, 0xda, 0x59, 0xbd, 0xa9, 0xf8, 0x6a, 0xd2, 0x7d, 0x45, 0x39,
|
0xa5, 0x9c, 0xcb, 0xff, 0x80, 0xce, 0x87, 0x49, 0x7b, 0xed, 0xac, 0xde, 0x54, 0xfc, 0x7c, 0x92,
|
||||||
0xff, 0xd5, 0x94, 0x0d, 0xaa, 0x4b, 0x63, 0xb7, 0x45, 0xf6, 0x71, 0x4a, 0x29, 0xd1, 0xd4, 0x99,
|
0xfe, 0x9c, 0xa2, 0xfe, 0xab, 0x29, 0x7b, 0x54, 0x97, 0xc6, 0x6e, 0x8b, 0x6c, 0xe5, 0x14, 0x54,
|
||||||
0x9d, 0xa2, 0x27, 0x84, 0x20, 0x70, 0x26, 0xbf, 0xcd, 0xcb, 0x32, 0x13, 0x98, 0x0f, 0xc8, 0xb4,
|
0xa2, 0xa9, 0x33, 0x3b, 0xa5, 0x4f, 0x08, 0x41, 0xe0, 0x4c, 0x7e, 0x93, 0x97, 0x65, 0x26, 0x30,
|
||||||
0x0b, 0x74, 0x08, 0x91, 0x66, 0x6d, 0x23, 0xa4, 0x2e, 0xfb, 0x31, 0xa8, 0x35, 0xb0, 0xf3, 0x65,
|
0x1f, 0x90, 0x69, 0x17, 0xe8, 0x10, 0x22, 0xcd, 0xda, 0x46, 0x48, 0x5d, 0xf6, 0x63, 0x50, 0x6b,
|
||||||
0x29, 0x89, 0x6f, 0x5a, 0x77, 0x8a, 0xdc, 0x94, 0xbf, 0xe9, 0xc7, 0xfe, 0x09, 0x45, 0xc9, 0x0d,
|
0x60, 0xa7, 0xcb, 0x52, 0x12, 0xdf, 0xb4, 0xee, 0x94, 0xba, 0x29, 0x82, 0xd3, 0xbf, 0xfd, 0x13,
|
||||||
0xd4, 0xee, 0x03, 0x00, 0x00
|
0x46, 0x22, 0xf9, 0xe1, 0xf1, 0x03, 0x00, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2261
wled00/html_simple.h
2261
wled00/html_simple.h
File diff suppressed because it is too large
Load Diff
3936
wled00/html_ui.h
3936
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -210,7 +210,7 @@ void sendImprovInfoResponse() {
|
|||||||
//Use serverDescription if it has been changed from the default "WLED", else mDNS name
|
//Use serverDescription if it has been changed from the default "WLED", else mDNS name
|
||||||
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
|
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
|
||||||
char vString[20];
|
char vString[20];
|
||||||
sprintf_P(vString, PSTR("0.14.0/%i"), VERSION);
|
sprintf_P(vString, PSTR("0.14.0-b4/%i"), VERSION);
|
||||||
const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription};
|
const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription};
|
||||||
|
|
||||||
sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str);
|
sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str);
|
||||||
|
@ -20,7 +20,6 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
byte id = elem["id"] | it;
|
byte id = elem["id"] | it;
|
||||||
if (id >= strip.getMaxSegments()) return false;
|
if (id >= strip.getMaxSegments()) return false;
|
||||||
|
|
||||||
bool newSeg = false;
|
|
||||||
int stop = elem["stop"] | -1;
|
int stop = elem["stop"] | -1;
|
||||||
|
|
||||||
// append segment
|
// append segment
|
||||||
@ -28,14 +27,10 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
if (stop <= 0) return false; // ignore empty/inactive segments
|
if (stop <= 0) return false; // ignore empty/inactive segments
|
||||||
strip.appendSegment(Segment(0, strip.getLengthTotal()));
|
strip.appendSegment(Segment(0, strip.getLengthTotal()));
|
||||||
id = strip.getSegmentsNum()-1; // segments are added at the end of list
|
id = strip.getSegmentsNum()-1; // segments are added at the end of list
|
||||||
newSeg = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//DEBUG_PRINTLN("-- JSON deserialize segment.");
|
|
||||||
Segment& seg = strip.getSegment(id);
|
Segment& seg = strip.getSegment(id);
|
||||||
//DEBUG_PRINTF("-- Original segment: %p\n", &seg);
|
|
||||||
Segment prev = seg; //make a backup so we can tell if something changed
|
Segment prev = seg; //make a backup so we can tell if something changed
|
||||||
//DEBUG_PRINTF("-- Duplicate segment: %p\n", &prev);
|
|
||||||
|
|
||||||
uint16_t start = elem["start"] | seg.start;
|
uint16_t start = elem["start"] | seg.start;
|
||||||
if (stop < 0) {
|
if (stop < 0) {
|
||||||
@ -120,12 +115,8 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
// do not call seg.setUp() here, as it may cause a crash due to concurrent access if the segment is currently drawing effects
|
// do not call seg.setUp() here, as it may cause a crash due to concurrent access if the segment is currently drawing effects
|
||||||
// WS2812FX handles queueing of the change
|
// WS2812FX handles queueing of the change
|
||||||
strip.setSegment(id, start, stop, grp, spc, of, startY, stopY);
|
strip.setSegment(id, start, stop, grp, spc, of, startY, stopY);
|
||||||
if (newSeg) seg.refreshLightCapabilities(); // fix for #3403
|
|
||||||
|
|
||||||
if (seg.reset && seg.stop == 0) {
|
if (seg.reset && seg.stop == 0) return true; // segment was deleted & is marked for reset, no need to change anything else
|
||||||
if (id == strip.getMainSegmentId()) strip.setMainSegmentId(0); // fix for #3403
|
|
||||||
return true; // segment was deleted & is marked for reset, no need to change anything else
|
|
||||||
}
|
|
||||||
|
|
||||||
byte segbri = seg.opacity;
|
byte segbri = seg.opacity;
|
||||||
if (getVal(elem["bri"], &segbri)) {
|
if (getVal(elem["bri"], &segbri)) {
|
||||||
@ -748,10 +739,6 @@ void serializeInfo(JsonObject root)
|
|||||||
#endif
|
#endif
|
||||||
root[F("uptime")] = millis()/1000 + rolloverMillis*4294967;
|
root[F("uptime")] = millis()/1000 + rolloverMillis*4294967;
|
||||||
|
|
||||||
char time[32];
|
|
||||||
getTimeString(time);
|
|
||||||
root[F("time")] = time;
|
|
||||||
|
|
||||||
usermods.addToJsonInfo(root);
|
usermods.addToJsonInfo(root);
|
||||||
|
|
||||||
uint16_t os = 0;
|
uint16_t os = 0;
|
||||||
@ -988,10 +975,9 @@ void serializeNodes(JsonObject root)
|
|||||||
// deserializes mode data string into JsonArray
|
// deserializes mode data string into JsonArray
|
||||||
void serializeModeData(JsonArray fxdata)
|
void serializeModeData(JsonArray fxdata)
|
||||||
{
|
{
|
||||||
char lineBuffer[256];
|
char lineBuffer[128];
|
||||||
for (size_t i = 0; i < strip.getModeCount(); i++) {
|
for (size_t i = 0; i < strip.getModeCount(); i++) {
|
||||||
strncpy_P(lineBuffer, strip.getModeData(i), sizeof(lineBuffer)/sizeof(char)-1);
|
strncpy_P(lineBuffer, strip.getModeData(i), 127);
|
||||||
lineBuffer[sizeof(lineBuffer)/sizeof(char)-1] = '\0'; // terminate string
|
|
||||||
if (lineBuffer[0] != 0) {
|
if (lineBuffer[0] != 0) {
|
||||||
char* dataPtr = strchr(lineBuffer,'@');
|
char* dataPtr = strchr(lineBuffer,'@');
|
||||||
if (dataPtr) fxdata.add(dataPtr+1);
|
if (dataPtr) fxdata.add(dataPtr+1);
|
||||||
@ -1002,12 +988,10 @@ void serializeModeData(JsonArray fxdata)
|
|||||||
|
|
||||||
// deserializes mode names string into JsonArray
|
// deserializes mode names string into JsonArray
|
||||||
// also removes effect data extensions (@...) from deserialised names
|
// also removes effect data extensions (@...) from deserialised names
|
||||||
void serializeModeNames(JsonArray arr)
|
void serializeModeNames(JsonArray arr) {
|
||||||
{
|
char lineBuffer[128];
|
||||||
char lineBuffer[256];
|
|
||||||
for (size_t i = 0; i < strip.getModeCount(); i++) {
|
for (size_t i = 0; i < strip.getModeCount(); i++) {
|
||||||
strncpy_P(lineBuffer, strip.getModeData(i), sizeof(lineBuffer)/sizeof(char)-1);
|
strncpy_P(lineBuffer, strip.getModeData(i), 127);
|
||||||
lineBuffer[sizeof(lineBuffer)/sizeof(char)-1] = '\0'; // terminate string
|
|
||||||
if (lineBuffer[0] != 0) {
|
if (lineBuffer[0] != 0) {
|
||||||
char* dataPtr = strchr(lineBuffer,'@');
|
char* dataPtr = strchr(lineBuffer,'@');
|
||||||
if (dataPtr) *dataPtr = 0; // terminate mode data after name
|
if (dataPtr) *dataPtr = 0; // terminate mode data after name
|
||||||
|
@ -37,12 +37,12 @@ void applyValuesToSelectedSegs()
|
|||||||
|
|
||||||
if (effectSpeed != selsegPrev.speed) {seg.speed = effectSpeed; stateChanged = true;}
|
if (effectSpeed != selsegPrev.speed) {seg.speed = effectSpeed; stateChanged = true;}
|
||||||
if (effectIntensity != selsegPrev.intensity) {seg.intensity = effectIntensity; stateChanged = true;}
|
if (effectIntensity != selsegPrev.intensity) {seg.intensity = effectIntensity; stateChanged = true;}
|
||||||
if (effectPalette != selsegPrev.palette) {seg.setPalette(effectPalette);}
|
if (effectPalette != selsegPrev.palette) {seg.setPalette(effectPalette); stateChanged = true;}
|
||||||
if (effectCurrent != selsegPrev.mode) {seg.setMode(effectCurrent);}
|
if (effectCurrent != selsegPrev.mode) {seg.setMode(effectCurrent); stateChanged = true;}
|
||||||
uint32_t col0 = RGBW32( col[0], col[1], col[2], col[3]);
|
uint32_t col0 = RGBW32( col[0], col[1], col[2], col[3]);
|
||||||
uint32_t col1 = RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]);
|
uint32_t col1 = RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]);
|
||||||
if (col0 != selsegPrev.colors[0]) {seg.setColor(0, col0);}
|
if (col0 != selsegPrev.colors[0]) {seg.setColor(0, col0); stateChanged = true;}
|
||||||
if (col1 != selsegPrev.colors[1]) {seg.setColor(1, col1);}
|
if (col1 != selsegPrev.colors[1]) {seg.setColor(1, col1); stateChanged = true;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,8 +161,6 @@ void stateUpdated(byte callMode) {
|
|||||||
|
|
||||||
void updateInterfaces(uint8_t callMode)
|
void updateInterfaces(uint8_t callMode)
|
||||||
{
|
{
|
||||||
if (!interfaceUpdateCallMode || millis() - lastInterfaceUpdate < INTERFACE_UPDATE_COOLDOWN) return;
|
|
||||||
|
|
||||||
sendDataWs();
|
sendDataWs();
|
||||||
lastInterfaceUpdate = millis();
|
lastInterfaceUpdate = millis();
|
||||||
if (callMode == CALL_MODE_WS_SEND) return;
|
if (callMode == CALL_MODE_WS_SEND) return;
|
||||||
@ -181,7 +179,7 @@ void updateInterfaces(uint8_t callMode)
|
|||||||
void handleTransitions()
|
void handleTransitions()
|
||||||
{
|
{
|
||||||
//handle still pending interface update
|
//handle still pending interface update
|
||||||
updateInterfaces(interfaceUpdateCallMode);
|
if (interfaceUpdateCallMode && millis() - lastInterfaceUpdate > INTERFACE_UPDATE_COOLDOWN) updateInterfaces(interfaceUpdateCallMode);
|
||||||
#ifndef WLED_DISABLE_MQTT
|
#ifndef WLED_DISABLE_MQTT
|
||||||
if (doPublishMqtt) publishMqtt();
|
if (doPublishMqtt) publishMqtt();
|
||||||
#endif
|
#endif
|
||||||
@ -189,7 +187,7 @@ void handleTransitions()
|
|||||||
if (transitionActive && transitionDelayTemp > 0)
|
if (transitionActive && transitionDelayTemp > 0)
|
||||||
{
|
{
|
||||||
float tper = (millis() - transitionStartTime)/(float)transitionDelayTemp;
|
float tper = (millis() - transitionStartTime)/(float)transitionDelayTemp;
|
||||||
if (tper >= 1.0f)
|
if (tper >= 1.0)
|
||||||
{
|
{
|
||||||
strip.setTransitionMode(false);
|
strip.setTransitionMode(false);
|
||||||
transitionActive = false;
|
transitionActive = false;
|
||||||
|
@ -25,7 +25,7 @@ bool parseLx(int lxValue, byte* rgbw)
|
|||||||
float tmpBri = floor((lxValue - 200000000) / 10000); ;
|
float tmpBri = floor((lxValue - 200000000) / 10000); ;
|
||||||
uint16_t ct = (lxValue - 200000000) - (((uint8_t)tmpBri) * 10000);
|
uint16_t ct = (lxValue - 200000000) - (((uint8_t)tmpBri) * 10000);
|
||||||
|
|
||||||
tmpBri *= 2.55f;
|
tmpBri *= 2.55;
|
||||||
tmpBri = constrain(tmpBri, 0, 255);
|
tmpBri = constrain(tmpBri, 0, 255);
|
||||||
|
|
||||||
colorKtoRGB(ct, rgbw);
|
colorKtoRGB(ct, rgbw);
|
||||||
|
@ -2,26 +2,10 @@
|
|||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
#include "fcn_declare.h"
|
#include "fcn_declare.h"
|
||||||
|
|
||||||
// on esp8266, building with `-D WLED_USE_UNREAL_MATH` saves around 7Kb flash and 1KB RAM
|
|
||||||
// warning: causes errors in sunset calculations, see #3400
|
|
||||||
#if defined(WLED_USE_UNREAL_MATH)
|
|
||||||
#define sinf sin_t
|
|
||||||
#define asinf asin_t
|
|
||||||
#define cosf cos_t
|
|
||||||
#define acosf acos_t
|
|
||||||
#define tanf tan_t
|
|
||||||
#define atanf atan_t
|
|
||||||
#define fmodf fmod_t
|
|
||||||
#define floorf floor_t
|
|
||||||
#else
|
|
||||||
#include <math.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Acquires time from NTP server
|
* Acquires time from NTP server
|
||||||
*/
|
*/
|
||||||
//#define WLED_DEBUG_NTP
|
//#define WLED_DEBUG_NTP
|
||||||
#define NTP_SYNC_INTERVAL 42000UL //Get fresh NTP time about twice per day
|
|
||||||
|
|
||||||
Timezone* tz;
|
Timezone* tz;
|
||||||
|
|
||||||
@ -195,7 +179,7 @@ void handleTime() {
|
|||||||
|
|
||||||
void handleNetworkTime()
|
void handleNetworkTime()
|
||||||
{
|
{
|
||||||
if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > (1000*NTP_SYNC_INTERVAL) && WLED_CONNECTED)
|
if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > (1000UL*ntpSyncInterval) && WLED_CONNECTED)
|
||||||
{
|
{
|
||||||
if (millis() - ntpPacketSentTime > 10000)
|
if (millis() - ntpPacketSentTime > 10000)
|
||||||
{
|
{
|
||||||
@ -427,8 +411,8 @@ int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunse
|
|||||||
//1. first calculate the day of the year
|
//1. first calculate the day of the year
|
||||||
float N1 = 275 * month / 9;
|
float N1 = 275 * month / 9;
|
||||||
float N2 = (month + 9) / 12;
|
float N2 = (month + 9) / 12;
|
||||||
float N3 = (1.0f + floorf((year - 4 * floorf(year / 4) + 2.0f) / 3.0f));
|
float N3 = (1 + floor_t((year - 4 * floor_t(year / 4) + 2) / 3));
|
||||||
float N = N1 - (N2 * N3) + day - 30.0f;
|
float N = N1 - (N2 * N3) + day - 30;
|
||||||
|
|
||||||
//2. convert the longitude to hour value and calculate an approximate time
|
//2. convert the longitude to hour value and calculate an approximate time
|
||||||
float lngHour = lon / 15.0f;
|
float lngHour = lon / 15.0f;
|
||||||
@ -438,37 +422,37 @@ int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunse
|
|||||||
float M = (0.9856f * t) - 3.289f;
|
float M = (0.9856f * t) - 3.289f;
|
||||||
|
|
||||||
//4. calculate the Sun's true longitude
|
//4. calculate the Sun's true longitude
|
||||||
float L = fmodf(M + (1.916f * sinf(DEG_TO_RAD*M)) + (0.02f * sinf(2*DEG_TO_RAD*M)) + 282.634f, 360.0f);
|
float L = fmod_t(M + (1.916f * sin_t(DEG_TO_RAD*M)) + (0.02f * sin_t(2*DEG_TO_RAD*M)) + 282.634f, 360.0f);
|
||||||
|
|
||||||
//5a. calculate the Sun's right ascension
|
//5a. calculate the Sun's right ascension
|
||||||
float RA = fmodf(RAD_TO_DEG*atanf(0.91764f * tanf(DEG_TO_RAD*L)), 360.0f);
|
float RA = fmod_t(RAD_TO_DEG*atan_t(0.91764f * tan_t(DEG_TO_RAD*L)), 360.0f);
|
||||||
|
|
||||||
//5b. right ascension value needs to be in the same quadrant as L
|
//5b. right ascension value needs to be in the same quadrant as L
|
||||||
float Lquadrant = floorf( L/90) * 90;
|
float Lquadrant = floor_t( L/90) * 90;
|
||||||
float RAquadrant = floorf(RA/90) * 90;
|
float RAquadrant = floor_t(RA/90) * 90;
|
||||||
RA = RA + (Lquadrant - RAquadrant);
|
RA = RA + (Lquadrant - RAquadrant);
|
||||||
|
|
||||||
//5c. right ascension value needs to be converted into hours
|
//5c. right ascension value needs to be converted into hours
|
||||||
RA /= 15.0f;
|
RA /= 15.0f;
|
||||||
|
|
||||||
//6. calculate the Sun's declination
|
//6. calculate the Sun's declination
|
||||||
float sinDec = 0.39782f * sinf(DEG_TO_RAD*L);
|
float sinDec = 0.39782f * sin_t(DEG_TO_RAD*L);
|
||||||
float cosDec = cosf(asinf(sinDec));
|
float cosDec = cos_t(asin_t(sinDec));
|
||||||
|
|
||||||
//7a. calculate the Sun's local hour angle
|
//7a. calculate the Sun's local hour angle
|
||||||
float cosH = (sinf(DEG_TO_RAD*ZENITH) - (sinDec * sinf(DEG_TO_RAD*lat))) / (cosDec * cosf(DEG_TO_RAD*lat));
|
float cosH = (sin_t(DEG_TO_RAD*ZENITH) - (sinDec * sin_t(DEG_TO_RAD*lat))) / (cosDec * cos_t(DEG_TO_RAD*lat));
|
||||||
if ((cosH > 1.0f) && !sunset) return 0; // the sun never rises on this location (on the specified date)
|
if (cosH > 1 && !sunset) return 0; // the sun never rises on this location (on the specified date)
|
||||||
if ((cosH < -1.0f) && sunset) return 0; // the sun never sets on this location (on the specified date)
|
if (cosH < -1 && sunset) return 0; // the sun never sets on this location (on the specified date)
|
||||||
|
|
||||||
//7b. finish calculating H and convert into hours
|
//7b. finish calculating H and convert into hours
|
||||||
float H = sunset ? RAD_TO_DEG*acosf(cosH) : 360 - RAD_TO_DEG*acosf(cosH);
|
float H = sunset ? RAD_TO_DEG*acos_t(cosH) : 360 - RAD_TO_DEG*acos_t(cosH);
|
||||||
H /= 15.0f;
|
H /= 15.0f;
|
||||||
|
|
||||||
//8. calculate local mean time of rising/setting
|
//8. calculate local mean time of rising/setting
|
||||||
float T = H + RA - (0.06571f * t) - 6.622f;
|
float T = H + RA - (0.06571f * t) - 6.622f;
|
||||||
|
|
||||||
//9. adjust back to UTC
|
//9. adjust back to UTC
|
||||||
float UT = fmodf(T - lngHour, 24.0f);
|
float UT = fmod_t(T - lngHour, 24.0f);
|
||||||
|
|
||||||
// return in minutes from midnight
|
// return in minutes from midnight
|
||||||
return UT*60;
|
return UT*60;
|
||||||
|
@ -112,7 +112,7 @@ int16_t loadPlaylist(JsonObject playlistObj, byte presetId) {
|
|||||||
if (playlistEndPreset == 255 && currentPreset > 0) playlistEndPreset = currentPreset;
|
if (playlistEndPreset == 255 && currentPreset > 0) playlistEndPreset = currentPreset;
|
||||||
if (playlistEndPreset > 250) playlistEndPreset = 0;
|
if (playlistEndPreset > 250) playlistEndPreset = 0;
|
||||||
shuffle = shuffle || playlistObj["r"];
|
shuffle = shuffle || playlistObj["r"];
|
||||||
if (shuffle) playlistOptions |= PL_OPTION_SHUFFLE;
|
if (shuffle) playlistOptions += PL_OPTION_SHUFFLE;
|
||||||
|
|
||||||
currentPlaylist = presetId;
|
currentPlaylist = presetId;
|
||||||
DEBUG_PRINTLN(F("Playlist loaded."));
|
DEBUG_PRINTLN(F("Playlist loaded."));
|
||||||
@ -156,7 +156,7 @@ void serializePlaylist(JsonObject sObj) {
|
|||||||
JsonArray ps = playlist.createNestedArray("ps");
|
JsonArray ps = playlist.createNestedArray("ps");
|
||||||
JsonArray dur = playlist.createNestedArray("dur");
|
JsonArray dur = playlist.createNestedArray("dur");
|
||||||
JsonArray transition = playlist.createNestedArray(F("transition"));
|
JsonArray transition = playlist.createNestedArray(F("transition"));
|
||||||
playlist[F("repeat")] = (playlistIndex < 0 && playlistRepeat > 0) ? playlistRepeat - 1 : playlistRepeat; // remove added repetition count (if not yet running)
|
playlist[F("repeat")] = (playlistIndex < 0) ? playlistRepeat - 1 : playlistRepeat; // remove added repetition count (if not yet running)
|
||||||
playlist["end"] = playlistEndPreset;
|
playlist["end"] = playlistEndPreset;
|
||||||
playlist["r"] = playlistOptions & PL_OPTION_SHUFFLE;
|
playlist["r"] = playlistOptions & PL_OPTION_SHUFFLE;
|
||||||
for (int i=0; i<playlistLen; i++) {
|
for (int i=0; i<playlistLen; i++) {
|
||||||
|
@ -347,14 +347,14 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
|
|
||||||
#ifdef WLED_ENABLE_MQTT
|
#ifdef WLED_ENABLE_MQTT
|
||||||
mqttEnabled = request->hasArg(F("MQ"));
|
mqttEnabled = request->hasArg(F("MQ"));
|
||||||
strlcpy(mqttServer, request->arg(F("MS")).c_str(), MQTT_MAX_SERVER_LEN+1);
|
strlcpy(mqttServer, request->arg(F("MS")).c_str(), 33);
|
||||||
t = request->arg(F("MQPORT")).toInt();
|
t = request->arg(F("MQPORT")).toInt();
|
||||||
if (t > 0) mqttPort = t;
|
if (t > 0) mqttPort = t;
|
||||||
strlcpy(mqttUser, request->arg(F("MQUSER")).c_str(), 41);
|
strlcpy(mqttUser, request->arg(F("MQUSER")).c_str(), 41);
|
||||||
if (!isAsterisksOnly(request->arg(F("MQPASS")).c_str(), 41)) strlcpy(mqttPass, request->arg(F("MQPASS")).c_str(), 65);
|
if (!isAsterisksOnly(request->arg(F("MQPASS")).c_str(), 41)) strlcpy(mqttPass, request->arg(F("MQPASS")).c_str(), 65);
|
||||||
strlcpy(mqttClientID, request->arg(F("MQCID")).c_str(), 41);
|
strlcpy(mqttClientID, request->arg(F("MQCID")).c_str(), 41);
|
||||||
strlcpy(mqttDeviceTopic, request->arg(F("MD")).c_str(), MQTT_MAX_TOPIC_LEN+1);
|
strlcpy(mqttDeviceTopic, request->arg(F("MD")).c_str(), 33);
|
||||||
strlcpy(mqttGroupTopic, request->arg(F("MG")).c_str(), MQTT_MAX_TOPIC_LEN+1);
|
strlcpy(mqttGroupTopic, request->arg(F("MG")).c_str(), 33);
|
||||||
buttonPublishMqtt = request->hasArg(F("BM"));
|
buttonPublishMqtt = request->hasArg(F("BM"));
|
||||||
retainMqttMsg = request->hasArg(F("RT"));
|
retainMqttMsg = request->hasArg(F("RT"));
|
||||||
#endif
|
#endif
|
||||||
@ -390,6 +390,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
ntpEnabled = request->hasArg(F("NT"));
|
ntpEnabled = request->hasArg(F("NT"));
|
||||||
strlcpy(ntpServerName, request->arg(F("NS")).c_str(), 33);
|
strlcpy(ntpServerName, request->arg(F("NS")).c_str(), 33);
|
||||||
useAMPM = !request->hasArg(F("CF"));
|
useAMPM = !request->hasArg(F("CF"));
|
||||||
|
ntpSyncInterval = min(86400U, max(10800U, (unsigned int)request->arg(F("NP")).toInt()));
|
||||||
currentTimezone = request->arg(F("TZ")).toInt();
|
currentTimezone = request->arg(F("TZ")).toInt();
|
||||||
utcOffsetSecs = request->arg(F("UO")).toInt();
|
utcOffsetSecs = request->arg(F("UO")).toInt();
|
||||||
|
|
||||||
|
@ -177,10 +177,6 @@
|
|||||||
#include "../usermods/boblight/boblight.h"
|
#include "../usermods/boblight/boblight.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USERMOD_INTERNAL_TEMPERATURE
|
|
||||||
#include "../usermods/Internal_Temperature_v2/usermod_internal_temperature.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(WLED_USE_SD_MMC) || defined(WLED_USE_SD_SPI)
|
#if defined(WLED_USE_SD_MMC) || defined(WLED_USE_SD_SPI)
|
||||||
// This include of SD.h and SD_MMC.h must happen here, else they won't be
|
// This include of SD.h and SD_MMC.h must happen here, else they won't be
|
||||||
// resolved correctly (when included in mod's header only)
|
// resolved correctly (when included in mod's header only)
|
||||||
@ -369,8 +365,4 @@ void registerUsermods()
|
|||||||
#ifdef USERMOD_SHT
|
#ifdef USERMOD_SHT
|
||||||
usermods.add(new ShtUsermod());
|
usermods.add(new ShtUsermod());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USERMOD_INTERNAL_TEMPERATURE
|
|
||||||
usermods.add(new InternalTemperatureUsermod());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
@ -148,14 +148,8 @@ bool oappendi(int i)
|
|||||||
bool oappend(const char* txt)
|
bool oappend(const char* txt)
|
||||||
{
|
{
|
||||||
uint16_t len = strlen(txt);
|
uint16_t len = strlen(txt);
|
||||||
if (olen + len >= SETTINGS_STACK_BUF_SIZE) {
|
if (olen + len >= SETTINGS_STACK_BUF_SIZE)
|
||||||
#ifdef WLED_DEBUG
|
|
||||||
DEBUG_PRINT(F("oappend() buffer overflow. Cannnot append "));
|
|
||||||
DEBUG_PRINT(len); DEBUG_PRINT(F(" bytes \t\""));
|
|
||||||
DEBUG_PRINT(txt); DEBUG_PRINTLN(F("\""));
|
|
||||||
#endif
|
|
||||||
return false; // buffer full
|
return false; // buffer full
|
||||||
}
|
|
||||||
strcpy(obuf + olen, txt);
|
strcpy(obuf + olen, txt);
|
||||||
olen += len;
|
olen += len;
|
||||||
return true;
|
return true;
|
||||||
@ -239,8 +233,7 @@ uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLe
|
|||||||
if (mode < strip.getModeCount()) {
|
if (mode < strip.getModeCount()) {
|
||||||
char lineBuffer[256];
|
char lineBuffer[256];
|
||||||
//strcpy_P(lineBuffer, (const char*)pgm_read_dword(&(WS2812FX::_modeData[mode])));
|
//strcpy_P(lineBuffer, (const char*)pgm_read_dword(&(WS2812FX::_modeData[mode])));
|
||||||
strncpy_P(lineBuffer, strip.getModeData(mode), sizeof(lineBuffer)/sizeof(char)-1);
|
strcpy_P(lineBuffer, strip.getModeData(mode));
|
||||||
lineBuffer[sizeof(lineBuffer)/sizeof(char)-1] = '\0'; // terminate string
|
|
||||||
size_t len = strlen(lineBuffer);
|
size_t len = strlen(lineBuffer);
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
for (; j < maxLen && j < len; j++) {
|
for (; j < maxLen && j < len; j++) {
|
||||||
@ -252,12 +245,6 @@ uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLe
|
|||||||
} else return 0;
|
} else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src == JSON_palette_names && mode > GRADIENT_PALETTE_COUNT) {
|
|
||||||
snprintf_P(dest, maxLen, PSTR("~ Custom %d~"), 255-mode);
|
|
||||||
dest[maxLen-1] = '\0';
|
|
||||||
return strlen(dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t qComma = 0;
|
uint8_t qComma = 0;
|
||||||
bool insideQuotes = false;
|
bool insideQuotes = false;
|
||||||
uint8_t printedChars = 0;
|
uint8_t printedChars = 0;
|
||||||
@ -368,9 +355,9 @@ uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxL
|
|||||||
int16_t extractModeDefaults(uint8_t mode, const char *segVar)
|
int16_t extractModeDefaults(uint8_t mode, const char *segVar)
|
||||||
{
|
{
|
||||||
if (mode < strip.getModeCount()) {
|
if (mode < strip.getModeCount()) {
|
||||||
char lineBuffer[256];
|
char lineBuffer[128] = "";
|
||||||
strncpy_P(lineBuffer, strip.getModeData(mode), sizeof(lineBuffer)/sizeof(char)-1);
|
strncpy_P(lineBuffer, strip.getModeData(mode), 127);
|
||||||
lineBuffer[sizeof(lineBuffer)/sizeof(char)-1] = '\0'; // terminate string
|
lineBuffer[127] = '\0'; // terminate string
|
||||||
if (lineBuffer[0] != 0) {
|
if (lineBuffer[0] != 0) {
|
||||||
char* startPtr = strrchr(lineBuffer, ';'); // last ";" in FX data
|
char* startPtr = strrchr(lineBuffer, ';'); // last ";" in FX data
|
||||||
if (!startPtr) return -1;
|
if (!startPtr) return -1;
|
||||||
@ -520,7 +507,7 @@ um_data_t* simulateSound(uint8_t simulationId)
|
|||||||
maxVol = 31; // this gets feedback fro UI
|
maxVol = 31; // this gets feedback fro UI
|
||||||
binNum = 8; // this gets feedback fro UI
|
binNum = 8; // this gets feedback fro UI
|
||||||
volumeRaw = volumeSmth;
|
volumeRaw = volumeSmth;
|
||||||
my_magnitude = 10000.0f / 8.0f; //no idea if 10000 is a good value for FFT_Magnitude ???
|
my_magnitude = 10000.0 / 8.0f; //no idea if 10000 is a good value for FFT_Magnitude ???
|
||||||
if (volumeSmth < 1 ) my_magnitude = 0.001f; // noise gate closed - mute
|
if (volumeSmth < 1 ) my_magnitude = 0.001f; // noise gate closed - mute
|
||||||
|
|
||||||
return um_data;
|
return um_data;
|
||||||
@ -572,4 +559,4 @@ void enumerateLedmaps() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -195,15 +195,12 @@ void WLED::loop()
|
|||||||
|
|
||||||
#if WLED_WATCHDOG_TIMEOUT > 0
|
#if WLED_WATCHDOG_TIMEOUT > 0
|
||||||
// we finished our mainloop, reset the watchdog timer
|
// we finished our mainloop, reset the watchdog timer
|
||||||
static unsigned long lastWDTFeed = 0;
|
if (!strip.isUpdating())
|
||||||
if (!strip.isUpdating() || millis() - lastWDTFeed > (WLED_WATCHDOG_TIMEOUT*500)) {
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
#else
|
#else
|
||||||
ESP.wdtFeed();
|
ESP.wdtFeed();
|
||||||
#endif
|
#endif
|
||||||
lastWDTFeed = millis();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (doReboot && (!doInitBusses || !doSerializeConfig)) // if busses have to be inited & saved, wait until next iteration
|
if (doReboot && (!doInitBusses || !doSerializeConfig)) // if busses have to be inited & saved, wait until next iteration
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2310130
|
#define VERSION 2308110
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
@ -429,18 +429,12 @@ WLED_GLOBAL uint16_t pollReplyCount _INIT(0); // count numbe
|
|||||||
// mqtt
|
// mqtt
|
||||||
WLED_GLOBAL unsigned long lastMqttReconnectAttempt _INIT(0); // used for other periodic tasks too
|
WLED_GLOBAL unsigned long lastMqttReconnectAttempt _INIT(0); // used for other periodic tasks too
|
||||||
#ifndef WLED_DISABLE_MQTT
|
#ifndef WLED_DISABLE_MQTT
|
||||||
#ifndef MQTT_MAX_TOPIC_LEN
|
|
||||||
#define MQTT_MAX_TOPIC_LEN 32
|
|
||||||
#endif
|
|
||||||
#ifndef MQTT_MAX_SERVER_LEN
|
|
||||||
#define MQTT_MAX_SERVER_LEN 32
|
|
||||||
#endif
|
|
||||||
WLED_GLOBAL AsyncMqttClient *mqtt _INIT(NULL);
|
WLED_GLOBAL AsyncMqttClient *mqtt _INIT(NULL);
|
||||||
WLED_GLOBAL bool mqttEnabled _INIT(false);
|
WLED_GLOBAL bool mqttEnabled _INIT(false);
|
||||||
WLED_GLOBAL char mqttStatusTopic[40] _INIT(""); // this must be global because of async handlers
|
WLED_GLOBAL char mqttStatusTopic[40] _INIT(""); // this must be global because of async handlers
|
||||||
WLED_GLOBAL char mqttDeviceTopic[MQTT_MAX_TOPIC_LEN+1] _INIT(""); // main MQTT topic (individual per device, default is wled/mac)
|
WLED_GLOBAL char mqttDeviceTopic[33] _INIT(""); // main MQTT topic (individual per device, default is wled/mac)
|
||||||
WLED_GLOBAL char mqttGroupTopic[MQTT_MAX_TOPIC_LEN+1] _INIT("wled/all"); // second MQTT topic (for example to group devices)
|
WLED_GLOBAL char mqttGroupTopic[33] _INIT("wled/all"); // second MQTT topic (for example to group devices)
|
||||||
WLED_GLOBAL char mqttServer[MQTT_MAX_SERVER_LEN+1] _INIT(""); // both domains and IPs should work (no SSL)
|
WLED_GLOBAL char mqttServer[33] _INIT(""); // both domains and IPs should work (no SSL)
|
||||||
WLED_GLOBAL char mqttUser[41] _INIT(""); // optional: username for MQTT auth
|
WLED_GLOBAL char mqttUser[41] _INIT(""); // optional: username for MQTT auth
|
||||||
WLED_GLOBAL char mqttPass[65] _INIT(""); // optional: password for MQTT auth
|
WLED_GLOBAL char mqttPass[65] _INIT(""); // optional: password for MQTT auth
|
||||||
WLED_GLOBAL char mqttClientID[41] _INIT(""); // override the client ID
|
WLED_GLOBAL char mqttClientID[41] _INIT(""); // override the client ID
|
||||||
@ -645,13 +639,14 @@ WLED_GLOBAL DNSServer dnsServer;
|
|||||||
// network time
|
// network time
|
||||||
WLED_GLOBAL bool ntpConnected _INIT(false);
|
WLED_GLOBAL bool ntpConnected _INIT(false);
|
||||||
WLED_GLOBAL time_t localTime _INIT(0);
|
WLED_GLOBAL time_t localTime _INIT(0);
|
||||||
|
WLED_GLOBAL uint32_t ntpSyncInterval _INIT(43200U);
|
||||||
WLED_GLOBAL unsigned long ntpLastSyncTime _INIT(999000000L);
|
WLED_GLOBAL unsigned long ntpLastSyncTime _INIT(999000000L);
|
||||||
WLED_GLOBAL unsigned long ntpPacketSentTime _INIT(999000000L);
|
WLED_GLOBAL unsigned long ntpPacketSentTime _INIT(999000000L);
|
||||||
WLED_GLOBAL IPAddress ntpServerIP;
|
WLED_GLOBAL IPAddress ntpServerIP;
|
||||||
WLED_GLOBAL uint16_t ntpLocalPort _INIT(2390);
|
WLED_GLOBAL uint16_t ntpLocalPort _INIT(2390);
|
||||||
WLED_GLOBAL uint16_t rolloverMillis _INIT(0);
|
WLED_GLOBAL uint16_t rolloverMillis _INIT(0);
|
||||||
WLED_GLOBAL float longitude _INIT(0.0);
|
WLED_GLOBAL float longitude _INIT(0.0f);
|
||||||
WLED_GLOBAL float latitude _INIT(0.0);
|
WLED_GLOBAL float latitude _INIT(0.0f);
|
||||||
WLED_GLOBAL time_t sunrise _INIT(0);
|
WLED_GLOBAL time_t sunrise _INIT(0);
|
||||||
WLED_GLOBAL time_t sunset _INIT(0);
|
WLED_GLOBAL time_t sunset _INIT(0);
|
||||||
WLED_GLOBAL Toki toki _INIT(Toki());
|
WLED_GLOBAL Toki toki _INIT(Toki());
|
||||||
|
@ -41,7 +41,7 @@ float sin_t(float x) {
|
|||||||
|
|
||||||
float tan_t(float x) {
|
float tan_t(float x) {
|
||||||
float c = cos_t(x);
|
float c = cos_t(x);
|
||||||
if (c==0.0f) return 0;
|
if (c==0.0) return 0;
|
||||||
float res = sin_t(x) / c;
|
float res = sin_t(x) / c;
|
||||||
#ifdef WLED_DEBUG_MATH
|
#ifdef WLED_DEBUG_MATH
|
||||||
Serial.printf("tan: %f,%f,%f,(%f)\n",x,res,tan(x),res-tan(x));
|
Serial.printf("tan: %f,%f,%f,(%f)\n",x,res,tan(x),res-tan(x));
|
||||||
@ -54,14 +54,14 @@ float tan_t(float x) {
|
|||||||
float acos_t(float x) {
|
float acos_t(float x) {
|
||||||
float negate = float(x < 0);
|
float negate = float(x < 0);
|
||||||
float xabs = std::abs(x);
|
float xabs = std::abs(x);
|
||||||
float ret = -0.0187293f;
|
float ret = -0.0187293;
|
||||||
ret = ret * xabs;
|
ret = ret * xabs;
|
||||||
ret = ret + 0.0742610f;
|
ret = ret + 0.0742610;
|
||||||
ret = ret * xabs;
|
ret = ret * xabs;
|
||||||
ret = ret - 0.2121144f;
|
ret = ret - 0.2121144;
|
||||||
ret = ret * xabs;
|
ret = ret * xabs;
|
||||||
ret = ret + HALF_PI;
|
ret = ret + HALF_PI;
|
||||||
ret = ret * sqrt(1.0f-xabs);
|
ret = ret * sqrt(1.0-xabs);
|
||||||
ret = ret - 2 * negate * ret;
|
ret = ret - 2 * negate * ret;
|
||||||
float res = negate * PI + ret;
|
float res = negate * PI + ret;
|
||||||
#ifdef WLED_DEBUG_MATH
|
#ifdef WLED_DEBUG_MATH
|
||||||
|
@ -478,7 +478,6 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
|
|
||||||
if (subPage == SUBPAGE_SYNC)
|
if (subPage == SUBPAGE_SYNC)
|
||||||
{
|
{
|
||||||
char nS[32];
|
|
||||||
sappend('v',SET_F("UP"),udpPort);
|
sappend('v',SET_F("UP"),udpPort);
|
||||||
sappend('v',SET_F("U2"),udpPort2);
|
sappend('v',SET_F("U2"),udpPort2);
|
||||||
sappend('v',SET_F("GS"),syncGroups);
|
sappend('v',SET_F("GS"),syncGroups);
|
||||||
@ -535,9 +534,6 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
sappends('s',SET_F("MG"),mqttGroupTopic);
|
sappends('s',SET_F("MG"),mqttGroupTopic);
|
||||||
sappend('c',SET_F("BM"),buttonPublishMqtt);
|
sappend('c',SET_F("BM"),buttonPublishMqtt);
|
||||||
sappend('c',SET_F("RT"),retainMqttMsg);
|
sappend('c',SET_F("RT"),retainMqttMsg);
|
||||||
oappend(SET_F("d.Sf.MD.maxlength=")); oappend(itoa(MQTT_MAX_TOPIC_LEN,nS,10)); oappend(SET_F(";"));
|
|
||||||
oappend(SET_F("d.Sf.MG.maxlength=")); oappend(itoa(MQTT_MAX_TOPIC_LEN,nS,10)); oappend(SET_F(";"));
|
|
||||||
oappend(SET_F("d.Sf.MS.maxlength=")); oappend(itoa(MQTT_MAX_SERVER_LEN,nS,10)); oappend(SET_F(";"));
|
|
||||||
#else
|
#else
|
||||||
oappend(SET_F("toggle('MQTT');")); // hide MQTT settings
|
oappend(SET_F("toggle('MQTT');")); // hide MQTT settings
|
||||||
#endif
|
#endif
|
||||||
@ -578,6 +574,15 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
sappend('c',SET_F("NT"),ntpEnabled);
|
sappend('c',SET_F("NT"),ntpEnabled);
|
||||||
sappends('s',SET_F("NS"),ntpServerName);
|
sappends('s',SET_F("NS"),ntpServerName);
|
||||||
sappend('c',SET_F("CF"),!useAMPM);
|
sappend('c',SET_F("CF"),!useAMPM);
|
||||||
|
int syncIntervalIndex;
|
||||||
|
switch (ntpSyncInterval) {
|
||||||
|
case 86400: syncIntervalIndex = 0; break;
|
||||||
|
case 21600: syncIntervalIndex = 2; break;
|
||||||
|
case 14400: syncIntervalIndex = 3; break;
|
||||||
|
case 10800: syncIntervalIndex = 4; break;
|
||||||
|
default : syncIntervalIndex = 1; break;
|
||||||
|
}
|
||||||
|
sappend('i',SET_F("NP"),syncIntervalIndex);
|
||||||
sappend('i',SET_F("TZ"),currentTimezone);
|
sappend('i',SET_F("TZ"),currentTimezone);
|
||||||
sappend('v',SET_F("UO"),utcOffsetSecs);
|
sappend('v',SET_F("UO"),utcOffsetSecs);
|
||||||
char tm[32];
|
char tm[32];
|
||||||
@ -587,7 +592,7 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
sappends('s',SET_F("LT"),tm);
|
sappends('s',SET_F("LT"),tm);
|
||||||
getTimeString(tm);
|
getTimeString(tm);
|
||||||
sappends('m',SET_F("(\"times\")[0]"),tm);
|
sappends('m',SET_F("(\"times\")[0]"),tm);
|
||||||
if ((int)(longitude*10.0f) || (int)(latitude*10.0f)) {
|
if ((int)(longitude*10.) || (int)(latitude*10.)) {
|
||||||
sprintf_P(tm, PSTR("Sunrise: %02d:%02d Sunset: %02d:%02d"), hour(sunrise), minute(sunrise), hour(sunset), minute(sunset));
|
sprintf_P(tm, PSTR("Sunrise: %02d:%02d Sunset: %02d:%02d"), hour(sunrise), minute(sunrise), hour(sunset), minute(sunset));
|
||||||
sappends('m',SET_F("(\"times\")[1]"),tm);
|
sappends('m',SET_F("(\"times\")[1]"),tm);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user