Merge remote-tracking branch 'upstream/mdev' into mdev
This commit is contained in:
35
.github/workflows/wled-ci.yml
vendored
35
.github/workflows/wled-ci.yml
vendored
@@ -8,15 +8,15 @@ jobs:
|
|||||||
name: Gather Environments
|
name: Gather Environments
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Cache pip
|
- name: Cache pip
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/pip
|
path: ~/.cache/pip
|
||||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-pip-
|
${{ runner.os }}-pip-
|
||||||
- uses: actions/setup-python@v4
|
- uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.9'
|
python-version: '3.9'
|
||||||
- name: Install PlatformIO
|
- name: Install PlatformIO
|
||||||
@@ -38,21 +38,24 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
environment: ${{ fromJSON(needs.get_default_envs.outputs.environments) }}
|
environment: ${{ fromJSON(needs.get_default_envs.outputs.environments) }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Cache pip
|
- name: Cache pip
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/pip
|
path: ~/.cache/pip
|
||||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-pip-
|
${{ runner.os }}-pip-
|
||||||
- name: Cache PlatformIO
|
- name: Cache PlatformIO
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.platformio
|
path: ~/.platformio
|
||||||
key: ${{ runner.os }}-${{ matrix.environment}}-${{ hashFiles('platformio.ini') }}
|
key: ${{ runner.os }}-${{ matrix.environment}}-${{ hashFiles('platformio.ini') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-${{ matrix.environment}}
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.9'
|
python-version: '3.9'
|
||||||
- name: Install PlatformIO
|
- name: Install PlatformIO
|
||||||
@@ -61,16 +64,16 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
WLED_RELEASE: True
|
WLED_RELEASE: True
|
||||||
run: pio run -e ${{ matrix.environment }}
|
run: pio run -e ${{ matrix.environment }}
|
||||||
- uses: actions/upload-artifact@v2
|
- name: Rename Bin
|
||||||
|
run: mv -v .pio/build/${{ matrix.environment }}/firmware.bin firmware-${{ matrix.environment }}.bin
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-${{ matrix.environment }}
|
name: firmware-${{ matrix.environment }}
|
||||||
path: |
|
path: firmware-${{ matrix.environment }}.bin
|
||||||
build_output/firmware/*.bin
|
- uses: actions/upload-artifact@v4
|
||||||
build_output/firmware/*.gz
|
|
||||||
- uses: actions/upload-artifact@v2
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
with:
|
with:
|
||||||
name: firmware-release
|
name: firmware-release-${{ matrix.environment }}
|
||||||
path: build_output/release/*.bin
|
path: build_output/release/*.bin
|
||||||
release:
|
release:
|
||||||
name: Create Release
|
name: Create Release
|
||||||
@@ -78,9 +81,11 @@ jobs:
|
|||||||
needs: [get_default_envs, build]
|
needs: [get_default_envs, build]
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/download-artifact@v2
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-release
|
name: firmware-release-*
|
||||||
|
- name: List Artifacts
|
||||||
|
run: find ./
|
||||||
- name: Create draft release
|
- name: Create draft release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
47
boards/lilygo-t7-s3.json
Normal file
47
boards/lilygo-t7-s3.json
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino":{
|
||||||
|
"ldscript": "esp32s3_out.ld",
|
||||||
|
"memory_type": "qio_opi",
|
||||||
|
"partitions": "default_16MB.csv"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DARDUINO_TTGO_T7_S3",
|
||||||
|
"-DBOARD_HAS_PSRAM",
|
||||||
|
"-DARDUINO_USB_MODE=1"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"hwids": [
|
||||||
|
[
|
||||||
|
"0X303A",
|
||||||
|
"0x1001"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "esp32s3"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"wifi",
|
||||||
|
"bluetooth"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "LILYGO T3-S3",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "16MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 16777216,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 921600
|
||||||
|
},
|
||||||
|
"url": "https://www.aliexpress.us/item/3256804591247074.html",
|
||||||
|
"vendor": "LILYGO"
|
||||||
|
}
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "wled",
|
"name": "wled",
|
||||||
"version": "0.14.1-b32.41",
|
"version": "0.14.1-b32.41.dev",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "wled",
|
"name": "wled",
|
||||||
"version": "0.14.1-b32.41",
|
"version": "0.14.1-b32.41.dev",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clean-css": "^4.2.3",
|
"clean-css": "^4.2.3",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "wled",
|
"name": "wled",
|
||||||
"version": "0.14.1-b32.41",
|
"version": "0.14.1-b32.41.dev",
|
||||||
"description": "Tools for WLED project",
|
"description": "Tools for WLED project",
|
||||||
"main": "tools/cdata.js",
|
"main": "tools/cdata.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
|||||||
156
platformio.ini
156
platformio.ini
@@ -72,6 +72,7 @@ default_envs =
|
|||||||
esp32_pico_4MB_M
|
esp32_pico_4MB_M
|
||||||
esp32_4MB_PSRAM_S
|
esp32_4MB_PSRAM_S
|
||||||
; esp32_4MB_PSRAM_REV3_S ;; experimental, optimized for WROVER-E with "revision3" chip
|
; esp32_4MB_PSRAM_REV3_S ;; experimental, optimized for WROVER-E with "revision3" chip
|
||||||
|
esp32S3_4MB_S
|
||||||
esp32S3_8MB_S ;; experimental, optimized for speed
|
esp32S3_8MB_S ;; experimental, optimized for speed
|
||||||
esp32S3_8MB_M
|
esp32S3_8MB_M
|
||||||
esp32S3_4MB_PSRAM_S ;; for lolin s3 mini, S3 zero, S3 super mini - optimized for speed
|
esp32S3_4MB_PSRAM_S ;; for lolin s3 mini, S3 zero, S3 super mini - optimized for speed
|
||||||
@@ -187,6 +188,7 @@ build_flags =
|
|||||||
-D DECODE_SONY=true
|
-D DECODE_SONY=true
|
||||||
-D DECODE_SAMSUNG=true
|
-D DECODE_SAMSUNG=true
|
||||||
-D DECODE_LG=true
|
-D DECODE_LG=true
|
||||||
|
-D FASTLED_NO_FASTLED
|
||||||
;-Dregister= # remove warnings in C++17 due to use of deprecated register keyword by the FastLED library ;; warning: this breaks framework code on ESP32-C3 and ESP32-S2
|
;-Dregister= # remove warnings in C++17 due to use of deprecated register keyword by the FastLED library ;; warning: this breaks framework code on ESP32-C3 and ESP32-S2
|
||||||
-DWLED_USE_MY_CONFIG
|
-DWLED_USE_MY_CONFIG
|
||||||
; -D USERMOD_SENSORSTOMQTT
|
; -D USERMOD_SENSORSTOMQTT
|
||||||
@@ -240,11 +242,13 @@ upload_speed = 115200
|
|||||||
lib_compat_mode = strict
|
lib_compat_mode = strict
|
||||||
lib_deps =
|
lib_deps =
|
||||||
fastled/FastLED @ 3.6.0
|
fastled/FastLED @ 3.6.0
|
||||||
|
;; fastled/FastLED @ 3.7.1
|
||||||
|
;; https://github.com/softhack007/FastLED.git#ESP32-C6 ;; patched version needed for -C6
|
||||||
IRremoteESP8266 @ 2.8.2
|
IRremoteESP8266 @ 2.8.2
|
||||||
;;makuna/NeoPixelBus @ 2.7.5 ;; WLEDMM will be added in board specific sections
|
;;makuna/NeoPixelBus @ 2.7.5 ;; WLEDMM will be added in board specific sections
|
||||||
;;https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.7
|
;;https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.7
|
||||||
;; https://github.com/lost-hope/ESPAsyncWebServer.git#master ;; WLEDMM to display .log and .wled files in /edit
|
;; https://github.com/lost-hope/ESPAsyncWebServer.git#master ;; WLEDMM to display .log and .wled files in /edit
|
||||||
https://github.com/Aircoookie/ESPAsyncWebServer.git @ 2.2.1 ;; newer with bugfixes and stability improvements
|
https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.2.1 ;; newer with bugfixes and stability improvements
|
||||||
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
|
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
|
||||||
#TFT_eSPI
|
#TFT_eSPI
|
||||||
#For compatible OLED display uncomment following
|
#For compatible OLED display uncomment following
|
||||||
@@ -293,6 +297,37 @@ lib_deps =
|
|||||||
makuna/NeoPixelBus @ 2.7.5
|
makuna/NeoPixelBus @ 2.7.5
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
|
|
||||||
|
;; compatibilty flags - same as 0.14.0 which seems to work better on some 8266 boards. Not using PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48
|
||||||
|
build_flags_compat =
|
||||||
|
-DESP8266
|
||||||
|
-DFP_IN_IROM
|
||||||
|
;;-Wno-deprecated-declarations
|
||||||
|
-Wno-misleading-indentation
|
||||||
|
;;-Wno-attributes ;; silence warnings about unknown attribute 'maybe_unused' in NeoPixelBus
|
||||||
|
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
|
||||||
|
-DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
|
||||||
|
-DVTABLES_IN_FLASH
|
||||||
|
-DMIMETYPE_MINIMAL
|
||||||
|
-DWLED_SAVE_IRAM ;; needed to prevent linker error
|
||||||
|
|
||||||
|
;; this platform version was used for WLED 0.14.0
|
||||||
|
platform_compat = espressif8266@4.2.0
|
||||||
|
platform_packages_compat =
|
||||||
|
platformio/toolchain-xtensa @ ~2.100300.220621 #2.40802.200502
|
||||||
|
platformio/tool-esptool #@ ~1.413.0
|
||||||
|
platformio/tool-esptoolpy #@ ~1.30000.0
|
||||||
|
|
||||||
|
;; experimental - for using older NeoPixelBus 2.7.9
|
||||||
|
lib_deps_compat =
|
||||||
|
ESPAsyncTCP @ 1.2.2
|
||||||
|
ESPAsyncUDP
|
||||||
|
ESP8266PWM
|
||||||
|
fastled/FastLED @ 3.6.0
|
||||||
|
IRremoteESP8266 @ 2.8.2
|
||||||
|
makuna/NeoPixelBus @ 2.7.9
|
||||||
|
https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.2.1
|
||||||
|
|
||||||
|
|
||||||
[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
|
||||||
@@ -1035,8 +1070,9 @@ HUB75_build_flags =
|
|||||||
-D NO_GFX ;; Disable the use of Adafruit_GFX by the HUB75 driver
|
-D NO_GFX ;; Disable the use of Adafruit_GFX by the HUB75 driver
|
||||||
-D NO_FAST_FUNCTIONS ;; If you are not using AdafruitGFX than you probably do not need this either, save memory/code size
|
-D NO_FAST_FUNCTIONS ;; If you are not using AdafruitGFX than you probably do not need this either, save memory/code size
|
||||||
-D NO_CIE1931 ;; Do not use LED brightness compensation described in CIE 1931. We use FastLED dimming already
|
-D NO_CIE1931 ;; Do not use LED brightness compensation described in CIE 1931. We use FastLED dimming already
|
||||||
;; HUB75_lib_deps = https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.10 ;; does not work any more
|
-D S3_LCD_DIV_NUM=20 ;; Attempt to fix wifi performance issue when panel active with S3 chips
|
||||||
HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; something strange is going on here ...
|
-D WLEDMM_SLOWPATH ;; WLEDMM: do not use I2S for driving ws2812 LEDs (HUB75 driver needs I2S#1)
|
||||||
|
HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#aa28e2a9 ;; S3_LCD_DIV_NUM fix
|
||||||
HUB75_lib_ignore = ESP32 HUB75 LED MATRIX PANEL DMA Display ;; to remove the HUB75 lib dependancy (saves a few bytes)
|
HUB75_lib_ignore = ESP32 HUB75 LED MATRIX PANEL DMA Display ;; to remove the HUB75 lib dependancy (saves a few bytes)
|
||||||
|
|
||||||
NetDebug_build_flags =
|
NetDebug_build_flags =
|
||||||
@@ -1599,6 +1635,67 @@ lib_deps = ${esp32_4MB_V4_S_base.esp32_lib_deps}
|
|||||||
lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation
|
lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation
|
||||||
; RAM: [=== ] 28.1% (used 91960 bytes from 327680 bytes)
|
; RAM: [=== ] 28.1% (used 91960 bytes from 327680 bytes)
|
||||||
; Flash: [==========] 97.8% (used 1537777 bytes from 1572864 bytes)
|
; Flash: [==========] 97.8% (used 1537777 bytes from 1572864 bytes)
|
||||||
|
|
||||||
|
;; softhack007: my favourite HUB75 buildenv - fastest possible
|
||||||
|
[env:esp32_4MB_V4_HUB75_forum]
|
||||||
|
extends = esp32_4MB_V4_S_base
|
||||||
|
platform_packages = ${esp32_4MB_V4_S_base.platform_packages}
|
||||||
|
;; toolchain-xtensa-esp32@~11.2 ;; for trying out newer gcc @11.2.0+2022r1 ;; 25fps -> 30fps;; FastLED 3.7.1 required !!
|
||||||
|
|
||||||
|
build_unflags = ${esp32_4MB_V4_S_base.build_unflags}
|
||||||
|
${Speed_Flags.build_unflags} ;; to override -Os
|
||||||
|
;; -D WLED_ENABLE_DMX_INPUT
|
||||||
|
-DARDUINO_EVENT_RUNNING_CORE=1
|
||||||
|
;;-DCORE_DEBUG_LEVEL=0
|
||||||
|
;; -D NDEBUG
|
||||||
|
-D NO_CIE1931 ;; Do use LED brightness compensation described in CIE 1931
|
||||||
|
|
||||||
|
build_flags = ${esp32_4MB_V4_S_base.esp32_build_flags}
|
||||||
|
;; -Wsuggest-attribute=const -Wsuggest-attribute=pure
|
||||||
|
;; -Wmissing-noreturn -Wmissing-return
|
||||||
|
;; -Wall -Wextra
|
||||||
|
-Wno-unused-value -Wno-format -Wno-type-limits
|
||||||
|
-D WLED_RELEASE_NAME=esp32_4MB_V4_HUB75
|
||||||
|
${Speed_Flags.build_flags} ;; -O2 -> optimize for speed instead of size
|
||||||
|
;; -D DEBUG
|
||||||
|
-D WLED_WATCHDOG_TIMEOUT=0 #-D WLED_DISABLE_BROWNOUT_DET
|
||||||
|
-D ARDUINO_USB_CDC_ON_BOOT=0 ; needed for arduino-esp32 >=2.0.4; avoids errors on startup
|
||||||
|
-D WLEDMM_FASTPATH ; WLEDMM experimental option. Reduces audio lag (latency), and allows for faster LED framerates. May break compatibility with previous versions.
|
||||||
|
-D WLED_DISABLE_LOXONE
|
||||||
|
-D WLED_DISABLE_ALEXA
|
||||||
|
-D WLED_DISABLE_HUESYNC
|
||||||
|
-D WLED_DISABLE_MQTT
|
||||||
|
-D WLED_DISABLE_INFRARED
|
||||||
|
-D WLED_DISABLE_ADALIGHT
|
||||||
|
;; -D WLED_DEBUG
|
||||||
|
;; -D SR_DEBUG
|
||||||
|
-D WLED_BOOTUPDELAY=350
|
||||||
|
-D WLED_ENABLE_HUB75MATRIX -DESP32_FORUM_PINOUT
|
||||||
|
;; -D HUB75_NO_DOUBLEBUFFER ;; -D PIXEL_COLOUR_DEPTH_BITS=12
|
||||||
|
${common_mm.animartrix_build_flags}
|
||||||
|
;;-DARDUINO_EVENT_RUNNING_CORE=0 ;; assign Wifi to core0, to have more CPU on core#1 (arduino loop)
|
||||||
|
;;-DARDUINO_RUNNING_CORE=1 ;; should be default, but does not hurt
|
||||||
|
-DCONFIG_MBEDTLS_DYNAMIC_BUFFER=1 ;; optional - seems to move more buffers into PSRAM
|
||||||
|
;; -D CONFIG_ESP32_REV_MIN=3 ;; disables PSRAM bug workarounds in the core, reducing the code size and improving overall performance.
|
||||||
|
-D JSON_BUFFER_SIZE=18432 -D MIN_HEAP_SIZE=6144
|
||||||
|
-D MAX_SEGMENT_DATA=40960 ;; default 32767
|
||||||
|
-D WLEDMM_SAVE_FLASH
|
||||||
|
-D WLED_DISABLE_BROWNOUT_DET
|
||||||
|
;;-DCORE_DEBUG_LEVEL=1
|
||||||
|
;;-D WLED_DISABLE_PARTICLESYSTEM1D
|
||||||
|
;;-D WLED_DISABLE_PARTICLESYSTEM2D
|
||||||
|
;;-D WLED_DISABLE_PARTICLESYSTEM_BUFFER
|
||||||
|
|
||||||
|
lib_deps = ${esp32_4MB_V4_S_base.esp32_lib_deps}
|
||||||
|
${common_mm.animartrix_lib_deps}
|
||||||
|
lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation
|
||||||
|
;; ${common_mm.DMXin_lib_ignore}
|
||||||
|
|
||||||
|
board_build.partitions = ${esp32.big_partitions}
|
||||||
|
board_build.f_flash = 80000000L ; use full 80MHz speed for flash (default = 40Mhz)
|
||||||
|
board_build.flash_mode = qio ; (dio = dual i/o; more compatible than qio = quad i/o)
|
||||||
|
|
||||||
|
|
||||||
; compiled with ESP-IDF 4.4.1
|
; compiled with ESP-IDF 4.4.1
|
||||||
[env:esp32_4MB_V4_M]
|
[env:esp32_4MB_V4_M]
|
||||||
extends = esp32_4MB_V4_M_base
|
extends = esp32_4MB_V4_M_base
|
||||||
@@ -1785,6 +1882,32 @@ lib_deps = ${esp32_4MB_V4_M_base.esp32_lib_deps}
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# esp32-S3 environments
|
# esp32-S3 environments
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
[env:esp32S3_4MB_S] ;; Use for HD-WF2
|
||||||
|
extends = esp32_4MB_V4_M_base
|
||||||
|
board = esp32-s3-devkitc-1
|
||||||
|
build_unflags =
|
||||||
|
-D USERMOD_DALLASTEMPERATURE ;; disabled because it hangs during usermod setup on -S3 (autodetect broken?)
|
||||||
|
-D USE_ALT_DISPLAY ;; four line display seems to have problems with I2C - it hangs during usermod setup
|
||||||
|
-D USERMOD_FOUR_LINE_DISPLAY ;; see above
|
||||||
|
-D USERMOD_ROTARY_ENCODER_UI ;; see above
|
||||||
|
-D WLED_ENABLE_DMX ;; disabled because it does not work with ESP-IDF 4.4.x (buggy driver in SparkFunDMX)
|
||||||
|
|
||||||
|
build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-indentation -Wno-format-truncation
|
||||||
|
${common_mm.build_flags_S}
|
||||||
|
${common_mm.HUB75_build_flags}
|
||||||
|
${common_mm.animartrix_build_flags}
|
||||||
|
-D WLED_RELEASE_NAME=esp32S3_4MB_S
|
||||||
|
-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip
|
||||||
|
;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode
|
||||||
|
-D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor)
|
||||||
|
-D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0
|
||||||
|
${common_mm.build_disable_sync_interfaces}
|
||||||
|
-D WLEDMM_FASTPATH ; WLEDMM experimental option. Reduces audio lag (latency), and allows for faster LED framerates. May break compatibility with previous versions.
|
||||||
|
; -D WLED_DEBUG
|
||||||
|
; -D SR_DEBUG
|
||||||
|
lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S}
|
||||||
|
${common_mm.HUB75_lib_deps}
|
||||||
|
${common_mm.animartrix_lib_deps}
|
||||||
|
|
||||||
|
|
||||||
[env:esp32S3_8MB_M]
|
[env:esp32S3_8MB_M]
|
||||||
@@ -1799,6 +1922,8 @@ build_unflags =
|
|||||||
|
|
||||||
build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-indentation -Wno-format-truncation
|
build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-indentation -Wno-format-truncation
|
||||||
${common_mm.build_flags_S} ${common_mm.build_flags_M}
|
${common_mm.build_flags_S} ${common_mm.build_flags_M}
|
||||||
|
${common_mm.HUB75_build_flags}
|
||||||
|
${common_mm.animartrix_build_flags}
|
||||||
; -DBOARD_HAS_PSRAM -D WLED_USE_PSRAM_JSON -D WLED_USE_PSRAM ;; un-comment in case your board supports PSRAM
|
; -DBOARD_HAS_PSRAM -D WLED_USE_PSRAM_JSON -D WLED_USE_PSRAM ;; un-comment in case your board supports PSRAM
|
||||||
-D WLED_RELEASE_NAME=esp32S3_8MB_M
|
-D WLED_RELEASE_NAME=esp32S3_8MB_M
|
||||||
-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip
|
-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip
|
||||||
@@ -1826,6 +1951,9 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden
|
|||||||
; -D SR_DEBUG
|
; -D SR_DEBUG
|
||||||
; -D MIC_LOGGER
|
; -D MIC_LOGGER
|
||||||
lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} ${common_mm.lib_deps_V4_M}
|
lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} ${common_mm.lib_deps_V4_M}
|
||||||
|
${common_mm.HUB75_lib_deps}
|
||||||
|
${common_mm.animartrix_lib_deps}
|
||||||
|
|
||||||
;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation
|
;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation
|
||||||
board_build.partitions = tools/WLED_ESP32_8MB.csv
|
board_build.partitions = tools/WLED_ESP32_8MB.csv
|
||||||
board_build.flash_mode = qio
|
board_build.flash_mode = qio
|
||||||
@@ -1844,6 +1972,7 @@ board_build.flash_mode = qio ;; use "dio" if your board gets unstable with "qio"
|
|||||||
build_unflags = ${env:esp32S3_8MB_M.build_unflags} ;; use the same as "normal" S3 buildenv
|
build_unflags = ${env:esp32S3_8MB_M.build_unflags} ;; use the same as "normal" S3 buildenv
|
||||||
build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-indentation -Wno-format-truncation
|
build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-indentation -Wno-format-truncation
|
||||||
${common_mm.build_flags_S} ${common_mm.build_flags_M}
|
${common_mm.build_flags_S} ${common_mm.build_flags_M}
|
||||||
|
${common_mm.HUB75_build_flags}
|
||||||
-DBOARD_HAS_PSRAM -D WLED_USE_PSRAM_JSON ;; -D WLED_USE_PSRAM ;; your board supports PSRAM
|
-DBOARD_HAS_PSRAM -D WLED_USE_PSRAM_JSON ;; -D WLED_USE_PSRAM ;; your board supports PSRAM
|
||||||
-D WLED_RELEASE_NAME=esp32S3_8MB_PSRAM_M
|
-D WLED_RELEASE_NAME=esp32S3_8MB_PSRAM_M
|
||||||
-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip
|
-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip
|
||||||
@@ -1868,10 +1997,12 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden
|
|||||||
; -D SR_DEBUG
|
; -D SR_DEBUG
|
||||||
; -D MIC_LOGGER
|
; -D MIC_LOGGER
|
||||||
lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} ${common_mm.lib_deps_V4_M}
|
lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} ${common_mm.lib_deps_V4_M}
|
||||||
|
${common_mm.HUB75_lib_deps}
|
||||||
|
|
||||||
;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation
|
;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation
|
||||||
board_build.partitions = tools/WLED_ESP32_8MB.csv
|
board_build.partitions = tools/WLED_ESP32_8MB.csv
|
||||||
; RAM: [==== ] 36.3% (used 118828 bytes from 327680 bytes)
|
; RAM: [== ] 21.1% (used 69156 bytes from 327680 bytes)
|
||||||
; Flash: [======= ] 70.7% (used 1483465 bytes from 2097152 bytes)
|
; Flash: [======== ] 75.9% (used 1591817 bytes from 2097152 bytes)
|
||||||
|
|
||||||
;; MM for ESP32-S3 boards - FASTPATH + optimize for speed
|
;; MM for ESP32-S3 boards - FASTPATH + optimize for speed
|
||||||
[env:esp32S3_8MB_S]
|
[env:esp32S3_8MB_S]
|
||||||
@@ -2106,7 +2237,6 @@ monitor_filters = esp32_exception_decoder
|
|||||||
; RAM: [== ] 21.8% (used 71304 bytes from 327680 bytes)
|
; RAM: [== ] 21.8% (used 71304 bytes from 327680 bytes)
|
||||||
; Flash: [======== ] 84.0% (used 1596970 bytes from 1900544 bytes)
|
; Flash: [======== ] 84.0% (used 1596970 bytes from 1900544 bytes)
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# esp32-C3 environments
|
# esp32-C3 environments
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -2394,12 +2524,17 @@ board_build.partitions = tools/WLED_ESP32_16MB.csv ;; WLED standard for
|
|||||||
;https://www.athom.tech/blank-1/wled-esp32-music-addressable-led-strip-controller
|
;https://www.athom.tech/blank-1/wled-esp32-music-addressable-led-strip-controller
|
||||||
[env:athom_music_esp32_4MB_M]
|
[env:athom_music_esp32_4MB_M]
|
||||||
extends = esp32_4MB_M_base
|
extends = esp32_4MB_M_base
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
-D USERMOD_ARTIFX ;; disabled to save some program space in flash
|
||||||
|
-D USERMOD_DALLASTEMPERATURE ;; disabled - flash space is too tight for this
|
||||||
|
-D USERMOD_ROTARY_ENCODER_UI ;; see above
|
||||||
build_flags = ${esp32_4MB_M_base.build_flags}
|
build_flags = ${esp32_4MB_M_base.build_flags}
|
||||||
${Athom_PDMmic.build_flags}
|
${Athom_PDMmic.build_flags}
|
||||||
-D WLED_AP_SSID_UNIQUE
|
-D WLED_AP_SSID_UNIQUE
|
||||||
-D WLED_RELEASE_NAME=athom_music_esp32_4MB_M
|
-D WLED_RELEASE_NAME=athom_music_esp32_4MB_M
|
||||||
-D ABL_MILLIAMPS_DEFAULT=14500 ; max 15A
|
-D ABL_MILLIAMPS_DEFAULT=14500 ; max 15A
|
||||||
-D WLED_DISABLE_MQTT -D WLED_DISABLE_LOXONE
|
; -D WLED_DISABLE_MQTT
|
||||||
|
-D WLED_DISABLE_LOXONE
|
||||||
-D WLED_DISABLE_ADALIGHT ;to get 4ld working
|
-D WLED_DISABLE_ADALIGHT ;to get 4ld working
|
||||||
-D BTNPIN=0 -D RLYPIN=2 -D IRPIN=25 -D IRTYPE=9 -D LEDPIN=18
|
-D BTNPIN=0 -D RLYPIN=2 -D IRPIN=25 -D IRTYPE=9 -D LEDPIN=18
|
||||||
-D AUDIOPIN=-1
|
-D AUDIOPIN=-1
|
||||||
@@ -2411,8 +2546,9 @@ build_flags = ${esp32_4MB_M_base.build_flags}
|
|||||||
; -D PIR_SENSOR_PIN=-1
|
; -D PIR_SENSOR_PIN=-1
|
||||||
; -D PWM_PIN=-1
|
; -D PWM_PIN=-1
|
||||||
; -D WLED_USE_MY_CONFIG
|
; -D WLED_USE_MY_CONFIG
|
||||||
; RAM: [=== ] 25.9% (used 84948 bytes from 327680 bytes)
|
-D WLEDMM_SAVE_FLASH
|
||||||
; Flash: [==========] 95.9% (used 1509113 bytes from 1572864 bytes)
|
; RAM: [=== ] 26.3% (used 86204 bytes from 327680 bytes)
|
||||||
|
; Flash: [========= ] 93.6% (used 1471681 bytes from 1572864 bytes)
|
||||||
|
|
||||||
;https://shop.myhome-control.de/Elektronik/
|
;https://shop.myhome-control.de/Elektronik/
|
||||||
[env:abc_wled_controller_v43_S]
|
[env:abc_wled_controller_v43_S]
|
||||||
@@ -2532,6 +2668,8 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden
|
|||||||
-D LOLIN_WIFI_FIX ;; try this in case Wifi does not work
|
-D LOLIN_WIFI_FIX ;; try this in case Wifi does not work
|
||||||
-D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0
|
-D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0
|
||||||
-D WLED_USE_PSRAM -DBOARD_HAS_PSRAM ; tells WLED that PSRAM shall be used
|
-D WLED_USE_PSRAM -DBOARD_HAS_PSRAM ; tells WLED that PSRAM shall be used
|
||||||
|
-D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap
|
||||||
|
; -DCONFIG_MBEDTLS_DYNAMIC_BUFFER=1 ;; optional - seems to move more buffers into PSRAM
|
||||||
${common_mm.HUB75_build_flags}
|
${common_mm.HUB75_build_flags}
|
||||||
-D DEFAULT_LED_TYPE=101
|
-D DEFAULT_LED_TYPE=101
|
||||||
lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} ;; ;; do not include ${esp32.lib_depsV4} !!!!
|
lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} ;; ;; do not include ${esp32.lib_depsV4} !!!!
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ static volatile float micReal_max2 = 0.0f; // MicIn data max afte
|
|||||||
// some prototypes, to ensure consistent interfaces
|
// some prototypes, to ensure consistent interfaces
|
||||||
static float mapf(float x, float in_min, float in_max, float out_min, float out_max); // map function for float
|
static float mapf(float x, float in_min, float in_max, float out_min, float out_max); // map function for float
|
||||||
static float fftAddAvg(int from, int to); // average of several FFT result bins
|
static float fftAddAvg(int from, int to); // average of several FFT result bins
|
||||||
void FFTcode(void * parameter); // audio processing task: read samples, run FFT, fill GEQ channels from FFT results
|
void FFTcode(void * parameter) __attribute__((noreturn)); // audio processing task: read samples, run FFT, fill GEQ channels from FFT results
|
||||||
static void runMicFilter(uint16_t numSamples, float *sampleBuffer); // pre-filtering of raw samples (band-pass)
|
static void runMicFilter(uint16_t numSamples, float *sampleBuffer); // pre-filtering of raw samples (band-pass)
|
||||||
static void postProcessFFTResults(bool noiseGateOpen, int numberOfChannels, bool i2sFastpath); // post-processing and post-amp of GEQ channels
|
static void postProcessFFTResults(bool noiseGateOpen, int numberOfChannels, bool i2sFastpath); // post-processing and post-amp of GEQ channels
|
||||||
|
|
||||||
@@ -2352,6 +2352,11 @@ class AudioReactive : public Usermod {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_MoonModules_WLED_) && defined(WLEDMM_FASTPATH)
|
||||||
|
void loop2(void) {
|
||||||
|
loop();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool getUMData(um_data_t **data)
|
bool getUMData(um_data_t **data)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -93,7 +93,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, 6)) // fixed in IDF 4.4.5, however arduino-esp32 2.0.14 did an "I2S rollback" to 4.4.4
|
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)) && (ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(4, 4, 8)) // should be fixed in IDF 4.4.5, however arduino-esp32 2.0.14 - 2.0.17 did an "I2S rollback" to 4.4.4
|
||||||
// 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)
|
||||||
|
|||||||
@@ -303,6 +303,7 @@ class AutoPlaylistUsermod : public Usermod {
|
|||||||
#ifdef USERMOD_AUTO_PLAYLIST_DEBUG
|
#ifdef USERMOD_AUTO_PLAYLIST_DEBUG
|
||||||
USER_PRINTF("AutoPlaylist: disable due to manual change of playlist from %u to %d, preset:%u\n", lastAutoPlaylist, currentPlaylist, currentPreset);
|
USER_PRINTF("AutoPlaylist: disable due to manual change of playlist from %u to %d, preset:%u\n", lastAutoPlaylist, currentPlaylist, currentPreset);
|
||||||
#endif
|
#endif
|
||||||
|
suspendPlaylist();
|
||||||
functionality_enabled = false;
|
functionality_enabled = false;
|
||||||
} else if (currentPlaylist == musicPlaylist) {
|
} else if (currentPlaylist == musicPlaylist) {
|
||||||
#ifdef USERMOD_AUTO_PLAYLIST_DEBUG
|
#ifdef USERMOD_AUTO_PLAYLIST_DEBUG
|
||||||
|
|||||||
368
wled00/FX.cpp
368
wled00/FX.cpp
@@ -37,6 +37,9 @@
|
|||||||
|
|
||||||
#define indexToVStrip(index, stripNr) ((index) | (int((stripNr)+1)<<16))
|
#define indexToVStrip(index, stripNr) ((index) | (int((stripNr)+1)<<16))
|
||||||
|
|
||||||
|
// WLEDMM replace abs8 by abs, as abs8 does not work for numbers >127
|
||||||
|
#define abs8(x) abs(x)
|
||||||
|
|
||||||
// effect utility functions
|
// effect utility functions
|
||||||
static uint8_t sin_gap(uint16_t in) {
|
static uint8_t sin_gap(uint16_t in) {
|
||||||
if (in & 0x100) return 0;
|
if (in & 0x100) return 0;
|
||||||
@@ -98,6 +101,14 @@ static long map2(long x, long in_min, long in_max, long out_min, long out_max)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static um_data_t* getAudioData() {
|
||||||
|
um_data_t *um_data;
|
||||||
|
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||||
|
// add support for no audio
|
||||||
|
um_data = simulateSound(SEGMENT.soundSim);
|
||||||
|
}
|
||||||
|
return um_data;
|
||||||
|
}
|
||||||
// effect functions
|
// effect functions
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1994,11 +2005,7 @@ uint16_t mode_partyjerk() {
|
|||||||
* step: pos
|
* step: pos
|
||||||
*/
|
*/
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float volumeSmth = *(float*) um_data->u_data[0];
|
float volumeSmth = *(float*) um_data->u_data[0];
|
||||||
|
|
||||||
SEGENV.aux0++;
|
SEGENV.aux0++;
|
||||||
@@ -2148,7 +2155,7 @@ uint16_t mode_fire_2012() {
|
|||||||
|
|
||||||
// Step 4. Map from heat cells to LED colors
|
// Step 4. Map from heat cells to LED colors
|
||||||
for (int j = 0; j < SEGLEN; j++) {
|
for (int j = 0; j < SEGLEN; j++) {
|
||||||
SEGMENT.setPixelColor(indexToVStrip(j, stripNr), ColorFromPalette(SEGPALETTE, min(heat[j],byte(240)), 255, NOBLEND));
|
SEGMENT.setPixelColor(indexToVStrip(j, stripNr), ColorFromPalette(SEGPALETTE, min(heat[j], byte(240)), 255, NOBLEND));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -2156,14 +2163,19 @@ uint16_t mode_fire_2012() {
|
|||||||
for (int stripNr=0; stripNr<strips; stripNr++)
|
for (int stripNr=0; stripNr<strips; stripNr++)
|
||||||
virtualStrip::runStrip(stripNr, &heat[stripNr * SEGLEN], it);
|
virtualStrip::runStrip(stripNr, &heat[stripNr * SEGLEN], it);
|
||||||
|
|
||||||
if (SEGMENT.is2D()) SEGMENT.blur(32);
|
if (SEGMENT.is2D()) {
|
||||||
|
uint8_t blurAmount = SEGMENT.custom2 >> 2;
|
||||||
|
if (blurAmount > 48) blurAmount += blurAmount-48; // extra blur when slider > 192 (bush burn)
|
||||||
|
if (blurAmount < 16) SEGMENT.blurCols(SEGMENT.custom2 >> 1); // no side-burn when slider < 64 (faster)
|
||||||
|
else SEGMENT.blur(blurAmount);
|
||||||
|
}
|
||||||
|
|
||||||
if (it != SEGENV.step)
|
if (it != SEGENV.step)
|
||||||
SEGENV.step = it;
|
SEGENV.step = it;
|
||||||
|
|
||||||
return FRAMETIME;
|
return FRAMETIME;
|
||||||
}
|
}
|
||||||
static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate,,,Boost;;!;1.5d;sx=64,ix=160,m12=1"; // bars WLEDMM 1.5d,
|
static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate,,2D Blur,Boost;;!;1.5d;sx=64,ix=160,c2=128,m12=1"; // bars WLEDMM 1.5d,
|
||||||
|
|
||||||
|
|
||||||
// ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb
|
// ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb
|
||||||
@@ -4922,17 +4934,18 @@ uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulma
|
|||||||
}
|
}
|
||||||
|
|
||||||
SEGMENT.fadeToBlackBy(16 + (SEGMENT.speed>>3)); // create fading trails
|
SEGMENT.fadeToBlackBy(16 + (SEGMENT.speed>>3)); // create fading trails
|
||||||
unsigned long t = strip.now/128; // timebase
|
const unsigned long ratio = 128; // rotation speed
|
||||||
|
unsigned long t = strip.now; // timebase
|
||||||
// outer stars
|
// outer stars
|
||||||
for (size_t i = 0; i < 8; i++) {
|
for (unsigned i = 0; i < 8; i++) {
|
||||||
x = beatsin8(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + t * i);
|
x = beatsin8(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + (t * i)/ratio);
|
||||||
y = beatsin8(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + t * i);
|
y = beatsin8(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + (t * i)/ratio);
|
||||||
SEGMENT.addPixelColorXY(x, y, CHSV(i*32, 255, 255));
|
SEGMENT.addPixelColorXY(x, y, CHSV(i*32, 255, 255));
|
||||||
}
|
}
|
||||||
// inner stars
|
// inner stars
|
||||||
for (size_t i = 0; i < 4; i++) {
|
for (size_t i = 0; i < 4; i++) {
|
||||||
x = beatsin8(SEGMENT.custom2>>3, cols/4, cols - 1 - cols/4, 0, ((i % 2) ? 128 : 0) + t * i);
|
x = beatsin8(SEGMENT.custom2>>3, cols/4, cols - 1 - cols/4, 0, ((i % 2) ? 128 : 0) + (t * i)/ratio);
|
||||||
y = beatsin8(SEGMENT.custom3 , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + t * i);
|
y = beatsin8(SEGMENT.custom3 , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + (t * i)/ratio);
|
||||||
SEGMENT.addPixelColorXY(x, y, CHSV(i*32, 255, 255));
|
SEGMENT.addPixelColorXY(x, y, CHSV(i*32, 255, 255));
|
||||||
}
|
}
|
||||||
// central white dot
|
// central white dot
|
||||||
@@ -4969,8 +4982,8 @@ uint16_t mode_2DColoredBursts() { // By: ldirko https://editor.so
|
|||||||
SEGMENT.fadeToBlackBy(40);
|
SEGMENT.fadeToBlackBy(40);
|
||||||
for (size_t i = 0; i < numLines; i++) {
|
for (size_t i = 0; i < numLines; i++) {
|
||||||
byte x1 = beatsin8(2 + SEGMENT.speed/16, 0, (cols - 1));
|
byte x1 = beatsin8(2 + SEGMENT.speed/16, 0, (cols - 1));
|
||||||
byte x2 = beatsin8(1 + SEGMENT.speed/16, 0, (cols - 1));
|
byte x2 = beatsin8(1 + SEGMENT.speed/16, 0, (rows - 1));
|
||||||
byte y1 = beatsin8(5 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 24);
|
byte y1 = beatsin8(5 + SEGMENT.speed/16, 0, (cols - 1), 0, i * 24);
|
||||||
byte y2 = beatsin8(3 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 48 + 64);
|
byte y2 = beatsin8(3 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 48 + 64);
|
||||||
CRGB color = ColorFromPalette(SEGPALETTE, i * 255 / numLines + (SEGENV.aux0&0xFF), 255, LINEARBLEND);
|
CRGB color = ColorFromPalette(SEGPALETTE, i * 255 / numLines + (SEGENV.aux0&0xFF), 255, LINEARBLEND);
|
||||||
|
|
||||||
@@ -5054,10 +5067,12 @@ uint16_t mode_2DDNASpiral() { // By: ldirko https://editor.soulma
|
|||||||
if ((i + ms / 8) & 3) {
|
if ((i + ms / 8) & 3) {
|
||||||
// draw a gradient line between x and x1
|
// draw a gradient line between x and x1
|
||||||
x = x / 2; x1 = x1 / 2;
|
x = x / 2; x1 = x1 / 2;
|
||||||
uint8_t steps = abs8(x - x1) + 1;
|
unsigned steps = abs8(x - x1) + 1;
|
||||||
|
bool positive = (x1 >= x); // direction of drawing
|
||||||
for (size_t k = 1; k <= steps; k++) {
|
for (size_t k = 1; k <= steps; k++) {
|
||||||
uint8_t rate = k * 255 / steps;
|
unsigned rate = k * 255 / steps;
|
||||||
uint8_t dx = lerp8by8(x, x1, rate);
|
//unsigned dx = lerp8by8(x, x1, rate);
|
||||||
|
unsigned dx = positive? (x + k-1) : (x - k+1); // behaves the same as "lerp8by8" but does not create holes
|
||||||
//SEGMENT.setPixelColorXY(dx, i, ColorFromPalette(SEGPALETTE, hue, 255, LINEARBLEND).nscale8_video(rate));
|
//SEGMENT.setPixelColorXY(dx, i, ColorFromPalette(SEGPALETTE, hue, 255, LINEARBLEND).nscale8_video(rate));
|
||||||
SEGMENT.addPixelColorXY(dx, i, ColorFromPalette(SEGPALETTE, hue, 255, LINEARBLEND)); // use setPixelColorXY for different look
|
SEGMENT.addPixelColorXY(dx, i, ColorFromPalette(SEGPALETTE, hue, 255, LINEARBLEND)); // use setPixelColorXY for different look
|
||||||
SEGMENT.fadePixelColorXY(dx, i, rate);
|
SEGMENT.fadePixelColorXY(dx, i, rate);
|
||||||
@@ -5364,7 +5379,7 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https:
|
|||||||
SEGENV.step = strip.now;
|
SEGENV.step = strip.now;
|
||||||
return FRAMETIME;
|
return FRAMETIME;
|
||||||
} // mode_2Dgameoflife()
|
} // mode_2Dgameoflife()
|
||||||
static const char _data_FX_MODE_2DGAMEOFLIFE[] PROGMEM = "Game Of Life@!,Color Mutation ☾,Blur ☾,,,All Colors ☾,Overlay BG ☾,Wrap ☾,;!,!;!;2;sx=56,ix=2,c1=128,o1=0,o2=0,o3=1";
|
static const char _data_FX_MODE_2DGAMEOFLIFE[] PROGMEM = "Game Of Life@!,Color Mutation ☾,Blur ☾,,,All Colors ☾,Overlay BG ☾,Wrap ☾;!,!;!;2;sx=56,ix=2,c1=128,o1=0,o2=0,o3=1";
|
||||||
|
|
||||||
/////////////////////////
|
/////////////////////////
|
||||||
// 2D SnowFall //
|
// 2D SnowFall //
|
||||||
@@ -5637,7 +5652,10 @@ uint16_t mode_2DLissajous(void) { // By: Andrew Tuline
|
|||||||
float ylocn = float(cos8(phase/2 + i*2)) / 255.0f;
|
float ylocn = float(cos8(phase/2 + i*2)) / 255.0f;
|
||||||
//SEGMENT.setPixelColorXY(xlocn, ylocn, SEGMENT.color_from_palette(strip.now/100+i, false, PALETTE_SOLID_WRAP, 0)); // draw pixel with anti-aliasing
|
//SEGMENT.setPixelColorXY(xlocn, ylocn, SEGMENT.color_from_palette(strip.now/100+i, false, PALETTE_SOLID_WRAP, 0)); // draw pixel with anti-aliasing
|
||||||
unsigned palIndex = (256*ylocn) + phase/2 + (i* SEGMENT.speed)/64;
|
unsigned palIndex = (256*ylocn) + phase/2 + (i* SEGMENT.speed)/64;
|
||||||
SEGMENT.setPixelColorXY(xlocn, ylocn, SEGMENT.color_from_palette(palIndex, false, PALETTE_SOLID_WRAP, 0)); // draw pixel with anti-aliasing - color follows rotation
|
//SEGMENT.setPixelColorXY(xlocn, ylocn, SEGMENT.color_from_palette(palIndex, false, PALETTE_SOLID_WRAP, 0)); // draw pixel with anti-aliasing - color follows rotation
|
||||||
|
// WLEDMM wu_pixel is 50% faster, and still lokks better
|
||||||
|
SEGMENT.wu_pixel(uint32_t(xlocn * (cols <<8)), uint32_t(ylocn * (rows <<8)),
|
||||||
|
CRGB(SEGMENT.color_from_palette(palIndex, false, PALETTE_SOLID_WRAP, 0)));
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
for (int i=0; i < 256; i ++) {
|
for (int i=0; i < 256; i ++) {
|
||||||
@@ -6381,6 +6399,10 @@ uint16_t mode_2Dfloatingblobs(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SEGMENT.fadeToBlackBy(20);
|
SEGMENT.fadeToBlackBy(20);
|
||||||
|
bool drawAA = (SEGMENT.custom1 > 0) && (SEGMENT.custom1 < 6); //WLEDMM
|
||||||
|
const uint16_t minDim = min(cols, rows); // WLEDMM use smaller dimension to find good blob size
|
||||||
|
float max_grow = min(minDim/4.f,2.f);
|
||||||
|
if (minDim>=24) max_grow =(minDim/8.0f); // WLEDMM allow bigger blobs
|
||||||
|
|
||||||
// Bounce balls around
|
// Bounce balls around
|
||||||
for (size_t i = 0; i < Amount; i++) {
|
for (size_t i = 0; i < Amount; i++) {
|
||||||
@@ -6389,18 +6411,18 @@ uint16_t mode_2Dfloatingblobs(void) {
|
|||||||
if (blob->grow[i]) {
|
if (blob->grow[i]) {
|
||||||
// enlarge radius until it is >= 4
|
// enlarge radius until it is >= 4
|
||||||
blob->r[i] += (fabsf(blob->sX[i]) > fabsf(blob->sY[i]) ? fabsf(blob->sX[i]) : fabsf(blob->sY[i])) * 0.05f;
|
blob->r[i] += (fabsf(blob->sX[i]) > fabsf(blob->sY[i]) ? fabsf(blob->sX[i]) : fabsf(blob->sY[i])) * 0.05f;
|
||||||
if (blob->r[i] >= min(cols/4.f,2.f)) {
|
if (blob->r[i] >= max_grow) {
|
||||||
blob->grow[i] = false;
|
blob->grow[i] = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// reduce radius until it is < 1
|
// reduce radius until it is < 1
|
||||||
blob->r[i] -= (fabsf(blob->sX[i]) > fabsf(blob->sY[i]) ? fabsf(blob->sX[i]) : fabsf(blob->sY[i])) * 0.05f;
|
blob->r[i] -= (fabsf(blob->sX[i]) > fabsf(blob->sY[i]) ? fabsf(blob->sX[i]) : fabsf(blob->sY[i])) * 0.05f;
|
||||||
if (blob->r[i] < 1.f) {
|
if (blob->r[i] < 0.8f) {
|
||||||
blob->grow[i] = true;
|
blob->grow[i] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint32_t c = SEGMENT.color_from_palette(blob->color[i], false, false, 0);
|
uint32_t c = SEGMENT.color_from_palette(blob->color[i], false, false, 0);
|
||||||
if (blob->r[i] > 1.f) SEGMENT.fillCircle(roundf(blob->x[i]), roundf(blob->y[i]), roundf(blob->r[i]), c);
|
if (blob->r[i] > 1.f) SEGMENT.fillCircle(roundf(blob->x[i]), roundf(blob->y[i]), roundf(blob->r[i]), c, drawAA);
|
||||||
else SEGMENT.setPixelColorXY((int)roundf(blob->x[i]), (int)roundf(blob->y[i]), c);
|
else SEGMENT.setPixelColorXY((int)roundf(blob->x[i]), (int)roundf(blob->y[i]), c);
|
||||||
// move x
|
// move x
|
||||||
if (blob->x[i] + blob->r[i] >= cols - 1) blob->x[i] += (blob->sX[i] * ((cols - 1 - blob->x[i]) / blob->r[i] + 0.005f));
|
if (blob->x[i] + blob->r[i] >= cols - 1) blob->x[i] += (blob->sX[i] * ((cols - 1 - blob->x[i]) / blob->r[i] + 0.005f));
|
||||||
@@ -6468,7 +6490,7 @@ uint16_t mode_2Dscrollingtext(void) {
|
|||||||
if (SEGMENT.name) for (size_t i=0,j=0; i<maxLen; i++) if (SEGMENT.name[i]>31 && SEGMENT.name[i]<128) text[j++] = SEGMENT.name[i];
|
if (SEGMENT.name) for (size_t i=0,j=0; i<maxLen; i++) if (SEGMENT.name[i]>31 && SEGMENT.name[i]<128) text[j++] = SEGMENT.name[i];
|
||||||
const bool zero = strchr(text, '0') != nullptr;
|
const bool zero = strchr(text, '0') != nullptr;
|
||||||
|
|
||||||
if (!strlen(text) || !strncmp_P(text,PSTR("#F"),2) || !strncmp_P(text,PSTR("#P"),2) || !strncmp_P(text,PSTR("#DATE"),5) || !strncmp_P(text,PSTR("#DDMM"),5) || !strncmp_P(text,PSTR("#MMDD"),5) || !strncmp_P(text,PSTR("#TIME"),5) || !strncmp_P(text,PSTR("#HH"),3) || !strncmp_P(text,PSTR("#MM"),3)) { // fallback if empty segment name: display date and time
|
if (!strlen(text) || !strncmp_P(text,PSTR("#F"),2) || !strncmp_P(text,PSTR("#P"),2) || !strncmp_P(text,PSTR("#A"),2) || !strncmp_P(text,PSTR("#DATE"),5) || !strncmp_P(text,PSTR("#DDMM"),5) || !strncmp_P(text,PSTR("#MMDD"),5) || !strncmp_P(text,PSTR("#TIME"),5) || !strncmp_P(text,PSTR("#HH"),3) || !strncmp_P(text,PSTR("#MM"),3)) { // fallback if empty segment name: display date and time
|
||||||
char sec[5]= {'\0'};
|
char sec[5]= {'\0'};
|
||||||
byte AmPmHour = hour(localTime);
|
byte AmPmHour = hour(localTime);
|
||||||
boolean isitAM = true;
|
boolean isitAM = true;
|
||||||
@@ -6501,6 +6523,7 @@ uint16_t mode_2Dscrollingtext(void) {
|
|||||||
SEGMENT.blendPixelColorXY(x, y, SEGCOLOR(1), 255 - (SEGMENT.custom1>>1));
|
SEGMENT.blendPixelColorXY(x, y, SEGCOLOR(1), 255 - (SEGMENT.custom1>>1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool drawShadow = (SEGMENT.check2) && (SEGMENT.custom1 == 0);
|
||||||
for (int i = 0; i < numberOfLetters; i++) {
|
for (int i = 0; i < numberOfLetters; i++) {
|
||||||
if (int(cols) - int(SEGENV.aux0) + letterWidth*(i+1) < 0) continue; // don't draw characters off-screen
|
if (int(cols) - int(SEGENV.aux0) + letterWidth*(i+1) < 0) continue; // don't draw characters off-screen
|
||||||
uint32_t col1 = SEGMENT.color_from_palette(SEGENV.aux1, false, PALETTE_SOLID_WRAP, 0);
|
uint32_t col1 = SEGMENT.color_from_palette(SEGENV.aux1, false, PALETTE_SOLID_WRAP, 0);
|
||||||
@@ -6509,7 +6532,7 @@ uint16_t mode_2Dscrollingtext(void) {
|
|||||||
col1 = SEGCOLOR(0);
|
col1 = SEGCOLOR(0);
|
||||||
col2 = SEGCOLOR(2);
|
col2 = SEGCOLOR(2);
|
||||||
}
|
}
|
||||||
SEGMENT.drawCharacter(text[i], int(cols) - int(SEGENV.aux0) + letterWidth*i, yoffset, letterWidth, letterHeight, col1, col2);
|
SEGMENT.drawCharacter(text[i], int(cols) - int(SEGENV.aux0) + letterWidth*i, yoffset, letterWidth, letterHeight, col1, col2, drawShadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FRAMETIME;
|
return FRAMETIME;
|
||||||
@@ -6620,11 +6643,7 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli
|
|||||||
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||||
Ripple* ripples = reinterpret_cast<Ripple*>(SEGENV.data);
|
Ripple* ripples = reinterpret_cast<Ripple*>(SEGENV.data);
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
uint8_t samplePeak = *(uint8_t*)um_data->u_data[3];
|
uint8_t samplePeak = *(uint8_t*)um_data->u_data[3];
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
float FFT_MajorPeak = *(float*) um_data->u_data[4];
|
float FFT_MajorPeak = *(float*) um_data->u_data[4];
|
||||||
@@ -6720,11 +6739,7 @@ uint16_t mode_2DSwirl(void) {
|
|||||||
uint8_t nj = (cols - 1) - j;
|
uint8_t nj = (cols - 1) - j;
|
||||||
uint16_t ms = strip.now;
|
uint16_t ms = strip.now;
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float volumeSmth = *(float*) um_data->u_data[0]; //ewowi: use instead of sampleAvg???
|
float volumeSmth = *(float*) um_data->u_data[0]; //ewowi: use instead of sampleAvg???
|
||||||
int16_t volumeRaw = *(int16_t*) um_data->u_data[1];
|
int16_t volumeRaw = *(int16_t*) um_data->u_data[1];
|
||||||
|
|
||||||
@@ -6757,11 +6772,7 @@ uint16_t mode_2DWaverly(void) {
|
|||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float volumeSmth = *(float*) um_data->u_data[0];
|
float volumeSmth = *(float*) um_data->u_data[0];
|
||||||
float soundPressure = *(float*) um_data->u_data[9];
|
float soundPressure = *(float*) um_data->u_data[9];
|
||||||
float agcSensitivity= *(float*) um_data->u_data[10];
|
float agcSensitivity= *(float*) um_data->u_data[10];
|
||||||
@@ -6773,20 +6784,26 @@ uint16_t mode_2DWaverly(void) {
|
|||||||
|
|
||||||
long t = strip.now / 2;
|
long t = strip.now / 2;
|
||||||
for (int i = 0; i < cols; i++) {
|
for (int i = 0; i < cols; i++) {
|
||||||
uint16_t thisVal = volumeSmth*SEGMENT.intensity/64 * inoise8(i * 45 , t , t)/64; // WLEDMM back to SR code
|
//uint16_t thisVal = volumeSmth*SEGMENT.intensity/64 * inoise8(i * 45 , t , t)/64; // WLEDMM back to SR code
|
||||||
uint16_t thisMax = map(thisVal, 0, 512, 0, rows);
|
unsigned thisVal = unsigned(volumeSmth*SEGMENT.intensity) * inoise8(i * 45 , t , t) / (64*64); // WLEDMM same result but more accurate
|
||||||
|
|
||||||
for (int j = 0; j < thisMax; j++) {
|
//int thisMax = map(thisVal, 0, 512, 0, rows);
|
||||||
|
int thisMax = (thisVal * rows) / 512; // WLEDMM same result, just faster
|
||||||
|
int thisMax2 = min(int(rows), thisMax); // WLEDMM limit height to visible are
|
||||||
|
|
||||||
|
for (int j = 0; j < thisMax2; j++) {
|
||||||
|
//int jmap = map(j, 0, thisMax, 250, 0);
|
||||||
|
int jmap = 250 - ((j * 250) / thisMax); // WLEDMM same result, just faster
|
||||||
if (!SEGENV.check1)
|
if (!SEGENV.check1)
|
||||||
SEGMENT.addPixelColorXY(i, j, ColorFromPalette(SEGPALETTE, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND));
|
SEGMENT.addPixelColorXY(i, j, ColorFromPalette(SEGPALETTE, jmap, 255, LINEARBLEND));
|
||||||
SEGMENT.addPixelColorXY((cols - 1) - i, (rows - 1) - j, ColorFromPalette(SEGPALETTE, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND));
|
SEGMENT.addPixelColorXY((cols - 1) - i, (rows - 1) - j, ColorFromPalette(SEGPALETTE, jmap, 255, LINEARBLEND));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SEGMENT.blur(16);
|
SEGMENT.blur(16);
|
||||||
|
|
||||||
return FRAMETIME;
|
return FRAMETIME;
|
||||||
} // mode_2DWaverly()
|
} // mode_2DWaverly()
|
||||||
static const char _data_FX_MODE_2DWAVERLY[] PROGMEM = "Waverly ☾@Amplification,Sensitivity,,,,No Clouds,Sound Pressure,AGC debug;;!;2v;ix=64,si=0"; // Beatsin
|
static const char _data_FX_MODE_2DWAVERLY[] PROGMEM = "Waverly ☾@Fade Rate,Amplification,,,,No Clouds,Sound Pressure,AGC debug;;!;2v;ix=64,si=0"; // Beatsin
|
||||||
|
|
||||||
#endif // WLED_DISABLE_2D
|
#endif // WLED_DISABLE_2D
|
||||||
|
|
||||||
@@ -6809,11 +6826,7 @@ uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline.
|
|||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float volumeSmth = *(float*) um_data->u_data[0];
|
float volumeSmth = *(float*) um_data->u_data[0];
|
||||||
|
|
||||||
//SEGMENT.fade_out(240);
|
//SEGMENT.fade_out(240);
|
||||||
@@ -6861,11 +6874,7 @@ uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew
|
|||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float volumeSmth = *(float*) um_data->u_data[0];
|
float volumeSmth = *(float*) um_data->u_data[0];
|
||||||
|
|
||||||
// printUmData();
|
// printUmData();
|
||||||
@@ -6912,11 +6921,7 @@ uint16_t mode_gravimeter(void) { // Gravmeter. By Andrew Tuline.
|
|||||||
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||||
Gravity* gravcen = reinterpret_cast<Gravity*>(SEGENV.data);
|
Gravity* gravcen = reinterpret_cast<Gravity*>(SEGENV.data);
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float volumeSmth = *(float*) um_data->u_data[0];
|
float volumeSmth = *(float*) um_data->u_data[0];
|
||||||
// int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; //WLEDMM: this variable not used here
|
// int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; //WLEDMM: this variable not used here
|
||||||
float soundPressure = *(float*) um_data->u_data[9];
|
float soundPressure = *(float*) um_data->u_data[9];
|
||||||
@@ -6989,11 +6994,7 @@ static const char _data_FX_MODE_GRAVIMETER[] PROGMEM = "Gravimeter ☾@Rate of f
|
|||||||
// * JUGGLES //
|
// * JUGGLES //
|
||||||
//////////////////////
|
//////////////////////
|
||||||
uint16_t mode_juggles(void) { // Juggles. By Andrew Tuline.
|
uint16_t mode_juggles(void) { // Juggles. By Andrew Tuline.
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float volumeSmth = *(float*) um_data->u_data[0];
|
float volumeSmth = *(float*) um_data->u_data[0];
|
||||||
if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor()
|
if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor()
|
||||||
|
|
||||||
@@ -7016,11 +7017,7 @@ static const char _data_FX_MODE_JUGGLES[] PROGMEM = "Juggles@!,# of balls;!,!;!;
|
|||||||
uint16_t mode_matripix(void) { // Matripix. By Andrew Tuline. With some enhancements by @softhack007
|
uint16_t mode_matripix(void) { // Matripix. By Andrew Tuline. With some enhancements by @softhack007
|
||||||
// even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment
|
// even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
|
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
|
||||||
float volumeSmth = *(float*) um_data->u_data[0];
|
float volumeSmth = *(float*) um_data->u_data[0];
|
||||||
float soundPressure = *(float*) um_data->u_data[9];
|
float soundPressure = *(float*) um_data->u_data[9];
|
||||||
@@ -7072,11 +7069,7 @@ static const char _data_FX_MODE_MATRIPIX[] PROGMEM = "Matripix ☾@!,Brightness,
|
|||||||
uint16_t mode_midnoise(void) { // Midnoise. By Andrew Tuline.
|
uint16_t mode_midnoise(void) { // Midnoise. By Andrew Tuline.
|
||||||
// Changing xdist to SEGENV.aux0 and ydist to SEGENV.aux1.
|
// Changing xdist to SEGENV.aux0 and ydist to SEGENV.aux1.
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float volumeSmth = *(float*) um_data->u_data[0];
|
float volumeSmth = *(float*) um_data->u_data[0];
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
@@ -7115,11 +7108,7 @@ uint16_t mode_noisefire(void) { // Noisefire. By Andrew Tuline.
|
|||||||
CRGB::DarkOrange, CRGB::DarkOrange, CRGB::Orange, CRGB::Orange,
|
CRGB::DarkOrange, CRGB::DarkOrange, CRGB::Orange, CRGB::Orange,
|
||||||
CRGB::Yellow, CRGB::Orange, CRGB::Yellow, CRGB::Yellow);
|
CRGB::Yellow, CRGB::Orange, CRGB::Yellow, CRGB::Yellow);
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float volumeSmth = *(float*) um_data->u_data[0];
|
float volumeSmth = *(float*) um_data->u_data[0];
|
||||||
|
|
||||||
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
|
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
|
||||||
@@ -7143,11 +7132,7 @@ static const char _data_FX_MODE_NOISEFIRE[] PROGMEM = "Noisefire@!,!;;;01v;m12=2
|
|||||||
///////////////////////
|
///////////////////////
|
||||||
uint16_t mode_noisemeter(void) { // Noisemeter. By Andrew Tuline.
|
uint16_t mode_noisemeter(void) { // Noisemeter. By Andrew Tuline.
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float volumeSmth = *(float*) um_data->u_data[0];
|
float volumeSmth = *(float*) um_data->u_data[0];
|
||||||
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
|
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
|
||||||
if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor()
|
if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor()
|
||||||
@@ -7185,11 +7170,7 @@ uint16_t mode_pixelwave(void) { // Pixelwave. By Andrew Tuline.
|
|||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
|
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
|
||||||
|
|
||||||
uint8_t secondHand = micros()/(256-SEGMENT.speed)/500+1 % 16;
|
uint8_t secondHand = micros()/(256-SEGMENT.speed)/500+1 % 16;
|
||||||
@@ -7223,11 +7204,7 @@ uint16_t mode_plasmoid(void) { // Plasmoid. By Andrew Tuline.
|
|||||||
if (!SEGENV.allocateData(sizeof(plasphase))) return mode_static(); //allocation failed
|
if (!SEGENV.allocateData(sizeof(plasphase))) return mode_static(); //allocation failed
|
||||||
Plasphase* plasmoip = reinterpret_cast<Plasphase*>(SEGENV.data);
|
Plasphase* plasmoip = reinterpret_cast<Plasphase*>(SEGENV.data);
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float volumeSmth = *(float*) um_data->u_data[0];
|
float volumeSmth = *(float*) um_data->u_data[0];
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
@@ -7266,11 +7243,7 @@ uint16_t mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline.
|
|||||||
uint8_t fadeVal = map2(SEGMENT.speed,0,255, 224, 254);
|
uint8_t fadeVal = map2(SEGMENT.speed,0,255, 224, 254);
|
||||||
uint16_t pos = random16(SEGLEN); // Set a random starting position.
|
uint16_t pos = random16(SEGLEN); // Set a random starting position.
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
uint8_t samplePeak = *(uint8_t*)um_data->u_data[3];
|
uint8_t samplePeak = *(uint8_t*)um_data->u_data[3];
|
||||||
uint8_t *maxVol = (uint8_t*)um_data->u_data[6];
|
uint8_t *maxVol = (uint8_t*)um_data->u_data[6];
|
||||||
uint8_t *binNum = (uint8_t*)um_data->u_data[7];
|
uint8_t *binNum = (uint8_t*)um_data->u_data[7];
|
||||||
@@ -7318,11 +7291,7 @@ uint16_t mode_puddles(void) { // Puddles. By Andrew Tuline.
|
|||||||
}
|
}
|
||||||
SEGMENT.fade_out(fadeVal);
|
SEGMENT.fade_out(fadeVal);
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
|
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
|
||||||
|
|
||||||
if (volumeRaw > 1) {
|
if (volumeRaw > 1) {
|
||||||
@@ -7347,10 +7316,7 @@ uint16_t mode_pixels(void) { // Pixels. By Andrew Tuline.
|
|||||||
if (!SEGENV.allocateData(32*sizeof(uint8_t))) return mode_static(); //allocation failed
|
if (!SEGENV.allocateData(32*sizeof(uint8_t))) return mode_static(); //allocation failed
|
||||||
uint8_t *myVals = reinterpret_cast<uint8_t*>(SEGENV.data); // Used to store a pile of samples because WLED frame rate and WLED sample rate are not synchronized. Frame rate is too low.
|
uint8_t *myVals = reinterpret_cast<uint8_t*>(SEGENV.data); // Used to store a pile of samples because WLED frame rate and WLED sample rate are not synchronized. Frame rate is too low.
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float volumeSmth = *(float*) um_data->u_data[0];
|
float volumeSmth = *(float*) um_data->u_data[0];
|
||||||
if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor()
|
if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor()
|
||||||
|
|
||||||
@@ -7380,11 +7346,7 @@ static const char _data_FX_MODE_PIXELS[] PROGMEM = "Pixels@Fade rate,# of pixels
|
|||||||
uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline.
|
uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline.
|
||||||
// even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment
|
// even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
@@ -7414,11 +7376,7 @@ static const char _data_FX_MODE_BLURZ[] PROGMEM = "Blurz@Fade rate,Blur;!,Color
|
|||||||
uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline.
|
uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline.
|
||||||
// Hint: Looks best with segment brightness set to max (use global brightness to reduce brightness)
|
// Hint: Looks best with segment brightness set to max (use global brightness to reduce brightness)
|
||||||
// even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment
|
// even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
||||||
float volumeSmth = *(float*)um_data->u_data[0];
|
float volumeSmth = *(float*)um_data->u_data[0];
|
||||||
|
|
||||||
@@ -7466,11 +7424,7 @@ uint16_t mode_DJLight(void) { // Written by Stefan Petrick, Ad
|
|||||||
// No need to prevent from executing on single led strips, only mid will be set (mid = 0)
|
// No need to prevent from executing on single led strips, only mid will be set (mid = 0)
|
||||||
const int mid = SEGLEN / 2;
|
const int mid = SEGLEN / 2;
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
||||||
float volumeSmth = *(float*)um_data->u_data[0];
|
float volumeSmth = *(float*)um_data->u_data[0];
|
||||||
|
|
||||||
@@ -7536,11 +7490,7 @@ uint16_t mode_freqmap(void) { // Map FFT_MajorPeak to SEGLEN.
|
|||||||
// Start frequency = 60 Hz and log10(60) = 1.78
|
// Start frequency = 60 Hz and log10(60) = 1.78
|
||||||
// End frequency = MAX_FREQUENCY in Hz and lo10(MAX_FREQUENCY) = MAX_FREQ_LOG10
|
// End frequency = MAX_FREQUENCY in Hz and lo10(MAX_FREQUENCY) = MAX_FREQ_LOG10
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float FFT_MajorPeak = *(float*)um_data->u_data[SEGENV.check1 ? 8:4]; // WLEDMM may use FFT_MajorPeakSmth
|
float FFT_MajorPeak = *(float*)um_data->u_data[SEGENV.check1 ? 8:4]; // WLEDMM may use FFT_MajorPeakSmth
|
||||||
float my_magnitude = *(float*)um_data->u_data[5] / 4.0f;
|
float my_magnitude = *(float*)um_data->u_data[5] / 4.0f;
|
||||||
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
|
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
|
||||||
@@ -7581,11 +7531,7 @@ static const char _data_FX_MODE_FREQMAP[] PROGMEM = "Freqmap@Fade rate,Starting
|
|||||||
///////////////////////
|
///////////////////////
|
||||||
uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Pleschung.
|
uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Pleschung.
|
||||||
// No need to prevent from executing on single led strips, we simply change pixel 0 each time and avoid the shift
|
// No need to prevent from executing on single led strips, we simply change pixel 0 each time and avoid the shift
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float FFT_MajorPeak = *(float*)um_data->u_data[4];
|
float FFT_MajorPeak = *(float*)um_data->u_data[4];
|
||||||
float volumeSmth = *(float*)um_data->u_data[0];
|
float volumeSmth = *(float*)um_data->u_data[0];
|
||||||
|
|
||||||
@@ -7622,9 +7568,9 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch
|
|||||||
}
|
}
|
||||||
|
|
||||||
// shift the pixels one pixel up
|
// shift the pixels one pixel up
|
||||||
SEGMENT.setPixelColor(0, color);
|
|
||||||
// if SEGLEN equals 1 this loop won't execute
|
// if SEGLEN equals 1 this loop won't execute
|
||||||
for (int i = SEGLEN - 1; i > 0; i--) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i-1)); //move to the left
|
for (int i = SEGLEN - 1; i > 0; i--) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i-1)); //move to the left
|
||||||
|
SEGMENT.setPixelColor(0, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FRAMETIME;
|
return FRAMETIME;
|
||||||
@@ -7640,11 +7586,7 @@ static const char _data_FX_MODE_FREQMATRIX[] PROGMEM = "Freqmatrix@Speed,Sound e
|
|||||||
// SEGMENT.speed select faderate
|
// SEGMENT.speed select faderate
|
||||||
// SEGMENT.intensity select colour index
|
// SEGMENT.intensity select colour index
|
||||||
uint16_t mode_freqpixels(void) { // Freqpixel. By Andrew Tuline.
|
uint16_t mode_freqpixels(void) { // Freqpixel. By Andrew Tuline.
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float FFT_MajorPeak = *(float*)um_data->u_data[4];
|
float FFT_MajorPeak = *(float*)um_data->u_data[4];
|
||||||
float my_magnitude = *(float*)um_data->u_data[5] / 16.0f;
|
float my_magnitude = *(float*)um_data->u_data[5] / 16.0f;
|
||||||
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
|
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
|
||||||
@@ -7687,11 +7629,7 @@ static const char _data_FX_MODE_FREQPIXELS[] PROGMEM = "Freqpixels@Fade rate,Sta
|
|||||||
// Depending on the music stream you have you might find it useful to change the frequency mapping.
|
// Depending on the music stream you have you might find it useful to change the frequency mapping.
|
||||||
uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschung. With some enhancements by @softhack007
|
uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschung. With some enhancements by @softhack007
|
||||||
// As before, this effect can also work on single pixels, we just lose the shifting effect
|
// As before, this effect can also work on single pixels, we just lose the shifting effect
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float FFT_MajorPeak = *(float*)um_data->u_data[4];
|
float FFT_MajorPeak = *(float*)um_data->u_data[4];
|
||||||
float volumeSmth = *(float*)um_data->u_data[0];
|
float volumeSmth = *(float*)um_data->u_data[0];
|
||||||
|
|
||||||
@@ -7761,11 +7699,7 @@ uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline.
|
|||||||
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||||
Gravity* gravcen = reinterpret_cast<Gravity*>(SEGENV.data);
|
Gravity* gravcen = reinterpret_cast<Gravity*>(SEGENV.data);
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float FFT_MajorPeak = *(float*)um_data->u_data[4];
|
float FFT_MajorPeak = *(float*)um_data->u_data[4];
|
||||||
float volumeSmth = *(float*)um_data->u_data[0];
|
float volumeSmth = *(float*)um_data->u_data[0];
|
||||||
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
|
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
|
||||||
@@ -7814,11 +7748,7 @@ static const char _data_FX_MODE_GRAVFREQ[] PROGMEM = "Gravfreq ☾@Rate of fall,
|
|||||||
// ** Noisemove //
|
// ** Noisemove //
|
||||||
//////////////////////
|
//////////////////////
|
||||||
uint16_t mode_noisemove(void) { // Noisemove. By: Andrew Tuline
|
uint16_t mode_noisemove(void) { // Noisemove. By: Andrew Tuline
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
uint8_t fftResult[NUM_GEQ_CHANNELS] = {0};
|
uint8_t fftResult[NUM_GEQ_CHANNELS] = {0};
|
||||||
if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values
|
if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values
|
||||||
|
|
||||||
@@ -7847,11 +7777,7 @@ static const char _data_FX_MODE_NOISEMOVE[] PROGMEM = "Noisemove@Speed of perlin
|
|||||||
// ** Rocktaves //
|
// ** Rocktaves //
|
||||||
//////////////////////
|
//////////////////////
|
||||||
uint16_t mode_rocktaves(void) { // Rocktaves. Same note from each octave is same colour. By: Andrew Tuline
|
uint16_t mode_rocktaves(void) { // Rocktaves. Same note from each octave is same colour. By: Andrew Tuline
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
float FFT_MajorPeak = *(float*) um_data->u_data[8]; // WLEDMM use FFT_MajorPeakSmth
|
float FFT_MajorPeak = *(float*) um_data->u_data[8]; // WLEDMM use FFT_MajorPeakSmth
|
||||||
float my_magnitude = *(float*) um_data->u_data[5] / 16.0f;
|
float my_magnitude = *(float*) um_data->u_data[5] / 16.0f;
|
||||||
|
|
||||||
@@ -7895,11 +7821,7 @@ uint16_t mode_waterfall(void) { // Waterfall. By: Andrew Tulin
|
|||||||
// effect can work on single pixels, we just lose the shifting effect
|
// effect can work on single pixels, we just lose the shifting effect
|
||||||
|
|
||||||
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
|
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
uint8_t samplePeak = *(uint8_t*)um_data->u_data[3];
|
uint8_t samplePeak = *(uint8_t*)um_data->u_data[3];
|
||||||
float FFT_MajorPeak = *(float*) um_data->u_data[4];
|
float FFT_MajorPeak = *(float*) um_data->u_data[4];
|
||||||
uint8_t *maxVol = (uint8_t*)um_data->u_data[6];
|
uint8_t *maxVol = (uint8_t*)um_data->u_data[6];
|
||||||
@@ -7960,11 +7882,7 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma.
|
|||||||
if (!SEGENV.allocateData(cols*sizeof(uint16_t))) return mode_static(); //allocation failed
|
if (!SEGENV.allocateData(cols*sizeof(uint16_t))) return mode_static(); //allocation failed
|
||||||
uint16_t *previousBarHeight = reinterpret_cast<uint16_t*>(SEGENV.data); //array of previous bar heights per frequency band
|
uint16_t *previousBarHeight = reinterpret_cast<uint16_t*>(SEGENV.data); //array of previous bar heights per frequency band
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
uint8_t fftResult[NUM_GEQ_CHANNELS] = {0};
|
uint8_t fftResult[NUM_GEQ_CHANNELS] = {0};
|
||||||
if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values
|
if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values
|
||||||
|
|
||||||
@@ -8071,11 +7989,7 @@ uint16_t mode_2DFunkyPlank(void) { // Written by ??? Adapted by Wil
|
|||||||
bandInc = (NUMB_BANDS / cols);
|
bandInc = (NUMB_BANDS / cols);
|
||||||
}
|
}
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
uint8_t fftResult[NUM_GEQ_CHANNELS] = {0};
|
uint8_t fftResult[NUM_GEQ_CHANNELS] = {0};
|
||||||
if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values
|
if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values
|
||||||
|
|
||||||
@@ -8156,7 +8070,7 @@ uint16_t mode_2DAkemi(void) {
|
|||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
const uint16_t cols = SEGMENT.virtualWidth();
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {SEGMENT.setUpLeds(); SEGMENT.fill(BLACK);}
|
if (SEGENV.call == 0) {SEGMENT.fill(BLACK);}
|
||||||
|
|
||||||
uint16_t counter = (strip.now * ((SEGMENT.speed >> 2) +2)) & 0xFFFF;
|
uint16_t counter = (strip.now * ((SEGMENT.speed >> 2) +2)) & 0xFFFF;
|
||||||
counter = counter >> 8;
|
counter = counter >> 8;
|
||||||
@@ -8164,10 +8078,7 @@ uint16_t mode_2DAkemi(void) {
|
|||||||
const float lightFactor = 0.15f;
|
const float lightFactor = 0.15f;
|
||||||
const float normalFactor = 0.4f;
|
const float normalFactor = 0.4f;
|
||||||
|
|
||||||
um_data_t *um_data = nullptr;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
uint8_t fftResult[NUM_GEQ_CHANNELS] = {0};
|
uint8_t fftResult[NUM_GEQ_CHANNELS] = {0};
|
||||||
if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values
|
if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values
|
||||||
float base = fftResult[0]/255.0f;
|
float base = fftResult[0]/255.0f;
|
||||||
@@ -8200,11 +8111,12 @@ uint16_t mode_2DAkemi(void) {
|
|||||||
|
|
||||||
//add geq left and right
|
//add geq left and right
|
||||||
if (um_data) {
|
if (um_data) {
|
||||||
for (int x=0; x < cols/8; x++) {
|
int xMax = cols/8;
|
||||||
uint16_t band = x * cols/8;
|
for (int x=0; x < xMax; x++) {
|
||||||
|
size_t band = map2(x, 0, max(xMax,4), 0, 15); // map 0..cols/8 to 16 GEQ bands
|
||||||
|
CRGB color = SEGMENT.color_from_palette((band * 35), false, PALETTE_SOLID_WRAP, 0);
|
||||||
band = constrain(band, 0, 15);
|
band = constrain(band, 0, 15);
|
||||||
uint16_t barHeight = map(fftResult[band], 0, 255, 0, 17*rows/32);
|
uint16_t barHeight = map(fftResult[band], 0, 255, 0, 17*rows/32);
|
||||||
CRGB color = SEGMENT.color_from_palette((band * 35), false, PALETTE_SOLID_WRAP, 0);
|
|
||||||
|
|
||||||
for (int y=0; y < barHeight; y++) {
|
for (int y=0; y < barHeight; y++) {
|
||||||
SEGMENT.setPixelColorXY(x, rows/2-y, color);
|
SEGMENT.setPixelColorXY(x, rows/2-y, color);
|
||||||
@@ -8553,11 +8465,7 @@ uint16_t mode_GEQLASER(void) {
|
|||||||
uint16_t horizon = map2(SEGMENT.custom1,0,255,rows-1,0);
|
uint16_t horizon = map2(SEGMENT.custom1,0,255,rows-1,0);
|
||||||
uint8_t depth = SEGMENT.custom2; // depth of perspective. 255 = infinite ("laser")
|
uint8_t depth = SEGMENT.custom2; // depth of perspective. 255 = infinite ("laser")
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data = getAudioData();
|
||||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
|
||||||
// add support for no audio
|
|
||||||
um_data = simulateSound(SEGMENT.soundSim);
|
|
||||||
}
|
|
||||||
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
||||||
|
|
||||||
uint8_t heights[NUM_GEQ_CHANNELS] = { 0 };
|
uint8_t heights[NUM_GEQ_CHANNELS] = { 0 };
|
||||||
@@ -8661,6 +8569,84 @@ static const char _data_FX_MODE_GEQLASER[] PROGMEM = "GEQ 3D ☾@Speed,Front Fil
|
|||||||
|
|
||||||
#endif // WLED_DISABLE_2D
|
#endif // WLED_DISABLE_2D
|
||||||
|
|
||||||
|
/*
|
||||||
|
@title MoonModules WLED - Painbrush Effect
|
||||||
|
@file included in FX.cpp
|
||||||
|
@repo https://github.com/MoonModules/WLED, submit changes to this file as PRs to MoonModules/WLED
|
||||||
|
@Authors https://github.com/MoonModules/WLED/commits/mdev/
|
||||||
|
@Copyright © 2024 Github MoonModules Commit Authors (contact moonmodules@icloud.com for details)
|
||||||
|
@license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007
|
||||||
|
|
||||||
|
This function is part of the MoonModules WLED fork also known as "WLED-MM".
|
||||||
|
WLED-MM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
WLED-MM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with WLED-MM. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
///////////////////////
|
||||||
|
// 2D Paintbrush //
|
||||||
|
///////////////////////
|
||||||
|
uint16_t mode_2DPaintbrush() {
|
||||||
|
|
||||||
|
// Author: @TroyHacks
|
||||||
|
// @license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007
|
||||||
|
|
||||||
|
if (!strip.isMatrix) return mode_static(); // not a 2D set-up
|
||||||
|
|
||||||
|
const uint16_t cols = SEGMENT.virtualWidth();
|
||||||
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
|
if (!SEGENV.allocateData(4)) return mode_static(); //allocation failed
|
||||||
|
|
||||||
|
if (SEGENV.call == 0) {
|
||||||
|
SEGMENT.setUpLeds();
|
||||||
|
SEGMENT.fill(BLACK);
|
||||||
|
SEGENV.aux0 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool phase_chaos = SEGMENT.check3;
|
||||||
|
bool soft = SEGMENT.check2;
|
||||||
|
bool color_chaos = SEGMENT.check1;
|
||||||
|
CRGB color;
|
||||||
|
|
||||||
|
byte numLines = map8(SEGMENT.intensity,1,16);
|
||||||
|
|
||||||
|
SEGENV.aux0++; // hue
|
||||||
|
SEGMENT.fadeToBlackBy(map8(SEGENV.custom1,10,128));
|
||||||
|
|
||||||
|
um_data_t *um_data = getAudioData();
|
||||||
|
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
||||||
|
|
||||||
|
SEGENV.aux1 = phase_chaos?random8():0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < numLines; i++) {
|
||||||
|
byte bin = map(i,0,numLines,0,15);
|
||||||
|
|
||||||
|
byte x1 = beatsin8(max(16,int(SEGMENT.speed))/16*1 + fftResult[0]/16, 0, (cols-1), fftResult[bin], SEGENV.aux1);
|
||||||
|
byte x2 = beatsin8(max(16,int(SEGMENT.speed))/16*2 + fftResult[0]/16, 0, (cols-1), fftResult[bin], SEGENV.aux1);
|
||||||
|
byte y1 = beatsin8(max(16,int(SEGMENT.speed))/16*3 + fftResult[0]/16, 0, (rows-1), fftResult[bin], SEGENV.aux1);
|
||||||
|
byte y2 = beatsin8(max(16,int(SEGMENT.speed))/16*4 + fftResult[0]/16, 0, (rows-1), fftResult[bin], SEGENV.aux1);
|
||||||
|
|
||||||
|
int length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
|
||||||
|
length = map8(fftResult[bin],0,length);
|
||||||
|
|
||||||
|
if (length > max(1,int(SEGMENT.custom3))) {
|
||||||
|
if (color_chaos) {
|
||||||
|
color = ColorFromPalette(SEGPALETTE, i * 255 / numLines + (SEGENV.aux0&0xFF), 255, LINEARBLEND);
|
||||||
|
} else {
|
||||||
|
uint16_t colorIndex = map(i,0,numLines,0,255);
|
||||||
|
color = SEGMENT.color_from_palette(colorIndex, false, PALETTE_SOLID_WRAP, 0);
|
||||||
|
}
|
||||||
|
SEGMENT.drawLine(x1,y1,x2,y2,color,soft,length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FRAMETIME;
|
||||||
|
} // mode_2DPaintbrush()
|
||||||
|
static const char _data_FX_MODE_2DPAINTBRUSH[] PROGMEM = "Paintbrush ☾@Oscillator Offset,# of lines,Fade Rate,,Min Length,Color Chaos,Anti-aliasing,Phase Chaos;!,,Peaks;!;2f;sx=160,ix=255,c1=80,c2=255,c3=0,pal=72,o1=0,o2=1,o3=0";
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// mode data
|
// mode data
|
||||||
@@ -8908,6 +8894,8 @@ void WS2812FX::setupEffectData() {
|
|||||||
|
|
||||||
addEffect(FX_MODE_GEQLASER, &mode_GEQLASER, _data_FX_MODE_GEQLASER); // audio
|
addEffect(FX_MODE_GEQLASER, &mode_GEQLASER, _data_FX_MODE_GEQLASER); // audio
|
||||||
|
|
||||||
|
addEffect(FX_MODE_2DPAINTBRUSH, &mode_2DPaintbrush, _data_FX_MODE_2DPAINTBRUSH); // audio
|
||||||
|
|
||||||
#endif // WLED_DISABLE_2D
|
#endif // WLED_DISABLE_2D
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
168
wled00/FX.h
168
wled00/FX.h
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
bool canUseSerial(void); // WLEDMM implemented in wled_serial.cpp
|
bool canUseSerial(void); // WLEDMM implemented in wled_serial.cpp
|
||||||
void strip_wait_until_idle(String whoCalledMe); // WLEDMM implemented in FX_fcn.cpp
|
void strip_wait_until_idle(String whoCalledMe); // WLEDMM implemented in FX_fcn.cpp
|
||||||
bool strip_uses_global_leds(void); // WLEDMM implemented in FX_fcn.cpp
|
bool strip_uses_global_leds(void) __attribute__((pure)); // WLEDMM implemented in FX_fcn.cpp
|
||||||
|
|
||||||
#define FASTLED_INTERNAL //remove annoying pragma messages
|
#define FASTLED_INTERNAL //remove annoying pragma messages
|
||||||
#define USE_GET_MILLISECOND_TIMER
|
#define USE_GET_MILLISECOND_TIMER
|
||||||
@@ -87,11 +87,13 @@ bool strip_uses_global_leds(void); // WLEDMM implemented in FX_fcn.
|
|||||||
#ifndef MAX_NUM_SEGMENTS
|
#ifndef MAX_NUM_SEGMENTS
|
||||||
#define MAX_NUM_SEGMENTS 32
|
#define MAX_NUM_SEGMENTS 32
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef MAX_SEGMENT_DATA
|
||||||
#if defined(ARDUINO_ARCH_ESP32S2)
|
#if defined(ARDUINO_ARCH_ESP32S2)
|
||||||
#define MAX_SEGMENT_DATA 24576
|
#define MAX_SEGMENT_DATA 24576
|
||||||
#else
|
#else
|
||||||
#define MAX_SEGMENT_DATA 32767
|
#define MAX_SEGMENT_DATA 32767
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* How much data bytes each segment should max allocate to leave enough space for other segments,
|
/* How much data bytes each segment should max allocate to leave enough space for other segments,
|
||||||
@@ -348,10 +350,10 @@ bool strip_uses_global_leds(void); // WLEDMM implemented in FX_fcn.
|
|||||||
#define FX_MODE_STARBURST_AR 192 // WLED-SR audioreactive fireworks starburst
|
#define FX_MODE_STARBURST_AR 192 // WLED-SR audioreactive fireworks starburst
|
||||||
// #define FX_MODE_PALETTE_AR 193 // WLED-SR audioreactive palette
|
// #define FX_MODE_PALETTE_AR 193 // WLED-SR audioreactive palette
|
||||||
#define FX_MODE_FIREWORKS_AR 194 // WLED-SR audioreactive fireworks
|
#define FX_MODE_FIREWORKS_AR 194 // WLED-SR audioreactive fireworks
|
||||||
#define FX_MODE_GEQLASER 195 // WLED-MM GEQ Laser
|
#define FX_MODE_GEQLASER 195 // WLED-MM GEQ Laser
|
||||||
#define FX_MODE_2DSNOWFALL 196 // WLED-MM Snowfall
|
#define FX_MODE_2DPAINTBRUSH 196 // WLED-MM Paintbrush
|
||||||
|
#define FX_MODE_2DSNOWFALL 197 // WLED-MM Snowfall
|
||||||
#define MODE_COUNT 197
|
#define MODE_COUNT 198
|
||||||
|
|
||||||
typedef enum mapping1D2D {
|
typedef enum mapping1D2D {
|
||||||
M12_Pixels = 0,
|
M12_Pixels = 0,
|
||||||
@@ -435,6 +437,21 @@ typedef struct Segment {
|
|||||||
static size_t _usedSegmentData; // WLEDMM uint16_t is too small
|
static size_t _usedSegmentData; // WLEDMM uint16_t is too small
|
||||||
void setPixelColorXY_fast(int x, int y,uint32_t c, uint32_t scaled_col, int cols, int rows); // set relative pixel within segment with color - faster, but no error checking!!!
|
void setPixelColorXY_fast(int x, int y,uint32_t c, uint32_t scaled_col, int cols, int rows); // set relative pixel within segment with color - faster, but no error checking!!!
|
||||||
|
|
||||||
|
bool _isSimpleSegment = false; // simple = no grouping or spacing - mirror, transpose or reverse allowed
|
||||||
|
bool _isSuperSimpleSegment = false; // superSimple = no grouping or spacing, no mirror - only transpose or reverse allowed
|
||||||
|
#ifdef WLEDMM_FASTPATH
|
||||||
|
// WLEDMM cache some values that won't change while drawing a frame
|
||||||
|
bool _isValid2D = false;
|
||||||
|
uint8_t _brightness = 255; // final pixel brightness - including transitions and segment opacity
|
||||||
|
bool _firstFill = true; // dirty HACK support
|
||||||
|
uint16_t _2dWidth = 0; // virtualWidth
|
||||||
|
uint16_t _2dHeight = 0; // virtualHeight
|
||||||
|
|
||||||
|
void setPixelColorXY_slow(int x, int y, uint32_t c); // set relative pixel within segment with color - full slow version
|
||||||
|
#else
|
||||||
|
void setPixelColorXY_slow(int x, int y, uint32_t c) { setPixelColorXY(x,y,c); } // not FASTPATH - slow is the normal
|
||||||
|
#endif
|
||||||
|
|
||||||
// perhaps this should be per segment, not static
|
// perhaps this should be per segment, not static
|
||||||
static CRGBPalette16 _currentPalette; // palette used for current effect (includes transition, used in color_from_palette())
|
static CRGBPalette16 _currentPalette; // palette used for current effect (includes transition, used in color_from_palette())
|
||||||
|
|
||||||
@@ -578,7 +595,7 @@ typedef struct Segment {
|
|||||||
void setCCT(uint16_t k);
|
void setCCT(uint16_t k);
|
||||||
void setOpacity(uint8_t o);
|
void setOpacity(uint8_t o);
|
||||||
void setOption(uint8_t n, bool val);
|
void setOption(uint8_t n, bool val);
|
||||||
void setMode(uint8_t fx, bool loadDefaults = false);
|
void setMode(uint8_t fx, bool loadDefaults = false, bool sliderDefaultsOnly = false);
|
||||||
void setPalette(uint8_t pal);
|
void setPalette(uint8_t pal);
|
||||||
uint8_t differs(Segment& b) const;
|
uint8_t differs(Segment& b) const;
|
||||||
void refreshLightCapabilities(void);
|
void refreshLightCapabilities(void);
|
||||||
@@ -588,6 +605,7 @@ typedef struct Segment {
|
|||||||
bool allocateData(size_t len);
|
bool allocateData(size_t len);
|
||||||
void deallocateData(void);
|
void deallocateData(void);
|
||||||
void resetIfRequired(void);
|
void resetIfRequired(void);
|
||||||
|
void startFrame(void); // cache a few values that don't change while an effect is drawing
|
||||||
/**
|
/**
|
||||||
* Flags that before the next effect is calculated,
|
* Flags that before the next effect is calculated,
|
||||||
* the internal segment state should be reset.
|
* the internal segment state should be reset.
|
||||||
@@ -626,7 +644,7 @@ typedef struct Segment {
|
|||||||
void setPixelColor(float i, uint32_t c, bool aa = true);
|
void setPixelColor(float i, uint32_t c, bool aa = true);
|
||||||
inline void setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = true) { setPixelColor(i, RGBW32(r,g,b,w), aa); }
|
inline void setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = true) { setPixelColor(i, RGBW32(r,g,b,w), aa); }
|
||||||
inline void setPixelColor(float i, CRGB c, bool aa = true) { setPixelColor(i, RGBW32(c.r,c.g,c.b,0), aa); }
|
inline void setPixelColor(float i, CRGB c, bool aa = true) { setPixelColor(i, RGBW32(c.r,c.g,c.b,0), aa); }
|
||||||
uint32_t __attribute__((pure)) getPixelColor(int i); // WLEDMM attribute added
|
uint32_t __attribute__((pure)) getPixelColor(int i) const; // WLEDMM attribute added
|
||||||
// 1D support functions (some implement 2D as well)
|
// 1D support functions (some implement 2D as well)
|
||||||
void blur(uint8_t, bool smear = false);
|
void blur(uint8_t, bool smear = false);
|
||||||
void fill(uint32_t c);
|
void fill(uint32_t c);
|
||||||
@@ -638,11 +656,22 @@ typedef struct Segment {
|
|||||||
inline void addPixelColor(int n, byte r, byte g, byte b, byte w = 0, bool fast = false) { addPixelColor(n, RGBW32(r,g,b,w), fast); } // automatically inline
|
inline void addPixelColor(int n, byte r, byte g, byte b, byte w = 0, bool fast = false) { addPixelColor(n, RGBW32(r,g,b,w), fast); } // automatically inline
|
||||||
inline void addPixelColor(int n, CRGB c, bool fast = false) { addPixelColor(n, RGBW32(c.r,c.g,c.b,0), fast); } // automatically inline
|
inline void addPixelColor(int n, CRGB c, bool fast = false) { addPixelColor(n, RGBW32(c.r,c.g,c.b,0), fast); } // automatically inline
|
||||||
void fadePixelColor(uint16_t n, uint8_t fade);
|
void fadePixelColor(uint16_t n, uint8_t fade);
|
||||||
uint8_t get_random_wheel_index(uint8_t pos);
|
uint8_t get_random_wheel_index(uint8_t pos) const;
|
||||||
uint32_t __attribute__((pure)) color_from_palette(uint_fast16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255);
|
uint32_t __attribute__((pure)) color_from_palette(uint_fast16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255);
|
||||||
uint32_t __attribute__((pure)) color_wheel(uint8_t pos);
|
uint32_t __attribute__((pure)) color_wheel(uint8_t pos);
|
||||||
|
|
||||||
|
// 2D Blur: shortcuts for bluring columns or rows only (50% faster than full 2D blur)
|
||||||
|
inline void blurCols(fract8 blur_amount, bool smear = false) { // blur all columns
|
||||||
|
const unsigned cols = virtualWidth();
|
||||||
|
for (unsigned k = 0; k < cols; k++) blurCol(k, blur_amount, smear);
|
||||||
|
}
|
||||||
|
inline void blurRows(fract8 blur_amount, bool smear = false) { // blur all rows
|
||||||
|
const unsigned rows = virtualHeight();
|
||||||
|
for ( unsigned i = 0; i < rows; i++) blurRow(i, blur_amount, smear);
|
||||||
|
}
|
||||||
|
|
||||||
// 2D matrix
|
// 2D matrix
|
||||||
|
#ifndef WLEDMM_FASTPATH
|
||||||
inline uint16_t virtualWidth() const { // WLEDMM use fast types, and make function inline
|
inline uint16_t virtualWidth() const { // WLEDMM use fast types, and make function inline
|
||||||
uint_fast16_t groupLen = groupLength();
|
uint_fast16_t groupLen = groupLength();
|
||||||
uint_fast16_t vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen;
|
uint_fast16_t vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen;
|
||||||
@@ -655,22 +684,53 @@ typedef struct Segment {
|
|||||||
if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||||
return vHeight;
|
return vHeight;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
inline uint16_t virtualWidth() const { return(_2dWidth);} // WLEDMM get pre-calculated virtualWidth
|
||||||
|
inline uint16_t virtualHeight() const { return(_2dHeight);} // WLEDMM get pre-calculated virtualHeight
|
||||||
|
|
||||||
|
uint16_t calc_virtualWidth() const {
|
||||||
|
uint_fast16_t groupLen = groupLength();
|
||||||
|
uint_fast16_t vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen;
|
||||||
|
if (mirror) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||||
|
return vWidth;
|
||||||
|
}
|
||||||
|
uint16_t calc_virtualHeight() const {
|
||||||
|
uint_fast16_t groupLen = groupLength();
|
||||||
|
uint_fast16_t vHeight = ((transpose ? width() : height()) + groupLen - 1) / groupLen;
|
||||||
|
if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||||
|
return vHeight;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uint16_t nrOfVStrips(void) const;
|
uint16_t nrOfVStrips(void) const;
|
||||||
void createjMap(); //WLEDMM jMap
|
void createjMap(); //WLEDMM jMap
|
||||||
void deletejMap(); //WLEDMM jMap
|
void deletejMap(); //WLEDMM jMap
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
inline uint16_t XY(uint_fast16_t x, uint_fast16_t y) { // support function to get relative index within segment (for leds[]) // WLEDMM inline for speed
|
inline uint16_t XY(uint_fast16_t x, uint_fast16_t y) const { // support function to get relative index within segment (for leds[]) // WLEDMM inline for speed
|
||||||
uint_fast16_t width = virtualWidth(); // segment width in logical pixels
|
uint_fast16_t width = max(uint16_t(1), virtualWidth()); // segment width in logical pixels -- softhack007 avoid div/0
|
||||||
uint_fast16_t height = virtualHeight(); // segment height in logical pixels
|
uint_fast16_t height = max(uint16_t(1), virtualHeight()); // segment height in logical pixels -- softhack007 avoid div/0
|
||||||
if (width == 0) return 0; // softhack007 avoid div/0
|
|
||||||
if (height == 0) return (x%width); // softhack007 avoid div/0
|
|
||||||
return (x%width) + (y%height) * width;
|
return (x%width) + (y%height) * width;
|
||||||
}
|
}
|
||||||
|
|
||||||
//void setPixelColorXY_fast(int x, int y,uint32_t c); // set relative pixel within segment with color - wrapper for _fast
|
#ifdef WLEDMM_FASTPATH
|
||||||
|
// WLEDMM this is a "gateway" function - we either call _fast or fall back to "slow"
|
||||||
|
inline void setPixelColorXY(int x, int y, uint32_t col) {
|
||||||
|
if (!_isSimpleSegment) { // slow path
|
||||||
|
setPixelColorXY_slow(x, y, col);
|
||||||
|
} else { // fast path
|
||||||
|
// some sanity checks
|
||||||
|
if (!_isValid2D) return; // not active
|
||||||
|
if ((unsigned(x) >= _2dWidth) || (unsigned(y) >= _2dHeight)) return; // check if (x,y) are out-of-range - due to 2's complement, this also catches negative values
|
||||||
|
if (!_brightness && !transitional) return; // black-out
|
||||||
|
|
||||||
|
uint32_t scaled_col = (_brightness == 255) ? col : color_fade(col, _brightness); // calculate final color
|
||||||
|
setPixelColorXY_fast(x, y, col, scaled_col, int(_2dWidth), int(_2dHeight)); // call "fast" function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
|
void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
|
||||||
|
#endif
|
||||||
inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColorXY(int(x), int(y), c); }
|
inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColorXY(int(x), int(y), c); }
|
||||||
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); }
|
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); }
|
||||||
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }
|
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }
|
||||||
@@ -680,7 +740,7 @@ typedef struct Segment {
|
|||||||
inline void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColorXY(x, y, RGBW32(r,g,b,w), aa); }
|
inline void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColorXY(x, y, RGBW32(r,g,b,w), aa); }
|
||||||
inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), aa); }
|
inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), aa); }
|
||||||
//#endif
|
//#endif
|
||||||
uint32_t __attribute__((pure)) getPixelColorXY(int x, int y);
|
uint32_t __attribute__((pure)) getPixelColorXY(int x, int y) const;
|
||||||
// 2D support functions
|
// 2D support functions
|
||||||
void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend);
|
void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend);
|
||||||
inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), blend); }
|
inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), blend); }
|
||||||
@@ -696,13 +756,13 @@ typedef struct Segment {
|
|||||||
void move(uint8_t dir, uint8_t delta, bool wrap = false);
|
void move(uint8_t dir, uint8_t delta, bool wrap = false);
|
||||||
void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false);
|
void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false);
|
||||||
inline void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { drawCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
|
inline void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { drawCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
|
||||||
void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false);
|
void fillCircle(unsigned cx, unsigned cy, int radius, uint32_t col, bool soft);
|
||||||
inline void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { fillCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
|
inline void fillCircle(unsigned cx, unsigned cy, int radius, CRGB c, bool soft = false) { fillCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
|
||||||
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, bool soft = false, uint8_t depth = UINT8_MAX);
|
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, bool soft = false, uint8_t depth = UINT8_MAX);
|
||||||
inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false, uint8_t depth = UINT8_MAX) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0), soft, depth); } // automatic inline
|
inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false, uint8_t depth = UINT8_MAX) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0), soft, depth); } // automatic inline
|
||||||
void drawArc(uint16_t x0, uint16_t y0, uint16_t radius, uint32_t color, uint32_t fillColor = 0);
|
void drawArc(unsigned x0, unsigned y0, int radius, uint32_t color, uint32_t fillColor = 0);
|
||||||
inline void drawArc(uint16_t x0, uint16_t y0, uint16_t radius, CRGB color, CRGB fillColor = BLACK) { drawArc(x0, y0, radius, RGBW32(color.r,color.g,color.b,0), RGBW32(fillColor.r,fillColor.g,fillColor.b,0)); } // automatic inline
|
inline void drawArc(unsigned x0, unsigned y0, int radius, CRGB color, CRGB fillColor = BLACK) { drawArc(x0, y0, radius, RGBW32(color.r,color.g,color.b,0), RGBW32(fillColor.r,fillColor.g,fillColor.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);
|
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, bool drawShadow = false);
|
||||||
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
|
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
|
||||||
@@ -746,7 +806,7 @@ typedef struct Segment {
|
|||||||
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) {}
|
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) {}
|
||||||
inline void wu_pixel(uint32_t x, uint32_t y, CRGB c) {}
|
inline void wu_pixel(uint32_t x, uint32_t y, CRGB c) {}
|
||||||
#endif
|
#endif
|
||||||
uint8_t * getAudioPalette(int pal); //WLEDMM netmindz ar palette
|
uint8_t * getAudioPalette(int pal) const; //WLEDMM netmindz ar palette
|
||||||
} segment;
|
} segment;
|
||||||
//static int segSize = sizeof(Segment);
|
//static int segSize = sizeof(Segment);
|
||||||
|
|
||||||
@@ -869,64 +929,66 @@ class WS2812FX { // 96 bytes
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
checkSegmentAlignment(void),
|
checkSegmentAlignment(void),
|
||||||
hasRGBWBus(void),
|
hasRGBWBus(void) const,
|
||||||
hasCCTBus(void),
|
hasCCTBus(void) const,
|
||||||
// return true if the strip is being sent pixel updates
|
// return true if the strip is being sent pixel updates
|
||||||
isUpdating(void),
|
isUpdating(void) const,
|
||||||
deserializeMap(uint8_t n=0),
|
deserializeMap(uint8_t n=0),
|
||||||
useLedsArray = false;
|
useLedsArray = false;
|
||||||
|
|
||||||
inline bool isServicing(void) { return _isServicing; }
|
inline bool isServicing(void) const { return _isServicing; }
|
||||||
inline bool hasWhiteChannel(void) {return _hasWhiteChannel;}
|
inline bool hasWhiteChannel(void) const {return _hasWhiteChannel;}
|
||||||
inline bool isOffRefreshRequired(void) {return _isOffRefreshRequired;}
|
inline bool isOffRefreshRequired(void) const {return _isOffRefreshRequired;}
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
paletteFade,
|
paletteFade,
|
||||||
paletteBlend,
|
paletteBlend,
|
||||||
milliampsPerLed,
|
milliampsPerLed,
|
||||||
cctBlending,
|
cctBlending,
|
||||||
getActiveSegmentsNum(void),
|
getActiveSegmentsNum(void) const,
|
||||||
getFirstSelectedSegId(void),
|
getFirstSelectedSegId(void) __attribute__((pure)),
|
||||||
getLastActiveSegmentId(void),
|
getLastActiveSegmentId(void) const,
|
||||||
getActiveSegsLightCapabilities(bool selectedOnly = false),
|
getActiveSegsLightCapabilities(bool selectedOnly = false) __attribute__((pure)),
|
||||||
setPixelSegment(uint8_t n);
|
setPixelSegment(uint8_t n);
|
||||||
|
|
||||||
inline uint8_t getBrightness(void) { return _brightness; }
|
inline uint8_t getBrightness(void) const { return _brightness; }
|
||||||
inline uint8_t getMaxSegments(void) { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value)
|
inline uint8_t getSegmentsNum(void) const { return _segments.size(); } // returns currently present segments
|
||||||
inline uint8_t getSegmentsNum(void) { return _segments.size(); } // returns currently present segments
|
inline uint8_t getCurrSegmentId(void) const { return _segment_index; }
|
||||||
inline uint8_t getCurrSegmentId(void) { return _segment_index; }
|
inline uint8_t getMainSegmentId(void) const { return _mainSegment; }
|
||||||
inline uint8_t getMainSegmentId(void) { return _mainSegment; }
|
inline uint8_t getTargetFps() const { return _targetFps; }
|
||||||
inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count
|
inline uint8_t getModeCount() const { return _modeCount; }
|
||||||
inline uint8_t getTargetFps() { return _targetFps; }
|
inline static constexpr uint8_t getMaxSegments(void) { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value)
|
||||||
inline uint8_t getModeCount() { return _modeCount; }
|
inline static constexpr uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count
|
||||||
|
|
||||||
uint16_t
|
uint16_t
|
||||||
ablMilliampsMax,
|
ablMilliampsMax,
|
||||||
currentMilliamps,
|
currentMilliamps,
|
||||||
getLengthPhysical(void),
|
getLengthPhysical(void) const,
|
||||||
__attribute__((pure)) getLengthTotal(void), // will include virtual/nonexistent pixels in matrix //WLEDMM attribute added
|
getLengthPhysical2(void) const, // WLEDMM total length including HUB75, network busses excluded
|
||||||
getFps();
|
__attribute__((pure)) getLengthTotal(void) const, // will include virtual/nonexistent pixels in matrix //WLEDMM attribute added
|
||||||
|
getFps() const;
|
||||||
|
|
||||||
inline uint16_t getFrameTime(void) { return _frametime; }
|
inline uint16_t getFrameTime(void) const { return _frametime; }
|
||||||
inline uint16_t getMinShowDelay(void) { return MIN_SHOW_DELAY; }
|
inline uint16_t getMinShowDelay(void) const { return MIN_SHOW_DELAY; }
|
||||||
inline uint16_t getLength(void) { return _length; } // 2D matrix may have less pixels than W*H
|
inline uint16_t getLength(void) const { return _length; } // 2D matrix may have less pixels than W*H
|
||||||
inline uint16_t getTransition(void) { return _transitionDur; }
|
inline uint16_t getTransition(void) const { return _transitionDur; }
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
now,
|
now,
|
||||||
timebase;
|
timebase;
|
||||||
uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t); // WLEDMM attribute pure = does not have side-effects
|
uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t) const; // WLEDMM attribute pure = does not have side-effects
|
||||||
|
uint32_t __attribute__((pure)) getPixelColorRestored(uint_fast16_t i) const;// WLEDMM gets the original color from the driver (without downscaling by _bri)
|
||||||
|
|
||||||
inline uint32_t getLastShow(void) { return _lastShow; }
|
inline uint32_t getLastShow(void) const { return _lastShow; }
|
||||||
inline uint32_t segColor(uint8_t i) { return _colors_t[i]; }
|
inline uint32_t segColor(uint8_t i) const { return _colors_t[i]; }
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
getModeData(uint8_t id = 0) { return (id && id<_modeCount) ? _modeData[id] : PSTR("Solid"); }
|
getModeData(uint8_t id = 0) const { return (id && id<_modeCount) ? _modeData[id] : PSTR("Solid"); }
|
||||||
|
|
||||||
const char **
|
const char **
|
||||||
getModeDataSrc(void) { return &(_modeData[0]); } // vectors use arrays for underlying data
|
getModeDataSrc(void) { return &(_modeData[0]); } // vectors use arrays for underlying data
|
||||||
|
|
||||||
Segment& getSegment(uint8_t id);
|
Segment& getSegment(uint8_t id) __attribute__((pure));
|
||||||
inline Segment& getFirstSelectedSeg(void) { return _segments[getFirstSelectedSegId()]; }
|
inline Segment& getFirstSelectedSeg(void) { return _segments[getFirstSelectedSegId()]; }
|
||||||
inline Segment& getMainSegment(void) { return _segments[getMainSegmentId()]; }
|
inline Segment& getMainSegment(void) { return _segments[getMainSegmentId()]; }
|
||||||
inline Segment* getSegments(void) { return &(_segments[0]); }
|
inline Segment* getSegments(void) { return &(_segments[0]); }
|
||||||
@@ -993,7 +1055,7 @@ class WS2812FX { // 96 bytes
|
|||||||
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }
|
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
getPixelColorXY(uint16_t, uint16_t);
|
getPixelColorXY(uint16_t, uint16_t) const;
|
||||||
|
|
||||||
// end 2D support
|
// end 2D support
|
||||||
|
|
||||||
@@ -1008,6 +1070,8 @@ class WS2812FX { // 96 bytes
|
|||||||
std::vector<segment> _segments;
|
std::vector<segment> _segments;
|
||||||
friend class Segment;
|
friend class Segment;
|
||||||
|
|
||||||
|
uint32_t getPixelColorXYRestored(uint16_t x, uint16_t y) const; // WLEDMM gets the original color from the driver (without downscaling by _bri)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t _length;
|
uint16_t _length;
|
||||||
uint8_t _brightness;
|
uint8_t _brightness;
|
||||||
|
|||||||
@@ -66,9 +66,26 @@ void WS2812FX::setUpMatrix() {
|
|||||||
|
|
||||||
USER_PRINTF("setUpMatrix %d x %d\n", Segment::maxWidth, Segment::maxHeight);
|
USER_PRINTF("setUpMatrix %d x %d\n", Segment::maxWidth, Segment::maxHeight);
|
||||||
|
|
||||||
|
// WLEDMM check if mapping table is necessary (avoiding heap fragmentation)
|
||||||
|
#if defined(WLED_ENABLE_HUB75MATRIX)
|
||||||
|
bool needLedMap = (loadedLedmap >0); // ledmap loaded
|
||||||
|
needLedMap |= WLED_FS.exists(F("/2d-gaps.json")); // gapFile found
|
||||||
|
needLedMap |= panel.size() > 1; // 2D config: more than one panel
|
||||||
|
if (panel.size() == 1) {
|
||||||
|
Panel &p = panel[0];
|
||||||
|
needLedMap |= p.serpentine; // panel serpentine
|
||||||
|
needLedMap |= p.vertical; // panel not horizotal
|
||||||
|
needLedMap |= p.bottomStart | p.rightStart; // panel not top left, or not left->light
|
||||||
|
needLedMap |= (p.xOffset > 0) || (p.yOffset > 0); // panel does not start at (0,0)
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
bool needLedMap = true; // always use ledMaps on non-HUB75 builds
|
||||||
|
#endif
|
||||||
|
|
||||||
//WLEDMM recreate customMappingTable if more space needed
|
//WLEDMM recreate customMappingTable if more space needed
|
||||||
if (Segment::maxWidth * Segment::maxHeight > customMappingTableSize) {
|
if (Segment::maxWidth * Segment::maxHeight > customMappingTableSize) {
|
||||||
size_t size = max(ledmapMaxSize, size_t(Segment::maxWidth * Segment::maxHeight)); // TroyHacks
|
size_t size = max(ledmapMaxSize, size_t(Segment::maxWidth * Segment::maxHeight)); // TroyHacks
|
||||||
|
if (!needLedMap) size = 0; // softhack007
|
||||||
USER_PRINTF("setupmatrix customMappingTable alloc %d from %d\n", size, customMappingTableSize);
|
USER_PRINTF("setupmatrix customMappingTable alloc %d from %d\n", size, customMappingTableSize);
|
||||||
//if (customMappingTable != nullptr) delete[] customMappingTable;
|
//if (customMappingTable != nullptr) delete[] customMappingTable;
|
||||||
//customMappingTable = new uint16_t[size];
|
//customMappingTable = new uint16_t[size];
|
||||||
@@ -88,8 +105,9 @@ void WS2812FX::setUpMatrix() {
|
|||||||
if (customMappingTable != nullptr) customMappingTableSize = size;
|
if (customMappingTable != nullptr) customMappingTableSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (customMappingTable != nullptr) {
|
if ((customMappingTable != nullptr) || (!needLedMap)) { // softhack007
|
||||||
customMappingSize = Segment::maxWidth * Segment::maxHeight;
|
customMappingSize = Segment::maxWidth * Segment::maxHeight;
|
||||||
|
if (!needLedMap) customMappingSize = 0; // softhack007
|
||||||
|
|
||||||
// fill with empty in case we don't fill the entire matrix
|
// fill with empty in case we don't fill the entire matrix
|
||||||
for (size_t i = 0; i< customMappingTableSize; i++) { //WLEDMM use customMappingTableSize
|
for (size_t i = 0; i< customMappingTableSize; i++) { //WLEDMM use customMappingTableSize
|
||||||
@@ -130,6 +148,7 @@ void WS2812FX::setUpMatrix() {
|
|||||||
releaseJSONBufferLock();
|
releaseJSONBufferLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needLedMap && customMappingTable != nullptr) { // softhack007
|
||||||
uint16_t x, y, pix=0; //pixel
|
uint16_t x, y, pix=0; //pixel
|
||||||
for (size_t pan = 0; pan < panel.size(); pan++) {
|
for (size_t pan = 0; pan < panel.size(); pan++) {
|
||||||
Panel &p = panel[pan];
|
Panel &p = panel[pan];
|
||||||
@@ -146,6 +165,7 @@ void WS2812FX::setUpMatrix() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// delete gap array as we no longer need it
|
// delete gap array as we no longer need it
|
||||||
if (gapTable) {delete[] gapTable; gapTable=nullptr;} // softhack prevent dangling pointer
|
if (gapTable) {delete[] gapTable; gapTable=nullptr;} // softhack prevent dangling pointer
|
||||||
@@ -171,13 +191,31 @@ void WS2812FX::setUpMatrix() {
|
|||||||
//WLEDMM: no resetSegments here, only do it in set.cpp/handleSettingsSet - as we want t0 maintain the segment settings after setup has changed
|
//WLEDMM: no resetSegments here, only do it in set.cpp/handleSettingsSet - as we want t0 maintain the segment settings after setup has changed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WLED_ENABLE_HUB75MATRIX
|
||||||
|
// softhack007 hack: delete mapping table in case it only contains "identity"
|
||||||
|
if (customMappingTable != nullptr && customMappingTableSize > 0) {
|
||||||
|
bool isIdentity = true;
|
||||||
|
for (size_t i = 0; (i< customMappingSize) && isIdentity; i++) { //WLEDMM use customMappingTableSize
|
||||||
|
if (customMappingTable[i] != (uint16_t)i ) isIdentity = false;
|
||||||
|
}
|
||||||
|
if (isIdentity) {
|
||||||
|
free(customMappingTable); customMappingTable = nullptr;
|
||||||
|
USER_PRINTF("!setupmatrix: customMappingTable is not needed. Dropping %d bytes.\n", customMappingTableSize * sizeof(uint16_t));
|
||||||
|
customMappingTableSize = 0;
|
||||||
|
customMappingSize = 0;
|
||||||
|
loadedLedmap = 0; //WLEDMM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
isMatrix = false; // no matter what config says
|
isMatrix = false; // no matter what config says
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// absolute matrix version of setPixelColor(), without error checking
|
// absolute matrix version of setPixelColor(), without error checking
|
||||||
void IRAM_ATTR WS2812FX::setPixelColorXY_fast(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
|
void IRAM_ATTR __attribute__((hot)) WS2812FX::setPixelColorXY_fast(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
|
||||||
{
|
{
|
||||||
uint_fast16_t index = y * Segment::maxWidth + x;
|
uint_fast16_t index = y * Segment::maxWidth + x;
|
||||||
if (index < customMappingSize) index = customMappingTable[index];
|
if (index < customMappingSize) index = customMappingTable[index];
|
||||||
@@ -200,7 +238,7 @@ void IRAM_ATTR_YN WS2812FX::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns RGBW values of pixel
|
// returns RGBW values of pixel
|
||||||
uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
uint32_t __attribute__((hot)) WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) const {
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
uint_fast16_t index = (y * Segment::maxWidth + x); //WLEDMM: use fast types
|
uint_fast16_t index = (y * Segment::maxWidth + x); //WLEDMM: use fast types
|
||||||
#else
|
#else
|
||||||
@@ -211,19 +249,48 @@ uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
|||||||
return busses.getPixelColor(index);
|
return busses.getPixelColor(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t __attribute__((hot)) WS2812FX::getPixelColorXYRestored(uint16_t x, uint16_t y) const { // WLEDMM gets the original color from the driver (without downscaling by _bri)
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
|
uint_fast16_t index = (y * Segment::maxWidth + x); //WLEDMM: use fast types
|
||||||
|
#else
|
||||||
|
uint16_t index = x;
|
||||||
|
#endif
|
||||||
|
if (index < customMappingSize) index = customMappingTable[index];
|
||||||
|
if (index >= _length) return 0;
|
||||||
|
return busses.getPixelColorRestored(index);
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
// Segment:: routines
|
// Segment:: routines
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
|
|
||||||
|
// WLEDMM cache some values so we don't need to re-calc then for each pixel
|
||||||
|
void Segment::startFrame(void) {
|
||||||
|
_isSimpleSegment = (grouping == 1) && (spacing == 0); // we can handle pixels faster when no grouping or spacing is involved
|
||||||
|
_isSuperSimpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0); // fastest - we only draw one pixel per call
|
||||||
|
|
||||||
|
#ifdef WLEDMM_FASTPATH
|
||||||
|
_isValid2D = isActive() && is2D();
|
||||||
|
_brightness = currentBri(on ? opacity : 0);
|
||||||
|
// if (reverse_y) _isSimpleSegment = false; // for A/B testing
|
||||||
|
_2dWidth = is2D() ? calc_virtualWidth() : virtualLength();
|
||||||
|
_2dHeight = calc_virtualHeight();
|
||||||
|
#if 0 && defined(WLED_ENABLE_HUB75MATRIX)
|
||||||
|
_firstFill = true; // dirty HACK
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// WLEDMM end
|
||||||
|
|
||||||
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
|
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
|
||||||
// WLEDMM Segment::XY()is declared inline, see FX.h
|
// WLEDMM Segment::XY()is declared inline, see FX.h
|
||||||
|
|
||||||
|
|
||||||
// Simplified version of Segment::setPixelColorXY - without error checking. Does not support grouping or spacing
|
// Simplified version of Segment::setPixelColorXY - without error checking. Does not support grouping or spacing
|
||||||
// * expects scaled color (final brightness) as additional input parameter, plus segment virtualWidth() and virtualHeight()
|
// * expects scaled color (final brightness) as additional input parameter, plus segment virtualWidth() and virtualHeight()
|
||||||
void IRAM_ATTR Segment::setPixelColorXY_fast(int x, int y, uint32_t col, uint32_t scaled_col, int cols, int rows) //WLEDMM
|
void IRAM_ATTR __attribute__((hot)) Segment::setPixelColorXY_fast(int x, int y, uint32_t col, uint32_t scaled_col, int cols, int rows) //WLEDMM
|
||||||
{
|
{
|
||||||
unsigned i = UINT_MAX;
|
unsigned i = UINT_MAX;
|
||||||
bool sameColor = false;
|
bool sameColor = false;
|
||||||
@@ -245,7 +312,11 @@ void IRAM_ATTR Segment::setPixelColorXY_fast(int x, int y, uint32_t col, uint32_
|
|||||||
|
|
||||||
// set the requested pixel
|
// set the requested pixel
|
||||||
strip.setPixelColorXY_fast(start + x, startY + y, scaled_col);
|
strip.setPixelColorXY_fast(start + x, startY + y, scaled_col);
|
||||||
|
#ifdef WLEDMM_FASTPATH
|
||||||
|
bool simpleSegment = _isSuperSimpleSegment;
|
||||||
|
#else
|
||||||
bool simpleSegment = !mirror && !mirror_y;
|
bool simpleSegment = !mirror && !mirror_y;
|
||||||
|
#endif
|
||||||
if (simpleSegment) return; // WLEDMM shortcut when no mirroring needed
|
if (simpleSegment) return; // WLEDMM shortcut when no mirroring needed
|
||||||
|
|
||||||
// handle mirroring
|
// handle mirroring
|
||||||
@@ -260,15 +331,19 @@ void IRAM_ATTR Segment::setPixelColorXY_fast(int x, int y, uint32_t col, uint32_
|
|||||||
else strip.setPixelColorXY_fast(start + x, startY + hei_ - y - 1, scaled_col);
|
else strip.setPixelColorXY_fast(start + x, startY + hei_ - y - 1, scaled_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_fast(wid_ - x - 1, hei_ - y - 1, scaled_col);
|
strip.setPixelColorXY_fast(start + wid_ - x - 1, startY + hei_ - y - 1, scaled_col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// normal Segment::setPixelColorXY with error checking, and support for grouping / spacing
|
// normal Segment::setPixelColorXY with error checking, and support for grouping / spacing
|
||||||
|
#ifdef WLEDMM_FASTPATH
|
||||||
|
void IRAM_ATTR_YN Segment::setPixelColorXY_slow(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally, renamed to "_slow"
|
||||||
|
#else
|
||||||
void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
|
void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if (Segment::maxHeight==1) return; // not a matrix set-up
|
if ((Segment::maxHeight==1) || !isActive()) return; // not a matrix set-up
|
||||||
const int_fast16_t cols = virtualWidth(); // WLEDMM optimization
|
const int_fast16_t cols = virtualWidth(); // WLEDMM optimization
|
||||||
const int_fast16_t rows = virtualHeight();
|
const int_fast16_t rows = virtualHeight();
|
||||||
|
|
||||||
@@ -297,15 +372,19 @@ void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM:
|
|||||||
if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
||||||
|
|
||||||
// WLEDMM shortcut when no grouping/spacing used
|
// WLEDMM shortcut when no grouping/spacing used
|
||||||
|
#ifdef WLEDMM_FASTPATH
|
||||||
|
bool simpleSegment = _isSuperSimpleSegment;
|
||||||
|
#else
|
||||||
bool simpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0);
|
bool simpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0);
|
||||||
|
#endif
|
||||||
if (simpleSegment) {
|
if (simpleSegment) {
|
||||||
strip.setPixelColorXY(start + x, startY + y, col);
|
strip.setPixelColorXY(start + x, startY + y, col);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int_fast16_t glen_ = groupLength(); // WLEDMM optimization
|
const uint_fast16_t glen_ = groupLength(); // WLEDMM optimization
|
||||||
const int_fast16_t wid_ = width();
|
const uint_fast16_t wid_ = width();
|
||||||
const int_fast16_t hei_ = height();
|
const uint_fast16_t hei_ = height();
|
||||||
|
|
||||||
x *= glen_; // expand to physical pixels
|
x *= glen_; // expand to physical pixels
|
||||||
y *= glen_; // expand to physical pixels
|
y *= glen_; // expand to physical pixels
|
||||||
@@ -328,18 +407,20 @@ void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM:
|
|||||||
else strip.setPixelColorXY(start + xX, startY + hei_ - yY - 1, col);
|
else strip.setPixelColorXY(start + xX, startY + hei_ - 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(wid_ - xX - 1, hei_ - yY - 1, col);
|
strip.setPixelColorXY(start + wid_ - xX - 1, startY + hei_ - yY - 1, col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WLEDMM setPixelColorXY(float x, float y, uint32_t col, ..) is depricated. use wu_pixel(x,y,col) instead.
|
||||||
// anti-aliased version of setPixelColorXY()
|
// anti-aliased version of setPixelColorXY()
|
||||||
void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa, bool fast) // WLEDMM some speedups due to fast int and faster sqrt16
|
void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa, bool fast) // WLEDMM some speedups due to fast int and faster sqrt16
|
||||||
{
|
{
|
||||||
if (Segment::maxHeight==1) return; // not a matrix set-up
|
if (Segment::maxHeight==1) return; // not a matrix set-up
|
||||||
if (x<0.0f || x>1.0f || y<0.0f || y>1.0f) return; // not normalized
|
if (x<0.0f || x>1.0f || y<0.0f || y>1.0f) return; // not normalized
|
||||||
|
|
||||||
|
#if 0 // depricated
|
||||||
const uint_fast16_t cols = virtualWidth();
|
const uint_fast16_t cols = virtualWidth();
|
||||||
const uint_fast16_t rows = virtualHeight();
|
const uint_fast16_t rows = virtualHeight();
|
||||||
|
|
||||||
@@ -383,10 +464,16 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa, bool fast
|
|||||||
} else {
|
} else {
|
||||||
setPixelColorXY(uint16_t(roundf(fX)), uint16_t(roundf(fY)), col);
|
setPixelColorXY(uint16_t(roundf(fX)), uint16_t(roundf(fY)), col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else // replacement using wu_pixel
|
||||||
|
unsigned px = x * (virtualWidth() <<8);
|
||||||
|
unsigned py = y * (virtualHeight() <<8);
|
||||||
|
wu_pixel(px, py, CRGB(col));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns RGBW values of pixel
|
// returns RGBW values of pixel
|
||||||
uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) {
|
uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const {
|
||||||
if (x<0 || y<0 || !isActive()) return 0; // not active or out-of range
|
if (x<0 || y<0 || !isActive()) return 0; // not active or out-of range
|
||||||
if (ledsrgb) {
|
if (ledsrgb) {
|
||||||
int i = XY(x,y);
|
int i = XY(x,y);
|
||||||
@@ -395,10 +482,11 @@ uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) {
|
|||||||
if (reverse ) x = virtualWidth() - x - 1;
|
if (reverse ) x = virtualWidth() - x - 1;
|
||||||
if (reverse_y) y = virtualHeight() - y - 1;
|
if (reverse_y) y = virtualHeight() - y - 1;
|
||||||
if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
||||||
x *= groupLength(); // expand to physical pixels
|
const uint_fast16_t groupLength_ = groupLength(); // WLEDMM small optimization
|
||||||
y *= groupLength(); // expand to physical pixels
|
x *= groupLength_; // expand to physical pixels
|
||||||
|
y *= groupLength_; // expand to physical pixels
|
||||||
if (x >= width() || y >= height()) return 0;
|
if (x >= width() || y >= height()) return 0;
|
||||||
return strip.getPixelColorXY(start + x, startY + y);
|
return strip.getPixelColorXYRestored(start + x, startY + y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blends the specified color with the existing pixel color.
|
// Blends the specified color with the existing pixel color.
|
||||||
@@ -409,17 +497,19 @@ void Segment::blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t
|
|||||||
|
|
||||||
// Adds the specified color with the existing pixel color perserving color balance.
|
// Adds the specified color with the existing pixel color perserving color balance.
|
||||||
void IRAM_ATTR_YN Segment::addPixelColorXY(int x, int y, uint32_t color, bool fast) {
|
void IRAM_ATTR_YN Segment::addPixelColorXY(int x, int y, uint32_t color, bool fast) {
|
||||||
if (!isActive()) return; // not active
|
// if (!isActive()) return; // not active //WLEDMM sanity check is repeated in getPixelColorXY / setPixelColorXY
|
||||||
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
|
// if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit //WLEDMM
|
||||||
uint32_t col = getPixelColorXY(x,y);
|
uint32_t oldCol = getPixelColorXY(x,y);
|
||||||
col = color_add(col, color, fast);
|
uint32_t col = color_add(oldCol, color, fast);
|
||||||
setPixelColorXY(x, y, col);
|
if (col != oldCol) setPixelColorXY(x, y, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Segment::fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) {
|
void Segment::fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) {
|
||||||
if (!isActive()) return; // not active
|
// if (!isActive()) return; // not active //WLEDMM sanity check is repeated in getPixelColorXY / setPixelColorXY
|
||||||
CRGB pix = CRGB(getPixelColorXY(x,y)).nscale8_video(fade);
|
CRGB pix = CRGB(getPixelColorXY(x,y));
|
||||||
setPixelColorXY(x, y, pix);
|
CRGB oldPix = pix;
|
||||||
|
pix = pix.nscale8_video(fade);
|
||||||
|
if (pix != oldPix) setPixelColorXY(int(x), int(y), pix);
|
||||||
}
|
}
|
||||||
|
|
||||||
// blurRow: perform a blur on a row of a rectangular matrix
|
// blurRow: perform a blur on a row of a rectangular matrix
|
||||||
@@ -521,7 +611,7 @@ void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
|
|||||||
for (int j = 0; j < dim1; j++) {
|
for (int j = 0; j < dim1; j++) {
|
||||||
int x = vertical ? i : j;
|
int x = vertical ? i : j;
|
||||||
int y = vertical ? j : i;
|
int y = vertical ? j : i;
|
||||||
setPixelColorXY(x, y, out[j]);
|
if (in[j] != out[j]) setPixelColorXY(x, y, out[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -635,19 +725,26 @@ void Segment::drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t col,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
|
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
|
||||||
void Segment::fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t col, bool soft) {
|
void Segment::fillCircle(unsigned cx, unsigned cy, int radius, uint32_t col, bool soft) {
|
||||||
if (!isActive() || radius == 0) return; // not active
|
if (!isActive() || radius <= 0) return; // not active
|
||||||
// draw soft bounding circle
|
// draw soft bounding circle
|
||||||
if (soft) drawCircle(cx, cy, radius, col, soft);
|
if (soft) drawCircle(cx, cy, radius, col, soft);
|
||||||
// fill it
|
|
||||||
const int cols = virtualWidth();
|
const int cols = virtualWidth();
|
||||||
const int rows = virtualHeight();
|
const int rows = virtualHeight();
|
||||||
for (int y = -radius; y <= radius; y++) {
|
|
||||||
for (int x = -radius; x <= radius; x++) {
|
const int_fast32_t maxRadius2 = radius * radius - (((radius > 3) && !soft) ? 1:0); // WLEDMM pre-compute r^2; '-1' removes spikes from bigger blobs
|
||||||
if (x * x + y * y <= radius * radius &&
|
// WLEDMM pre-compute boundaries
|
||||||
int16_t(cx)+x>=0 && int16_t(cy)+y>=0 &&
|
const int startx = max(-radius, -int(cx));
|
||||||
int16_t(cx)+x<cols && int16_t(cy)+y<rows)
|
const int endx = min(radius, cols-1-int(cx));
|
||||||
|
const int starty = max(-radius, -int(cy));
|
||||||
|
const int endy = min(radius, rows-1-int(cy));
|
||||||
|
|
||||||
|
// fill it - WLEDMM optimized
|
||||||
|
for (int y = starty; y <= endy; y++) {
|
||||||
|
for (int x = startx; x <= endx; x++) {
|
||||||
|
if ((x * x + y * y) <= maxRadius2) {
|
||||||
setPixelColorXY(cx + x, cy + y, col);
|
setPixelColorXY(cx + x, cy + y, col);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -674,7 +771,11 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
|||||||
uint32_t scaled_col = c;
|
uint32_t scaled_col = c;
|
||||||
if (simpleSegment) {
|
if (simpleSegment) {
|
||||||
// segment brightness must be pre-calculated for the "fast" setPixelColorXY variant!
|
// segment brightness must be pre-calculated for the "fast" setPixelColorXY variant!
|
||||||
|
#ifdef WLEDMM_FASTPATH
|
||||||
|
uint8_t _bri_t = _brightness;
|
||||||
|
#else
|
||||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
||||||
|
#endif
|
||||||
if (!_bri_t && !transitional) return;
|
if (!_bri_t && !transitional) return;
|
||||||
if (_bri_t < 255) scaled_col = color_fade(c, _bri_t);
|
if (_bri_t < 255) scaled_col = color_fade(c, _bri_t);
|
||||||
}
|
}
|
||||||
@@ -699,7 +800,7 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
|||||||
// single pixel (line length == 0)
|
// single pixel (line length == 0)
|
||||||
if (dx+dy == 0) {
|
if (dx+dy == 0) {
|
||||||
if (simpleSegment) setPixelColorXY_fast(x0, y0, c, scaled_col, cols, rows);
|
if (simpleSegment) setPixelColorXY_fast(x0, y0, c, scaled_col, cols, rows);
|
||||||
else setPixelColorXY(x0, y0, c);
|
else setPixelColorXY_slow(x0, y0, c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -735,7 +836,7 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
// if (x0 >= cols || y0 >= rows) break; // WLEDMM we hit the edge - should never happen
|
// if (x0 >= cols || y0 >= rows) break; // WLEDMM we hit the edge - should never happen
|
||||||
if (simpleSegment) setPixelColorXY_fast(x0, y0, c, scaled_col, cols, rows);
|
if (simpleSegment) setPixelColorXY_fast(x0, y0, c, scaled_col, cols, rows);
|
||||||
else setPixelColorXY(x0, y0, c);
|
else setPixelColorXY_slow(x0, y0, c);
|
||||||
if (x0==x1 && y0==y1) break;
|
if (x0==x1 && y0==y1) break;
|
||||||
int e2 = err;
|
int e2 = err;
|
||||||
if (e2 >-dx) { err -= dy; x0 += sx; }
|
if (e2 >-dx) { err -= dy; x0 += sx; }
|
||||||
@@ -744,27 +845,34 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Segment::drawArc(uint16_t x0, uint16_t y0, uint16_t radius, uint32_t color, uint32_t fillColor) {
|
void Segment::drawArc(unsigned x0, unsigned y0, int radius, uint32_t color, uint32_t fillColor) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive() || (radius <=0)) return; // not active
|
||||||
// float step = degrees / (2.85f*MAX(radius,1));
|
float minradius = float(radius) - .5;
|
||||||
// for (float rad = 0.0f; rad <= degrees+step/2; rad += step) {
|
float maxradius = float(radius) + .5;
|
||||||
// // may want to try float version as well (with or without antialiasing)
|
// WLEDMM pre-calculate values to speed up the loop
|
||||||
// int x = roundf(sin_t(rad) * radius);
|
const int minradius2 = roundf(minradius * minradius);
|
||||||
// int y = roundf(cos_t(rad) * radius);
|
const int maxradius2 = roundf(maxradius * maxradius);
|
||||||
// setPixelColorXY(x+x0, y+y0, c);
|
|
||||||
// }
|
|
||||||
float minradius = radius - .5;
|
|
||||||
float maxradius = radius + .5;
|
|
||||||
for (int x=0; x<virtualWidth(); x++) for (int y=0; y<virtualHeight(); y++) {
|
|
||||||
|
|
||||||
int newX = x - x0;
|
// WLEDMM only loop over surrounding square (50% faster)
|
||||||
int newY = y - y0;
|
const int width = virtualWidth();
|
||||||
|
const int height = virtualHeight();
|
||||||
|
const int startx = max(0, int(x0)-radius-1);
|
||||||
|
const int endx = min(width, int(x0)+radius+1);
|
||||||
|
const int starty = max(0, int(y0)-radius-1);
|
||||||
|
const int endy = min(height, int(y0)+radius+1);
|
||||||
|
|
||||||
if (newX*newX + newY*newY >= minradius * minradius && newX*newX + newY*newY <= maxradius * maxradius)
|
for (int x=startx; x<endx; x++) for (int y=starty; y<endy; y++) {
|
||||||
|
int newX2 = x - int(x0); newX2 *= newX2; // (distance from centerX) ^2
|
||||||
|
int newY2 = y - int(y0); newY2 *= newY2; // (distance from centerY) ^2
|
||||||
|
int distance2 = newX2 + newY2;
|
||||||
|
|
||||||
|
if ((distance2 >= minradius2) && (distance2 <= maxradius2)) {
|
||||||
setPixelColorXY(x, y, color);
|
setPixelColorXY(x, y, color);
|
||||||
|
} else {
|
||||||
if (fillColor != 0)
|
if (fillColor != 0)
|
||||||
if (newX*newX + newY*newY < minradius * minradius)
|
if (distance2 < minradius2)
|
||||||
setPixelColorXY(x, y, fillColor);
|
setPixelColorXY(x, y, fillColor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -814,7 +922,7 @@ bool Segment::jsonToPixels(char * name, uint8_t fileNr) {
|
|||||||
|
|
||||||
// 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) {
|
void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, bool drawShadow) {
|
||||||
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
|
||||||
@@ -824,6 +932,7 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w,
|
|||||||
|
|
||||||
CRGB col = CRGB(color);
|
CRGB col = CRGB(color);
|
||||||
CRGBPalette16 grad = CRGBPalette16(col, col2 ? CRGB(col2) : col);
|
CRGBPalette16 grad = CRGBPalette16(col, col2 ? CRGB(col2) : col);
|
||||||
|
uint32_t bgCol = SEGCOLOR(1);
|
||||||
|
|
||||||
//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
|
||||||
@@ -831,19 +940,39 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w,
|
|||||||
if (y0 < 0) continue; // drawing off-screen
|
if (y0 < 0) continue; // drawing off-screen
|
||||||
if (y0 >= rows) break; // drawing off-screen
|
if (y0 >= rows) break; // drawing off-screen
|
||||||
uint8_t bits = 0;
|
uint8_t bits = 0;
|
||||||
|
uint8_t bits_up = 0; // WLEDMM this is the previous line: font[(chr * h) + i -1]
|
||||||
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]);
|
||||||
case 40: bits = pgm_read_byte_near(&console_font_5x8[(chr * h) + i]); break; // 5x8 font
|
if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_4x6[(chr * h) + i -1]);
|
||||||
case 48: bits = pgm_read_byte_near(&console_font_6x8[(chr * h) + i]); break; // 6x8 font
|
break; // 5x8 font
|
||||||
case 63: bits = pgm_read_byte_near(&console_font_7x9[(chr * h) + i]); break; // 7x9 font
|
case 40: bits = pgm_read_byte_near(&console_font_5x8[(chr * h) + i]);
|
||||||
case 60: bits = pgm_read_byte_near(&console_font_5x12[(chr * h) + i]); break; // 5x12 font
|
if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_5x8[(chr * h) + i -1]);
|
||||||
|
break; // 5x8 font
|
||||||
|
case 48: bits = pgm_read_byte_near(&console_font_6x8[(chr * h) + i]);
|
||||||
|
if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_6x8[(chr * h) + i -1]);
|
||||||
|
break; // 6x8 font
|
||||||
|
case 63: bits = pgm_read_byte_near(&console_font_7x9[(chr * h) + i]);
|
||||||
|
if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_7x9[(chr * h) + i -1]);
|
||||||
|
break; // 7x9 font
|
||||||
|
case 60: bits = pgm_read_byte_near(&console_font_5x12[(chr * h) + i]);
|
||||||
|
if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_5x12[(chr * h) + i -1]);
|
||||||
|
break; // 5x12 font
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
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
|
||||||
int16_t x0 = x + (w-1) - j;
|
int16_t x0 = x + (w-1) - j;
|
||||||
if ((x0 >= 0 || x0 < cols) && ((bits>>(j+(8-w))) & 0x01)) { // bit set & drawing on-screen
|
if ((x0 >= 0) || (x0 < cols)) {
|
||||||
|
if ((bits>>(j+(8-w))) & 0x01) { // bit set & drawing on-screen
|
||||||
setPixelColorXY(x0, y0, col);
|
setPixelColorXY(x0, y0, col);
|
||||||
|
} else {
|
||||||
|
if (drawShadow) {
|
||||||
|
// WLEDMM
|
||||||
|
if ((j < (w-1)) && (bits>>(j+(8-w) +1)) & 0x01) setPixelColorXY(x0, y0, bgCol); // blank when pixel to the right is set
|
||||||
|
else if ((j > 0) && (bits>>(j+(8-w) -1)) & 0x01) setPixelColorXY(x0, y0, bgCol);// blank when pixel to the left is set
|
||||||
|
else if ((bits_up>>(j+(8-w))) & 0x01) setPixelColorXY(x0, y0, bgCol); // blank when pixel above is set
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -859,11 +988,14 @@ void Segment::wu_pixel(uint32_t x, uint32_t y, CRGB c) { //awesome wu_pixel
|
|||||||
WU_WEIGHT(ix, yy), WU_WEIGHT(xx, yy)};
|
WU_WEIGHT(ix, yy), WU_WEIGHT(xx, yy)};
|
||||||
// multiply the intensities by the colour, and saturating-add them to the pixels
|
// multiply the intensities by the colour, and saturating-add them to the pixels
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
CRGB led = getPixelColorXY((x >> 8) + (i & 1), (y >> 8) + ((i >> 1) & 1));
|
int wu_x = (x >> 8) + (i & 1); // WLEDMM precalculate x
|
||||||
|
int wu_y = (y >> 8) + ((i >> 1) & 1); // WLEDMM precalculate y
|
||||||
|
CRGB led = getPixelColorXY(wu_x, wu_y);
|
||||||
|
CRGB oldLed = led;
|
||||||
led.r = qadd8(led.r, c.r * wu[i] >> 8);
|
led.r = qadd8(led.r, c.r * wu[i] >> 8);
|
||||||
led.g = qadd8(led.g, c.g * wu[i] >> 8);
|
led.g = qadd8(led.g, c.g * wu[i] >> 8);
|
||||||
led.b = qadd8(led.b, c.b * wu[i] >> 8);
|
led.b = qadd8(led.b, c.b * wu[i] >> 8);
|
||||||
setPixelColorXY(int((x >> 8) + (i & 1)), int((y >> 8) + ((i >> 1) & 1)), led);
|
if (led != oldLed) setPixelColorXY(wu_x, wu_y, led); // WLEDMM don't repaint same color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#undef WU_WEIGHT
|
#undef WU_WEIGHT
|
||||||
|
|||||||
@@ -102,6 +102,11 @@ Segment::Segment(const Segment &orig) {
|
|||||||
DEBUG_PRINTLN(F("-- Copy segment constructor --"));
|
DEBUG_PRINTLN(F("-- Copy segment constructor --"));
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment)); //WLEDMM copy to this
|
memcpy((void*)this, (void*)&orig, sizeof(Segment)); //WLEDMM copy to this
|
||||||
transitional = false; // copied segment cannot be in transition
|
transitional = false; // copied segment cannot be in transition
|
||||||
|
// WLEDMM temporarily prevent any fast draw calls to the new segment
|
||||||
|
// _isValid2D = false;
|
||||||
|
_isSimpleSegment = false;
|
||||||
|
_isSuperSimpleSegment = false;
|
||||||
|
|
||||||
name = nullptr;
|
name = nullptr;
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
_dataLen = 0;
|
_dataLen = 0;
|
||||||
@@ -132,7 +137,7 @@ void Segment::allocLeds() {
|
|||||||
ledsrgbSize = ledsrgb?size:0;
|
ledsrgbSize = ledsrgb?size:0;
|
||||||
if (ledsrgb == nullptr) {
|
if (ledsrgb == nullptr) {
|
||||||
USER_PRINTLN("allocLeds failed!!");
|
USER_PRINTLN("allocLeds failed!!");
|
||||||
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
|
errorFlag = ERR_LOW_BUF; // WLEDMM raise errorflag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -143,8 +148,17 @@ void Segment::allocLeds() {
|
|||||||
// move constructor --> moves everything (including buffer) from orig to this
|
// move constructor --> moves everything (including buffer) from orig to this
|
||||||
Segment::Segment(Segment &&orig) noexcept {
|
Segment::Segment(Segment &&orig) noexcept {
|
||||||
DEBUG_PRINTLN(F("-- Move segment constructor --"));
|
DEBUG_PRINTLN(F("-- Move segment constructor --"));
|
||||||
|
|
||||||
|
// WLEDMM temporarily prevent any fast draw calls to old and new segment
|
||||||
|
orig._isSimpleSegment = false;
|
||||||
|
orig._isSuperSimpleSegment = false;
|
||||||
|
|
||||||
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
|
||||||
|
#ifdef WLEDMM_FASTPATH
|
||||||
|
// WLEDMM prevent any draw calls to old segment
|
||||||
|
orig._isValid2D = false;
|
||||||
|
#endif
|
||||||
orig.name = nullptr;
|
orig.name = nullptr;
|
||||||
orig.data = nullptr;
|
orig.data = nullptr;
|
||||||
orig._dataLen = 0;
|
orig._dataLen = 0;
|
||||||
@@ -169,6 +183,12 @@ Segment& Segment::operator= (const Segment &orig) {
|
|||||||
// copy source
|
// copy source
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
transitional = false;
|
transitional = false;
|
||||||
|
|
||||||
|
// WLEDMM prevent any fast draw calls to this segment until the next frame starts
|
||||||
|
//_isValid2D = false;
|
||||||
|
_isSimpleSegment = false;
|
||||||
|
_isSuperSimpleSegment = false;
|
||||||
|
|
||||||
// erase pointers to allocated data
|
// erase pointers to allocated data
|
||||||
name = nullptr;
|
name = nullptr;
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
@@ -196,7 +216,16 @@ Segment& Segment::operator= (Segment &&orig) noexcept {
|
|||||||
deallocateData(); // free old runtime data
|
deallocateData(); // free old runtime data
|
||||||
if (_t) { delete _t; _t = nullptr; }
|
if (_t) { delete _t; _t = nullptr; }
|
||||||
if (ledsrgb && !Segment::_globalLeds) free(ledsrgb); //WLEDMM: not needed anymore as we will use leds from copy. no need to nullify ledsrgb as it gets new value in memcpy
|
if (ledsrgb && !Segment::_globalLeds) free(ledsrgb); //WLEDMM: not needed anymore as we will use leds from copy. no need to nullify ledsrgb as it gets new value in memcpy
|
||||||
|
|
||||||
|
// WLEDMM temporarily prevent any fast draw calls to old and new segment
|
||||||
|
orig._isSimpleSegment = false;
|
||||||
|
orig._isSuperSimpleSegment = false;
|
||||||
|
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
|
#ifdef WLEDMM_FASTPATH
|
||||||
|
// WLEDMM temporarily prevent any draw calls to old segment
|
||||||
|
orig._isValid2D = false;
|
||||||
|
#endif
|
||||||
orig.name = nullptr;
|
orig.name = nullptr;
|
||||||
orig.data = nullptr;
|
orig.data = nullptr;
|
||||||
orig._dataLen = 0;
|
orig._dataLen = 0;
|
||||||
@@ -266,6 +295,7 @@ void Segment::resetIfRequired() {
|
|||||||
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; // setOption(SEG_OPTION_RESET, false);
|
reset = false; // setOption(SEG_OPTION_RESET, false);
|
||||||
|
startFrame(); // WLEDMM update cached propoerties
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,15 +594,11 @@ void Segment::setOption(uint8_t n, bool val) {
|
|||||||
if (!(n == SEG_OPTION_SELECTED || n == SEG_OPTION_RESET || n == SEG_OPTION_TRANSITIONAL)) stateChanged = true; // send UDP/WS broadcast
|
if (!(n == SEG_OPTION_SELECTED || n == SEG_OPTION_RESET || n == SEG_OPTION_TRANSITIONAL)) stateChanged = true; // send UDP/WS broadcast
|
||||||
}
|
}
|
||||||
|
|
||||||
void Segment::setMode(uint8_t fx, bool loadDefaults) {
|
void Segment::setMode(uint8_t fx, bool loadDefaults, bool sliderDefaultsOnly) {
|
||||||
//WLEDMM: return to old setting if not explicitly set
|
//WLEDMM: return to old setting if not explicitly set
|
||||||
static int16_t oldMap = -1;
|
static int16_t oldMap = -1;
|
||||||
static int16_t oldSim = -1;
|
static int16_t oldSim = -1;
|
||||||
static int16_t oldPalette = -1;
|
static int16_t oldPalette = -1;
|
||||||
static byte oldReverse = -1;
|
|
||||||
static byte oldMirror = -1;
|
|
||||||
static byte oldReverse_y = -1;
|
|
||||||
static byte oldMirror_y = -1;
|
|
||||||
// if we have a valid mode & is not reserved
|
// if we have a valid mode & is not reserved
|
||||||
if (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4)) {
|
if (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4)) {
|
||||||
if (fx != mode) {
|
if (fx != mode) {
|
||||||
@@ -591,14 +617,16 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
|
|||||||
sOpt = extractModeDefaults(fx, "o1"); check1 = (sOpt >= 0) ? (bool)sOpt : false;
|
sOpt = extractModeDefaults(fx, "o1"); check1 = (sOpt >= 0) ? (bool)sOpt : false;
|
||||||
sOpt = extractModeDefaults(fx, "o2"); check2 = (sOpt >= 0) ? (bool)sOpt : false;
|
sOpt = extractModeDefaults(fx, "o2"); check2 = (sOpt >= 0) ? (bool)sOpt : false;
|
||||||
sOpt = extractModeDefaults(fx, "o3"); check3 = (sOpt >= 0) ? (bool)sOpt : false;
|
sOpt = extractModeDefaults(fx, "o3"); check3 = (sOpt >= 0) ? (bool)sOpt : false;
|
||||||
//WLEDMM: return to old setting if not explicitly set
|
if (!sliderDefaultsOnly) {
|
||||||
sOpt = extractModeDefaults(fx, "m12"); if (sOpt >= 0) {if (oldMap==-1) oldMap = map1D2D; map1D2D = constrain(sOpt, 0, 7);} else {if (oldMap!=-1) map1D2D = oldMap; oldMap = -1;}
|
//WLEDMM: return to old setting if not explicitly set
|
||||||
sOpt = extractModeDefaults(fx, "si"); if (sOpt >= 0) {if (oldSim==-1) oldSim = soundSim; soundSim = constrain(sOpt, 0, 1);} else {if (oldSim!=-1) soundSim = oldSim; oldSim = -1;}
|
sOpt = extractModeDefaults(fx, "m12"); if (sOpt >= 0) {if (oldMap==-1) oldMap = map1D2D; map1D2D = constrain(sOpt, 0, 7);} else {if (oldMap!=-1) map1D2D = oldMap; oldMap = -1;}
|
||||||
sOpt = extractModeDefaults(fx, "rev"); if (sOpt >= 0) {if (oldReverse==-1) oldReverse = reverse; reverse = (bool)sOpt;} else {if (oldReverse!=-1) reverse = oldReverse==1; oldReverse = -1;}
|
sOpt = extractModeDefaults(fx, "si"); if (sOpt >= 0) {if (oldSim==-1) oldSim = soundSim; soundSim = constrain(sOpt, 0, 1);} else {if (oldSim!=-1) soundSim = oldSim; oldSim = -1;}
|
||||||
sOpt = extractModeDefaults(fx, "mi"); if (sOpt >= 0) {if (oldMirror==-1) oldMirror = mirror; mirror = (bool)sOpt;} else {if (oldMirror!=-1) mirror = oldMirror==1; oldMirror = -1;} // NOTE: setting this option is a risky business
|
sOpt = extractModeDefaults(fx, "rev"); if (sOpt >= 0) reverse = (bool)sOpt;
|
||||||
sOpt = extractModeDefaults(fx, "rY"); if (sOpt >= 0) {if (oldReverse_y==-1) oldReverse_y = reverse_y; reverse_y = (bool)sOpt;} else {if (oldReverse_y!=-1) reverse_y = oldReverse_y==1; oldReverse_y = -1;}
|
sOpt = extractModeDefaults(fx, "mi"); if (sOpt >= 0) mirror = (bool)sOpt; // NOTE: setting this option is a risky business
|
||||||
sOpt = extractModeDefaults(fx, "mY"); if (sOpt >= 0) {if (oldMirror_y==-1) oldMirror_y = mirror_y; mirror_y = (bool)sOpt;} else {if (oldMirror_y!=-1) mirror_y = oldMirror_y==1; oldMirror_y = -1;} // NOTE: setting this option is a risky business
|
sOpt = extractModeDefaults(fx, "rY"); if (sOpt >= 0) reverse_y = (bool)sOpt;
|
||||||
sOpt = extractModeDefaults(fx, "pal"); if (sOpt >= 0) {if (oldPalette==-1) oldPalette = palette; setPalette(sOpt);} else {if (oldPalette!=-1) setPalette(oldPalette); oldPalette = -1;}
|
sOpt = extractModeDefaults(fx, "mY"); if (sOpt >= 0) mirror_y = (bool)sOpt; // NOTE: setting this option is a risky business
|
||||||
|
sOpt = extractModeDefaults(fx, "pal"); if (sOpt >= 0) {if (oldPalette==-1) oldPalette = palette; setPalette(sOpt);} else {if (oldPalette!=-1) setPalette(oldPalette); oldPalette = -1;}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!fadeTransition) markForReset(); // WLEDMM quickfix for effect "double startup" bug. -> only works when "Crossfade" is disabled (led settings)
|
if (!fadeTransition) markForReset(); // WLEDMM quickfix for effect "double startup" bug. -> only works when "Crossfade" is disabled (led settings)
|
||||||
stateChanged = true; // send UDP/WS broadcast
|
stateChanged = true; // send UDP/WS broadcast
|
||||||
@@ -673,7 +701,11 @@ class JMapC {
|
|||||||
if (size > 0)
|
if (size > 0)
|
||||||
return size;
|
return size;
|
||||||
else
|
else
|
||||||
|
#ifndef WLEDMM_FASTPATH
|
||||||
return SEGMENT.virtualWidth() * SEGMENT.virtualHeight(); //pixels
|
return SEGMENT.virtualWidth() * SEGMENT.virtualHeight(); //pixels
|
||||||
|
#else
|
||||||
|
return SEGMENT.calc_virtualWidth() * SEGMENT.calc_virtualHeight(); // calc pixel sizes
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
void setPixelColor(uint16_t i, uint32_t col) {
|
void setPixelColor(uint16_t i, uint32_t col) {
|
||||||
updatejMapDoc();
|
updatejMapDoc();
|
||||||
@@ -765,7 +797,11 @@ class JMapC {
|
|||||||
jMapFile.close();
|
jMapFile.close();
|
||||||
|
|
||||||
maxWidth++; maxHeight++;
|
maxWidth++; maxHeight++;
|
||||||
|
#ifndef WLEDMM_FASTPATH
|
||||||
scale = min(SEGMENT.virtualWidth() / maxWidth, SEGMENT.virtualHeight() / maxHeight); // WLEDMM use native min/max
|
scale = min(SEGMENT.virtualWidth() / maxWidth, SEGMENT.virtualHeight() / maxHeight); // WLEDMM use native min/max
|
||||||
|
#else
|
||||||
|
scale = min(SEGMENT.calc_virtualWidth() / maxWidth, SEGMENT.calc_virtualHeight() / maxHeight); // WLEDMM re-calc width/heiht from active settings
|
||||||
|
#endif
|
||||||
dataSize += sizeof(jVectorMap);
|
dataSize += sizeof(jVectorMap);
|
||||||
USER_PRINT("dataSize ");
|
USER_PRINT("dataSize ");
|
||||||
USER_PRINT(dataSize);
|
USER_PRINT(dataSize);
|
||||||
@@ -803,10 +839,13 @@ constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big"
|
|||||||
constexpr int Pinwheel_Steps_Big = 304; // no holes up to 50x50
|
constexpr int Pinwheel_Steps_Big = 304; // no holes up to 50x50
|
||||||
constexpr int Pinwheel_Size_Big = 50; // larger than this -> use "XL"
|
constexpr int Pinwheel_Size_Big = 50; // larger than this -> use "XL"
|
||||||
constexpr int Pinwheel_Steps_XL = 368;
|
constexpr int Pinwheel_Steps_XL = 368;
|
||||||
|
constexpr int Pinwheel_Size_XL = 58; // larger than this -> use "XXL"
|
||||||
|
constexpr int Pinwheel_Steps_XXL = 456;
|
||||||
constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...72 to Radians
|
constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...72 to Radians
|
||||||
constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...192 to Radians
|
constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...192 to Radians
|
||||||
constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...304 to Radians
|
constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...304 to Radians
|
||||||
constexpr float Int_to_Rad_XL = (DEG_TO_RAD * 360) / Pinwheel_Steps_XL; // conversion: from 0...368 to Radians
|
constexpr float Int_to_Rad_XL = (DEG_TO_RAD * 360) / Pinwheel_Steps_XL; // conversion: from 0...368 to Radians
|
||||||
|
constexpr float Int_to_Rad_XXL = (DEG_TO_RAD * 360) / Pinwheel_Steps_XXL; // conversion: from 0...456 to Radians
|
||||||
|
|
||||||
constexpr int Fixed_Scale = 512; // fixpoint scaling factor (9bit for fraction)
|
constexpr int Fixed_Scale = 512; // fixpoint scaling factor (9bit for fraction)
|
||||||
|
|
||||||
@@ -816,8 +855,9 @@ static float getPinwheelAngle(int i, int vW, int vH) {
|
|||||||
if (maxXY <= Pinwheel_Size_Small) return float(i) * Int_to_Rad_Small;
|
if (maxXY <= Pinwheel_Size_Small) return float(i) * Int_to_Rad_Small;
|
||||||
if (maxXY <= Pinwheel_Size_Medium) return float(i) * Int_to_Rad_Med;
|
if (maxXY <= Pinwheel_Size_Medium) return float(i) * Int_to_Rad_Med;
|
||||||
if (maxXY <= Pinwheel_Size_Big) return float(i) * Int_to_Rad_Big;
|
if (maxXY <= Pinwheel_Size_Big) return float(i) * Int_to_Rad_Big;
|
||||||
|
if (maxXY <= Pinwheel_Size_XL) return float(i) * Int_to_Rad_XL;
|
||||||
// else
|
// else
|
||||||
return float(i) * Int_to_Rad_XL;
|
return float(i) * Int_to_Rad_XXL;
|
||||||
}
|
}
|
||||||
// Pinwheel helper function: matrix dimensions to number of rays
|
// Pinwheel helper function: matrix dimensions to number of rays
|
||||||
static int getPinwheelLength(int vW, int vH) {
|
static int getPinwheelLength(int vW, int vH) {
|
||||||
@@ -825,8 +865,9 @@ static int getPinwheelLength(int vW, int vH) {
|
|||||||
if (maxXY <= Pinwheel_Size_Small) return Pinwheel_Steps_Small;
|
if (maxXY <= Pinwheel_Size_Small) return Pinwheel_Steps_Small;
|
||||||
if (maxXY <= Pinwheel_Size_Medium) return Pinwheel_Steps_Medium;
|
if (maxXY <= Pinwheel_Size_Medium) return Pinwheel_Steps_Medium;
|
||||||
if (maxXY <= Pinwheel_Size_Big) return Pinwheel_Steps_Big;
|
if (maxXY <= Pinwheel_Size_Big) return Pinwheel_Steps_Big;
|
||||||
|
if (maxXY <= Pinwheel_Size_XL) return Pinwheel_Steps_XL;
|
||||||
// else
|
// else
|
||||||
return Pinwheel_Steps_XL;
|
return Pinwheel_Steps_XXL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -873,7 +914,7 @@ uint16_t Segment::virtualLength() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//WLEDMM used for M12_sBlock
|
//WLEDMM used for M12_sBlock
|
||||||
void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16_t vH, uint16_t vStrip) {
|
static void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16_t vH, uint16_t vStrip) {
|
||||||
float i2;
|
float i2;
|
||||||
if (i<=SEGLEN*0.25) { //top, left to right
|
if (i<=SEGLEN*0.25) { //top, left to right
|
||||||
i2 = i/(SEGLEN*0.25);
|
i2 = i/(SEGLEN*0.25);
|
||||||
@@ -898,7 +939,7 @@ void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16_t vH,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
|
void IRAM_ATTR_YN __attribute__((hot)) Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
|
||||||
{
|
{
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
@@ -927,42 +968,51 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATT
|
|||||||
if (i==0)
|
if (i==0)
|
||||||
setPixelColorXY(0, 0, col);
|
setPixelColorXY(0, 0, col);
|
||||||
else {
|
else {
|
||||||
//WLEDMM: drawArc(0, 0, i, col); could work as alternative
|
if (!_isSuperSimpleSegment) {
|
||||||
|
// WLEDMM: drawArc() is faster if it's NOT "super simple" as the regular M12_pArc
|
||||||
|
// can do "useSymmetry" to speed things along, but a more complicated segment likey
|
||||||
|
// uses mirroring which generates a symmetry speed-up, or other things which mean
|
||||||
|
// less pixels are calculated.
|
||||||
|
drawArc(0, 0, i, col);
|
||||||
|
} else {
|
||||||
|
//WLEDMM: some optimizations for the drawing loop
|
||||||
|
// pre-calculate loop limits, exploit symmetry at 45deg
|
||||||
|
float radius = float(i);
|
||||||
|
|
||||||
|
// float step = HALF_PI / (2.85f * radius); // upstream uses this
|
||||||
|
float step = HALF_PI / (M_PI * radius); // WLEDMM we use the correct circumference
|
||||||
|
bool useSymmetry = (max(vH, vW) > 20); // for segments wider than 20 pixels, we exploit symmetry
|
||||||
|
unsigned numSteps;
|
||||||
|
if (useSymmetry) numSteps = 1 + ((HALF_PI/2.0f + step/2.0f) / step); // with symmetry
|
||||||
|
else numSteps = 1 + ((HALF_PI + step/2.0f) / step); // without symmetry
|
||||||
|
|
||||||
//WLEDMM: some optimizations for the drawing loop
|
float rad = 0.0f;
|
||||||
// pre-calculate loop limits, exploit symmetry at 45deg
|
for (unsigned count = 0; count < numSteps; count++) {
|
||||||
float radius = float(i);
|
// may want to try float version as well (with or without antialiasing)
|
||||||
// float step = HALF_PI / (2.85f * radius); // upstream uses this
|
// int x = max(0, min(vW-1, (int)roundf(sinf(rad) * radius)));
|
||||||
float step = HALF_PI / (M_PI * radius); // WLEDMM we use the correct circumference
|
// int y = max(0, min(vH-1, (int)roundf(cosf(rad) * radius)));
|
||||||
bool useSymmetry = (max(vH, vW) > 20); // for segments wider than 20 pixels, we exploit symmetry
|
int x = roundf(sinf(rad) * radius);
|
||||||
unsigned numSteps;
|
int y = roundf(cosf(rad) * radius);
|
||||||
if (useSymmetry) numSteps = 1 + ((HALF_PI/2.0f + step/2.0f) / step); // with symmetry
|
setPixelColorXY(x, y, col);
|
||||||
else numSteps = 1 + ((HALF_PI + step/2.0f) / step); // without symmetry
|
if(useSymmetry) setPixelColorXY(y, x, col);// WLEDMM
|
||||||
|
rad += step;
|
||||||
|
}
|
||||||
|
|
||||||
float rad = 0.0f;
|
// // Bresenham’s Algorithm (may not fill every pixel)
|
||||||
for (unsigned count = 0; count < numSteps; count++) {
|
// int d = 3 - (2*i);
|
||||||
// may want to try float version as well (with or without antialiasing)
|
// int y = i, x = 0;
|
||||||
int x = roundf(sinf(rad) * radius);
|
// while (y >= x) {
|
||||||
int y = roundf(cosf(rad) * radius);
|
// setPixelColorXY(x, y, col);
|
||||||
setPixelColorXY(x, y, col);
|
// setPixelColorXY(y, x, col);
|
||||||
if(useSymmetry) setPixelColorXY(y, x, col);// WLEDMM
|
// x++;
|
||||||
rad += step;
|
// if (d > 0) {
|
||||||
|
// y--;
|
||||||
|
// d += 4 * (x - y) + 10;
|
||||||
|
// } else {
|
||||||
|
// d += 4 * x + 6;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bresenham’s Algorithm (may not fill every pixel)
|
|
||||||
//int d = 3 - (2*i);
|
|
||||||
//int y = i, x = 0;
|
|
||||||
//while (y >= x) {
|
|
||||||
// setPixelColorXY(x, y, col);
|
|
||||||
// setPixelColorXY(y, x, col);
|
|
||||||
// x++;
|
|
||||||
// if (d > 0) {
|
|
||||||
// y--;
|
|
||||||
// d += 4 * (x - y) + 10;
|
|
||||||
// } else {
|
|
||||||
// d += 4 * x + 6;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case M12_pCorner: {
|
case M12_pCorner: {
|
||||||
@@ -1057,7 +1107,7 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATT
|
|||||||
// set pixel
|
// set pixel
|
||||||
if (x != lastX || y != lastY) { // only paint if pixel position is different
|
if (x != lastX || y != lastY) { // only paint if pixel position is different
|
||||||
if (simpleSegment) setPixelColorXY_fast(x, y, col, scaled_col, vW, vH);
|
if (simpleSegment) setPixelColorXY_fast(x, y, col, scaled_col, vW, vH);
|
||||||
else setPixelColorXY(x, y, col);
|
else setPixelColorXY_slow(x, y, col);
|
||||||
}
|
}
|
||||||
lastX = x;
|
lastX = x;
|
||||||
lastY = y;
|
lastY = y;
|
||||||
@@ -1162,7 +1212,7 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Segment::getPixelColor(int i)
|
uint32_t __attribute__((hot)) Segment::getPixelColor(int i) const
|
||||||
{
|
{
|
||||||
if (!isActive()) return 0; // not active
|
if (!isActive()) return 0; // not active
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
@@ -1254,7 +1304,7 @@ uint32_t Segment::getPixelColor(int i)
|
|||||||
if (offset < INT16_MAX) i += offset; // WLEDMM
|
if (offset < INT16_MAX) i += offset; // WLEDMM
|
||||||
if ((i >= stop) && (stop>0)) i -= length(); // WLEDMM avoid negative index (stop = 0 is a possible value)
|
if ((i >= stop) && (stop>0)) i -= length(); // WLEDMM avoid negative index (stop = 0 is a possible value)
|
||||||
if (i<0) i=0; // WLEDMM just to be 100% sure
|
if (i<0) i=0; // WLEDMM just to be 100% sure
|
||||||
return strip.getPixelColor(i);
|
return strip.getPixelColorRestored(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Segment::differs(Segment& b) const {
|
uint8_t Segment::differs(Segment& b) const {
|
||||||
@@ -1336,8 +1386,20 @@ void Segment::refreshLightCapabilities() {
|
|||||||
/*
|
/*
|
||||||
* Fills segment with color - WLEDMM using faster sPC if possible
|
* Fills segment with color - WLEDMM using faster sPC if possible
|
||||||
*/
|
*/
|
||||||
void Segment::fill(uint32_t c) {
|
void __attribute__((hot)) Segment::fill(uint32_t c) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
|
|
||||||
|
#if 0 && defined(WLED_ENABLE_HUB75MATRIX) && defined(WLEDMM_FASTPATH)
|
||||||
|
// DIRTY HACK - this ignores the first fill(black) in each frame, knowing that HUB75 has already blanked out the display.
|
||||||
|
if (_firstFill) {
|
||||||
|
_firstFill = false;
|
||||||
|
if (c == BLACK) {
|
||||||
|
if (ledsrgb && ledsrgbSize > 0) memset(ledsrgb, 0, ledsrgbSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
|
const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
|
||||||
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
|
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
|
||||||
|
|
||||||
@@ -1351,12 +1413,12 @@ void Segment::fill(uint32_t c) {
|
|||||||
if (_bri_t < 255) scaled_col = color_fade(c, _bri_t);
|
if (_bri_t < 255) scaled_col = color_fade(c, _bri_t);
|
||||||
}
|
}
|
||||||
// fill 2D segment
|
// fill 2D segment
|
||||||
for(int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
for(unsigned y = 0; y < rows; y++) for (unsigned x = 0; x < cols; x++) {
|
||||||
if (simpleSegment) setPixelColorXY_fast(x, y, c, scaled_col, cols, rows);
|
if (simpleSegment) setPixelColorXY_fast(x, y, c, scaled_col, cols, rows);
|
||||||
else setPixelColorXY(x, y, c);
|
else setPixelColorXY_slow(x, y, c);
|
||||||
}
|
}
|
||||||
} else { // fill 1D strip
|
} else { // fill 1D strip
|
||||||
for (int x = 0; x < cols; x++) setPixelColor(x, c);
|
for (unsigned x = 0; x < cols; x++) setPixelColor(int(x), c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1395,7 +1457,7 @@ void Segment::fadePixelColor(uint16_t n, uint8_t fade) {
|
|||||||
/*
|
/*
|
||||||
* fade out function, higher rate = quicker fade
|
* fade out function, higher rate = quicker fade
|
||||||
*/
|
*/
|
||||||
void Segment::fade_out(uint8_t rate) {
|
void __attribute__((hot)) Segment::fade_out(uint8_t rate) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
|
const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
|
||||||
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
|
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
|
||||||
@@ -1409,8 +1471,8 @@ void Segment::fade_out(uint8_t rate) {
|
|||||||
int g2 = G(color2);
|
int g2 = G(color2);
|
||||||
int b2 = B(color2);
|
int b2 = B(color2);
|
||||||
|
|
||||||
for (uint_fast16_t y = 0; y < rows; y++) for (uint_fast16_t x = 0; x < cols; x++) {
|
for (unsigned y = 0; y < rows; y++) for (unsigned x = 0; x < cols; x++) {
|
||||||
uint32_t color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x);
|
uint32_t color = is2D() ? getPixelColorXY(int(x), int(y)) : getPixelColor(int(x));
|
||||||
if (color == color2) continue; // WLEDMM speedup - pixel color = target color, so nothing to do
|
if (color == color2) continue; // WLEDMM speedup - pixel color = target color, so nothing to do
|
||||||
int w1 = W(color);
|
int w1 = W(color);
|
||||||
int r1 = R(color);
|
int r1 = R(color);
|
||||||
@@ -1427,15 +1489,17 @@ void Segment::fade_out(uint8_t rate) {
|
|||||||
rdelta += (r2 == r1) ? 0 : (r2 > r1) ? 1 : -1;
|
rdelta += (r2 == r1) ? 0 : (r2 > r1) ? 1 : -1;
|
||||||
gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1;
|
gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1;
|
||||||
bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 1 : -1;
|
bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 1 : -1;
|
||||||
|
uint32_t colorNew = RGBW32(r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta); // WLEDMM
|
||||||
|
|
||||||
//if ((wdelta == 0) && (rdelta == 0) && (gdelta == 0) && (bdelta == 0)) continue; // WLEDMM delta = zero => no change // causes problem with text overlay
|
if (colorNew != color) { // WLEDMM speedup - do not repaint the same color
|
||||||
if (is2D()) setPixelColorXY((uint16_t)x, (uint16_t)y, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
|
if (is2D()) setPixelColorXY(int(x), int(y), colorNew);
|
||||||
else setPixelColor((uint16_t)x, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
|
else setPixelColor(int(x), colorNew);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fades all pixels to black using nscale8()
|
// fades all pixels to black using nscale8()
|
||||||
void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
void __attribute__((hot)) Segment::fadeToBlackBy(uint8_t fadeBy) {
|
||||||
if (!isActive() || fadeBy == 0) return; // optimization - no scaling to apply
|
if (!isActive() || fadeBy == 0) return; // optimization - no scaling to apply
|
||||||
const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
|
const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
|
||||||
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
|
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
|
||||||
@@ -1443,8 +1507,13 @@ void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
|||||||
|
|
||||||
// WLEDMM minor optimization
|
// WLEDMM minor optimization
|
||||||
if(is2D()) {
|
if(is2D()) {
|
||||||
for (uint_fast16_t y = 0; y < rows; y++) for (uint_fast16_t x = 0; x < cols; x++) {
|
for (unsigned y = 0; y < rows; y++) for (unsigned x = 0; x < cols; x++) {
|
||||||
setPixelColorXY((uint16_t)x, (uint16_t)y, CRGB(getPixelColorXY(x,y)).nscale8(scaledown));
|
uint32_t cc = getPixelColorXY(int(x),int(y)); // WLEDMM avoid RGBW32 -> CRGB -> RGBW32 conversion
|
||||||
|
uint32_t cc2 = color_fade(cc, scaledown); // fade
|
||||||
|
#ifdef WLEDMM_FASTPATH
|
||||||
|
if (cc2 != cc) // WLEDMM only re-paint if faded color is different - normally disabled - causes problem with text overlay
|
||||||
|
#endif
|
||||||
|
setPixelColorXY(int(x), int(y), cc2);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (uint_fast16_t x = 0; x < cols; x++) {
|
for (uint_fast16_t x = 0; x < cols; x++) {
|
||||||
@@ -1456,7 +1525,7 @@ void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
|||||||
/*
|
/*
|
||||||
* blurs segment content, source: FastLED colorutils.cpp
|
* blurs segment content, source: FastLED colorutils.cpp
|
||||||
*/
|
*/
|
||||||
void Segment::blur(uint8_t blur_amount, bool smear) {
|
void __attribute__((hot)) Segment::blur(uint8_t blur_amount, bool smear) {
|
||||||
if (!isActive() || blur_amount == 0) return; // optimization: 0 means "don't blur"
|
if (!isActive() || blur_amount == 0) return; // optimization: 0 means "don't blur"
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
if (is2D()) {
|
if (is2D()) {
|
||||||
@@ -1517,7 +1586,7 @@ uint32_t Segment::color_wheel(uint8_t pos) {
|
|||||||
/*
|
/*
|
||||||
* Returns a new, random wheel index with a minimum distance of 42 from pos.
|
* Returns a new, random wheel index with a minimum distance of 42 from pos.
|
||||||
*/
|
*/
|
||||||
uint8_t Segment::get_random_wheel_index(uint8_t pos) { // WLEDMM use fast int types, use native min/max
|
uint8_t Segment::get_random_wheel_index(uint8_t pos) const { // WLEDMM use fast int types, use native min/max
|
||||||
uint_fast8_t r = 0, x = 0, y = 0, d = 0;
|
uint_fast8_t r = 0, x = 0, y = 0, d = 0;
|
||||||
|
|
||||||
while(d < 42) {
|
while(d < 42) {
|
||||||
@@ -1538,7 +1607,7 @@ uint8_t Segment::get_random_wheel_index(uint8_t pos) { // WLEDMM use fast int ty
|
|||||||
* @param pbri Value to scale the brightness of the returned color by. Default is 255. (no scaling)
|
* @param pbri Value to scale the brightness of the returned color by. Default is 255. (no scaling)
|
||||||
* @returns Single color from palette
|
* @returns Single color from palette
|
||||||
*/
|
*/
|
||||||
uint32_t Segment::color_from_palette(uint_fast16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri) // WLEDMM use fast int types
|
uint32_t __attribute__((hot)) Segment::color_from_palette(uint_fast16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri) // WLEDMM use fast int types
|
||||||
{
|
{
|
||||||
// default palette or no RGB support on segment
|
// default palette or no RGB support on segment
|
||||||
if ((palette == 0 && mcol < NUM_COLORS) || !_isRGB) {
|
if ((palette == 0 && mcol < NUM_COLORS) || !_isRGB) {
|
||||||
@@ -1558,7 +1627,7 @@ uint32_t Segment::color_from_palette(uint_fast16_t i, bool mapping, bool wrap, u
|
|||||||
}
|
}
|
||||||
|
|
||||||
//WLEDMM netmindz ar palette
|
//WLEDMM netmindz ar palette
|
||||||
uint8_t * Segment::getAudioPalette(int pal) {
|
uint8_t * Segment::getAudioPalette(int pal) const {
|
||||||
// https://forum.makerforums.info/t/hi-is-it-possible-to-define-a-gradient-palette-at-runtime-the-define-gradient-palette-uses-the/63339
|
// https://forum.makerforums.info/t/hi-is-it-possible-to-define-a-gradient-palette-at-runtime-the-define-gradient-palette-uses-the/63339
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data;
|
||||||
@@ -1835,6 +1904,7 @@ 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]);
|
||||||
|
|
||||||
|
seg.startFrame(); // WLEDMM
|
||||||
// effect blending (execute previous effect)
|
// effect blending (execute previous effect)
|
||||||
// actual code may be a bit more involved as effects have runtime data including allocated memory
|
// actual code may be a bit more involved as effects have runtime data including allocated memory
|
||||||
//if (seg.transitional && seg._modeP) (*_mode[seg._modeP])(progress());
|
//if (seg.transitional && seg._modeP) (*_mode[seg._modeP])(progress());
|
||||||
@@ -1866,13 +1936,19 @@ void IRAM_ATTR WS2812FX::setPixelColor(int i, uint32_t col)
|
|||||||
busses.setPixelColor(i, col);
|
busses.setPixelColor(i, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t WS2812FX::getPixelColor(uint_fast16_t i) // WLEDMM fast int types
|
uint32_t WS2812FX::getPixelColor(uint_fast16_t i) const // WLEDMM fast int types
|
||||||
{
|
{
|
||||||
if (i < customMappingSize) i = customMappingTable[i];
|
if (i < customMappingSize) i = customMappingTable[i];
|
||||||
if (i >= _length) return 0;
|
if (i >= _length) return 0;
|
||||||
return busses.getPixelColor(i);
|
return busses.getPixelColor(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t WS2812FX::getPixelColorRestored(uint_fast16_t i) const // WLEDMM gets the original color from the driver (without downscaling by _bri)
|
||||||
|
{
|
||||||
|
if (i < customMappingSize) i = customMappingTable[i];
|
||||||
|
if (i >= _length) return 0;
|
||||||
|
return busses.getPixelColorRestored(i);
|
||||||
|
}
|
||||||
|
|
||||||
//DISCLAIMER
|
//DISCLAIMER
|
||||||
//The following function attemps to calculate the current LED power usage,
|
//The following function attemps to calculate the current LED power usage,
|
||||||
@@ -1917,7 +1993,8 @@ void WS2812FX::estimateCurrentAndLimitBri() {
|
|||||||
|
|
||||||
for (uint_fast8_t bNum = 0; bNum < busses.getNumBusses(); bNum++) {
|
for (uint_fast8_t bNum = 0; bNum < busses.getNumBusses(); bNum++) {
|
||||||
Bus *bus = busses.getBus(bNum);
|
Bus *bus = busses.getBus(bNum);
|
||||||
if (bus->getType() >= TYPE_NET_DDP_RGB) continue; //exclude non-physical network busses
|
auto btype = bus->getType();
|
||||||
|
if (EXCLUDE_FROM_ABL(btype)) continue; // WLEDMM exclude non-ABL and network busses
|
||||||
uint16_t len = bus->getLength();
|
uint16_t len = bus->getLength();
|
||||||
uint32_t busPowerSum = 0;
|
uint32_t busPowerSum = 0;
|
||||||
for (uint_fast16_t i = 0; i < len; i++) { //sum up the usage of each LED
|
for (uint_fast16_t i = 0; i < len; i++) { //sum up the usage of each LED
|
||||||
@@ -2004,7 +2081,7 @@ void WS2812FX::show(void) {
|
|||||||
* Returns a true value if any of the strips are still being updated.
|
* Returns a true value if any of the strips are still being updated.
|
||||||
* On some hardware (ESP32), strip updates are done asynchronously.
|
* On some hardware (ESP32), strip updates are done asynchronously.
|
||||||
*/
|
*/
|
||||||
bool WS2812FX::isUpdating() {
|
bool WS2812FX::isUpdating() const {
|
||||||
return !busses.canAllShow();
|
return !busses.canAllShow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2012,7 +2089,7 @@ bool WS2812FX::isUpdating() {
|
|||||||
* Returns the refresh rate of the LED strip. Useful for finding out whether a given setup is fast enough.
|
* Returns the refresh rate of the LED strip. Useful for finding out whether a given setup is fast enough.
|
||||||
* Only updates on show() or is set to 0 fps if last show is more than 2 secs ago, so accuracy varies
|
* Only updates on show() or is set to 0 fps if last show is more than 2 secs ago, so accuracy varies
|
||||||
*/
|
*/
|
||||||
uint16_t WS2812FX::getFps() {
|
uint16_t WS2812FX::getFps() const {
|
||||||
if (millis() - _lastShow > 2000) return 0;
|
if (millis() - _lastShow > 2000) return 0;
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
return ((_cumulativeFps500 + 250) / 500); // +250 for proper rounding
|
return ((_cumulativeFps500 + 250) / 500); // +250 for proper rounding
|
||||||
@@ -2103,14 +2180,14 @@ void WS2812FX::setMainSegmentId(uint8_t n) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t WS2812FX::getLastActiveSegmentId(void) {
|
uint8_t WS2812FX::getLastActiveSegmentId(void) const {
|
||||||
for (size_t i = _segments.size() -1; i > 0; i--) {
|
for (size_t i = _segments.size() -1; i > 0; i--) {
|
||||||
if (_segments[i].isActive()) return i;
|
if (_segments[i].isActive()) return i;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t WS2812FX::getActiveSegmentsNum(void) {
|
uint8_t WS2812FX::getActiveSegmentsNum(void) const {
|
||||||
uint8_t c = 0;
|
uint8_t c = 0;
|
||||||
for (size_t i = 0; i < _segments.size(); i++) {
|
for (size_t i = 0; i < _segments.size(); i++) {
|
||||||
if (_segments[i].isActive()) c++;
|
if (_segments[i].isActive()) c++;
|
||||||
@@ -2118,17 +2195,30 @@ uint8_t WS2812FX::getActiveSegmentsNum(void) {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t WS2812FX::getLengthTotal(void) { // WLEDMM fast int types
|
uint16_t WS2812FX::getLengthTotal(void) const { // WLEDMM fast int types
|
||||||
uint_fast16_t len = Segment::maxWidth * Segment::maxHeight; // will be _length for 1D (see finalizeInit()) but should cover whole matrix for 2D
|
uint_fast16_t len = Segment::maxWidth * Segment::maxHeight; // will be _length for 1D (see finalizeInit()) but should cover whole matrix for 2D
|
||||||
if (isMatrix && _length > len) len = _length; // for 2D with trailing strip
|
if (isMatrix && _length > len) len = _length; // for 2D with trailing strip
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t WS2812FX::getLengthPhysical(void) { // WLEDMM fast int types
|
uint16_t WS2812FX::getLengthPhysical(void) const { // WLEDMM fast int types
|
||||||
uint_fast16_t len = 0;
|
uint_fast16_t len = 0;
|
||||||
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
||||||
Bus *bus = busses.getBus(b);
|
Bus *bus = busses.getBus(b);
|
||||||
if (bus->getType() >= TYPE_NET_DDP_RGB) continue; //exclude non-physical network busses
|
auto btype = bus->getType();
|
||||||
|
if (EXCLUDE_FROM_ABL(btype)) continue; //exclude HUB75, and non-physical network busses
|
||||||
|
len += bus->getLength();
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
//WLEDMM - getLengthPhysical plus plysical busses not supporting ABL (i.e. HUB75)
|
||||||
|
uint16_t WS2812FX::getLengthPhysical2(void) const {
|
||||||
|
uint_fast16_t len = 0;
|
||||||
|
for (unsigned b = 0; b < busses.getNumBusses(); b++) {
|
||||||
|
Bus *bus = busses.getBus(b);
|
||||||
|
auto btype = bus->getType();
|
||||||
|
if (IS_VIRTUAL(btype)) continue;
|
||||||
len += bus->getLength();
|
len += bus->getLength();
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
@@ -2137,7 +2227,7 @@ uint16_t WS2812FX::getLengthPhysical(void) { // WLEDMM fast int types
|
|||||||
//used for JSON API info.leds.rgbw. Little practical use, deprecate with info.leds.rgbw.
|
//used for JSON API info.leds.rgbw. Little practical use, deprecate with info.leds.rgbw.
|
||||||
//returns if there is an RGBW bus (supports RGB and White, not only white)
|
//returns if there is an RGBW bus (supports RGB and White, not only white)
|
||||||
//not influenced by auto-white mode, also true if white slider does not affect output white channel
|
//not influenced by auto-white mode, also true if white slider does not affect output white channel
|
||||||
bool WS2812FX::hasRGBWBus(void) {
|
bool WS2812FX::hasRGBWBus(void) const {
|
||||||
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
||||||
Bus *bus = busses.getBus(b);
|
Bus *bus = busses.getBus(b);
|
||||||
if (bus == nullptr || bus->getLength()==0) break;
|
if (bus == nullptr || bus->getLength()==0) break;
|
||||||
@@ -2146,7 +2236,7 @@ bool WS2812FX::hasRGBWBus(void) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WS2812FX::hasCCTBus(void) {
|
bool WS2812FX::hasCCTBus(void) const {
|
||||||
if (cctFromRgb && !correctWB) return false;
|
if (cctFromRgb && !correctWB) return false;
|
||||||
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
||||||
Bus *bus = busses.getBus(b);
|
Bus *bus = busses.getBus(b);
|
||||||
@@ -2490,6 +2580,7 @@ bool WS2812FX::deserializeMap(uint8_t n) {
|
|||||||
uint16_t maxHeight = atoi(cleanUpName(fileName));
|
uint16_t maxHeight = atoi(cleanUpName(fileName));
|
||||||
//DEBUG_PRINTF(" (\"height\": %s) \n", fileName)
|
//DEBUG_PRINTF(" (\"height\": %s) \n", fileName)
|
||||||
|
|
||||||
|
#ifndef WLEDMM_NO_MAP_RESET
|
||||||
//WLEDMM: support ledmap file properties width and height: if found change segment
|
//WLEDMM: support ledmap file properties width and height: if found change segment
|
||||||
if (maxWidth * maxHeight > 0) {
|
if (maxWidth * maxHeight > 0) {
|
||||||
Segment::maxWidth = maxWidth;
|
Segment::maxWidth = maxWidth;
|
||||||
@@ -2498,6 +2589,7 @@ bool WS2812FX::deserializeMap(uint8_t n) {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
setUpMatrix(); //reset segment sizes to panels
|
setUpMatrix(); //reset segment sizes to panels
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
USER_PRINTF("deserializeMap %d x %d\n", Segment::maxWidth, Segment::maxHeight);
|
USER_PRINTF("deserializeMap %d x %d\n", Segment::maxWidth, Segment::maxHeight);
|
||||||
|
|||||||
@@ -9,6 +9,36 @@
|
|||||||
#include "bus_wrapper.h"
|
#include "bus_wrapper.h"
|
||||||
#include "bus_manager.h"
|
#include "bus_manager.h"
|
||||||
|
|
||||||
|
// WLEDMM functions to get/set bits in an array - based on functions created by Brandon for GOL
|
||||||
|
// toDo : make this a class that's completely defined in a header file
|
||||||
|
bool getBitFromArray(const uint8_t* byteArray, size_t position) { // get bit value
|
||||||
|
size_t byteIndex = position / 8;
|
||||||
|
unsigned bitIndex = position % 8;
|
||||||
|
uint8_t byteValue = byteArray[byteIndex];
|
||||||
|
return (byteValue >> bitIndex) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBitInArray(uint8_t* byteArray, size_t position, bool value) { // set bit - with error handling for nullptr
|
||||||
|
//if (byteArray == nullptr) return;
|
||||||
|
size_t byteIndex = position / 8;
|
||||||
|
unsigned bitIndex = position % 8;
|
||||||
|
if (value)
|
||||||
|
byteArray[byteIndex] |= (1 << bitIndex);
|
||||||
|
else
|
||||||
|
byteArray[byteIndex] &= ~(1 << bitIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getBitArrayBytes(size_t num_bits) { // number of bytes needed for an array with num_bits bits
|
||||||
|
return (num_bits + 7) / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBitArray(uint8_t* byteArray, size_t numBits, bool value) { // set all bits to same value
|
||||||
|
if (byteArray == nullptr) return;
|
||||||
|
size_t len = getBitArrayBytes(numBits);
|
||||||
|
if (value) memset(byteArray, 0xFF, len);
|
||||||
|
else memset(byteArray, 0x00, len);
|
||||||
|
}
|
||||||
|
|
||||||
//WLEDMM: #define DEBUGOUT(x) netDebugEnabled?NetDebug.print(x):Serial.print(x) not supported in this file as netDebugEnabled not in scope
|
//WLEDMM: #define DEBUGOUT(x) netDebugEnabled?NetDebug.print(x):Serial.print(x) not supported in this file as netDebugEnabled not in scope
|
||||||
#if 0
|
#if 0
|
||||||
//colors.cpp
|
//colors.cpp
|
||||||
@@ -49,13 +79,6 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte
|
|||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//color mangling macros
|
|
||||||
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
|
|
||||||
#define R(c) (byte((c) >> 16))
|
|
||||||
#define G(c) (byte((c) >> 8))
|
|
||||||
#define B(c) (byte(c))
|
|
||||||
#define W(c) (byte((c) >> 24))
|
|
||||||
|
|
||||||
|
|
||||||
void ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) {
|
void ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) {
|
||||||
if (_count >= WLED_MAX_COLOR_ORDER_MAPPINGS) {
|
if (_count >= WLED_MAX_COLOR_ORDER_MAPPINGS) {
|
||||||
@@ -86,7 +109,7 @@ uint8_t IRAM_ATTR ColorOrderMap::getPixelColorOrder(uint16_t pix, uint8_t defaul
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t Bus::autoWhiteCalc(uint32_t c) {
|
uint32_t Bus::autoWhiteCalc(uint32_t c) const {
|
||||||
uint8_t aWM = _autoWhiteMode;
|
uint8_t aWM = _autoWhiteMode;
|
||||||
if (_gAWM != AW_GLOBAL_DISABLED) aWM = _gAWM;
|
if (_gAWM != AW_GLOBAL_DISABLED) aWM = _gAWM;
|
||||||
if (aWM == RGBW_MODE_MANUAL_ONLY) return c;
|
if (aWM == RGBW_MODE_MANUAL_ONLY) return c;
|
||||||
@@ -182,7 +205,7 @@ void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) {
|
|||||||
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co);
|
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t IRAM_ATTR_YN BusDigital::getPixelColor(uint16_t pix) {
|
uint32_t IRAM_ATTR_YN BusDigital::getPixelColor(uint16_t pix) const {
|
||||||
if (reversed) pix = _len - pix -1;
|
if (reversed) pix = _len - pix -1;
|
||||||
else pix += _skip;
|
else pix += _skip;
|
||||||
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
||||||
@@ -200,7 +223,7 @@ uint32_t IRAM_ATTR_YN BusDigital::getPixelColor(uint16_t pix) {
|
|||||||
return PolyBus::getPixelColor(_busPtr, _iType, pix, co);
|
return PolyBus::getPixelColor(_busPtr, _iType, pix, co);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t BusDigital::getPins(uint8_t* pinArray) {
|
uint8_t BusDigital::getPins(uint8_t* pinArray) const {
|
||||||
uint8_t numPins = IS_2PIN(_type) ? 2 : 1;
|
uint8_t numPins = IS_2PIN(_type) ? 2 : 1;
|
||||||
for (uint8_t i = 0; i < numPins; i++) pinArray[i] = _pins[i];
|
for (uint8_t i = 0; i < numPins; i++) pinArray[i] = _pins[i];
|
||||||
return numPins;
|
return numPins;
|
||||||
@@ -317,7 +340,7 @@ void BusPwm::setPixelColor(uint16_t pix, uint32_t c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//does no index check
|
//does no index check
|
||||||
uint32_t BusPwm::getPixelColor(uint16_t pix) {
|
uint32_t BusPwm::getPixelColor(uint16_t pix) const {
|
||||||
if (!_valid) return 0;
|
if (!_valid) return 0;
|
||||||
#if 1
|
#if 1
|
||||||
// WLEDMM stick with the old code - we don't have cctICused
|
// WLEDMM stick with the old code - we don't have cctICused
|
||||||
@@ -356,7 +379,7 @@ void BusPwm::show() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t BusPwm::getPins(uint8_t* pinArray) {
|
uint8_t BusPwm::getPins(uint8_t* pinArray) const {
|
||||||
if (!_valid) return 0;
|
if (!_valid) return 0;
|
||||||
uint8_t numPins = NUM_PWM_PINS(_type);
|
uint8_t numPins = NUM_PWM_PINS(_type);
|
||||||
for (uint8_t i = 0; i < numPins; i++) {
|
for (uint8_t i = 0; i < numPins; i++) {
|
||||||
@@ -408,7 +431,7 @@ void BusOnOff::setPixelColor(uint16_t pix, uint32_t c) {
|
|||||||
_data = bool(r|g|b|w) && bool(_bri) ? 0xFF : 0;
|
_data = bool(r|g|b|w) && bool(_bri) ? 0xFF : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t BusOnOff::getPixelColor(uint16_t pix) {
|
uint32_t BusOnOff::getPixelColor(uint16_t pix) const {
|
||||||
if (!_valid) return 0;
|
if (!_valid) return 0;
|
||||||
return RGBW32(_data, _data, _data, _data);
|
return RGBW32(_data, _data, _data, _data);
|
||||||
}
|
}
|
||||||
@@ -418,7 +441,7 @@ void BusOnOff::show() {
|
|||||||
digitalWrite(_pin, reversed ? !(bool)_data : (bool)_data);
|
digitalWrite(_pin, reversed ? !(bool)_data : (bool)_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t BusOnOff::getPins(uint8_t* pinArray) {
|
uint8_t BusOnOff::getPins(uint8_t* pinArray) const {
|
||||||
if (!_valid) return 0;
|
if (!_valid) return 0;
|
||||||
pinArray[0] = _pin;
|
pinArray[0] = _pin;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -467,7 +490,7 @@ void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
|
|||||||
if (_rgbw) _data[offset+3] = W(c);
|
if (_rgbw) _data[offset+3] = W(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t BusNetwork::getPixelColor(uint16_t pix) {
|
uint32_t BusNetwork::getPixelColor(uint16_t pix) const {
|
||||||
if (!_valid || pix >= _len) return 0;
|
if (!_valid || pix >= _len) return 0;
|
||||||
uint16_t offset = pix * _UDPchannels;
|
uint16_t offset = pix * _UDPchannels;
|
||||||
return RGBW32(_data[offset], _data[offset+1], _data[offset+2], _rgbw ? (_data[offset+3] << 24) : 0);
|
return RGBW32(_data[offset], _data[offset+1], _data[offset+2], _rgbw ? (_data[offset+3] << 24) : 0);
|
||||||
@@ -480,7 +503,7 @@ void BusNetwork::show() {
|
|||||||
_broadcastLock = false;
|
_broadcastLock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t BusNetwork::getPins(uint8_t* pinArray) {
|
uint8_t BusNetwork::getPins(uint8_t* pinArray) const {
|
||||||
for (uint8_t i = 0; i < 4; i++) {
|
for (uint8_t i = 0; i < 4; i++) {
|
||||||
pinArray[i] = _client[i];
|
pinArray[i] = _client[i];
|
||||||
}
|
}
|
||||||
@@ -500,12 +523,35 @@ void BusNetwork::cleanup() {
|
|||||||
#warning "HUB75 driver enabled (experimental)"
|
#warning "HUB75 driver enabled (experimental)"
|
||||||
|
|
||||||
BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||||
|
size_t lastHeap = ESP.getFreeHeap();
|
||||||
|
|
||||||
mxconfig.double_buff = false; // default to off, known to cause issue with some effects but needs more memory
|
_valid = false;
|
||||||
|
|
||||||
|
|
||||||
fourScanPanel = nullptr;
|
fourScanPanel = nullptr;
|
||||||
|
|
||||||
|
mxconfig.double_buff = false; // Use our own memory-optimised buffer rather than the driver's own double-buffer
|
||||||
|
|
||||||
|
// mxconfig.driver = HUB75_I2S_CFG::ICN2038S; // experimental - use specific shift register driver
|
||||||
|
// mxconfig.latch_blanking = 3;
|
||||||
|
// mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_10M; // experimental - 5MHZ should be enugh, but colours looks slightly better at 10MHz
|
||||||
|
// mxconfig.min_refresh_rate = 90;
|
||||||
|
mxconfig.clkphase = false; // can help in case that the leftmost column is invisible, or pixels on the right side "bleeds out" to the left.
|
||||||
|
|
||||||
|
// How many panels we have connected, cap at sane value
|
||||||
|
mxconfig.chain_length = max((uint8_t) 1, min(bc.pins[0], (uint8_t) 4)); // prevent bad data preventing boot due to low memory
|
||||||
|
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(BOARD_HAS_PSRAM)
|
||||||
|
if(bc.pins[0] > 4) {
|
||||||
|
USER_PRINTLN("WARNING, chain limited to 4");
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
// Disable this check if you are want to try bigger setups and accept you
|
||||||
|
// might need to do full erase to recover from memory relayed boot-loop if you push too far
|
||||||
|
if(mxconfig.mx_height >= 64 && (bc.pins[0] > 1)) {
|
||||||
|
USER_PRINTLN("WARNING, only single panel can be used of 64 pixel boards due to memory");
|
||||||
|
//mxconfig.chain_length = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
switch(bc.type) {
|
switch(bc.type) {
|
||||||
case 101:
|
case 101:
|
||||||
mxconfig.mx_width = 32;
|
mxconfig.mx_width = 32;
|
||||||
@@ -533,12 +579,13 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mxconfig.mx_height >= 64 && (bc.pins[0] > 1)) {
|
#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2)// classic esp32, or esp32-s2: reduce bitdepth for large panels
|
||||||
USER_PRINT("WARNING, only single panel can be used of 64 pixel boards due to memory")
|
if (mxconfig.mx_height >= 64) {
|
||||||
mxconfig.chain_length = 1;
|
if (mxconfig.chain_length * mxconfig.mx_width > 192) mxconfig.setPixelColorDepthBits(3);
|
||||||
}
|
else if (mxconfig.chain_length * mxconfig.mx_width > 64) mxconfig.setPixelColorDepthBits(4);
|
||||||
|
else mxconfig.setPixelColorDepthBits(8);
|
||||||
// mxconfig.driver = HUB75_I2S_CFG::SHIFTREG;
|
} else mxconfig.setPixelColorDepthBits(8);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(ARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3) // MatrixPortal ESP32-S3
|
#if defined(ARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3) // MatrixPortal ESP32-S3
|
||||||
|
|
||||||
@@ -546,8 +593,6 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh
|
|||||||
|
|
||||||
USER_PRINTLN("MatrixPanel_I2S_DMA - Matrix Portal S3 config");
|
USER_PRINTLN("MatrixPanel_I2S_DMA - Matrix Portal S3 config");
|
||||||
|
|
||||||
mxconfig.double_buff = true; // <------------- Turn on double buffer
|
|
||||||
|
|
||||||
mxconfig.gpio.r1 = 42;
|
mxconfig.gpio.r1 = 42;
|
||||||
mxconfig.gpio.g1 = 41;
|
mxconfig.gpio.g1 = 41;
|
||||||
mxconfig.gpio.b1 = 40;
|
mxconfig.gpio.b1 = 40;
|
||||||
@@ -565,6 +610,76 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh
|
|||||||
mxconfig.gpio.d = 35;
|
mxconfig.gpio.d = 35;
|
||||||
mxconfig.gpio.e = 21;
|
mxconfig.gpio.e = 21;
|
||||||
|
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32S3) && defined(BOARD_HAS_PSRAM)// ESP32-S3
|
||||||
|
|
||||||
|
USER_PRINTLN("MatrixPanel_I2S_DMA - S3 with PSRAM");
|
||||||
|
|
||||||
|
mxconfig.gpio.r1 = 1;
|
||||||
|
mxconfig.gpio.g1 = 2;
|
||||||
|
mxconfig.gpio.b1 = 42;
|
||||||
|
// 4th pin is GND
|
||||||
|
mxconfig.gpio.r2 = 41;
|
||||||
|
mxconfig.gpio.g2 = 40;
|
||||||
|
mxconfig.gpio.b2 = 39;
|
||||||
|
mxconfig.gpio.e = 38;
|
||||||
|
mxconfig.gpio.a = 45;
|
||||||
|
mxconfig.gpio.b = 48;
|
||||||
|
mxconfig.gpio.c = 47;
|
||||||
|
mxconfig.gpio.d = 21;
|
||||||
|
mxconfig.gpio.clk = 18;
|
||||||
|
mxconfig.gpio.lat = 8;
|
||||||
|
mxconfig.gpio.oe = 3;
|
||||||
|
// 16th pin is GND
|
||||||
|
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32S3) // ESP32-S3
|
||||||
|
|
||||||
|
// Huidu HD-WF2 ESP32-S3
|
||||||
|
// https://www.aliexpress.com/item/1005002258734810.html
|
||||||
|
// https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/issues/433
|
||||||
|
|
||||||
|
USER_PRINTLN("MatrixPanel_I2S_DMA - HD-WF2 S3 config");
|
||||||
|
|
||||||
|
mxconfig.gpio.r1 = 2;
|
||||||
|
mxconfig.gpio.g1 = 6;
|
||||||
|
mxconfig.gpio.b1 = 10;
|
||||||
|
mxconfig.gpio.r2 = 3;
|
||||||
|
mxconfig.gpio.g2 = 7;
|
||||||
|
mxconfig.gpio.b2 = 11;
|
||||||
|
|
||||||
|
mxconfig.gpio.lat = 33;
|
||||||
|
mxconfig.gpio.oe = 35;
|
||||||
|
mxconfig.gpio.clk = 34;
|
||||||
|
|
||||||
|
mxconfig.gpio.a = 39;
|
||||||
|
mxconfig.gpio.b = 38;
|
||||||
|
mxconfig.gpio.c = 37;
|
||||||
|
mxconfig.gpio.d = 36;
|
||||||
|
mxconfig.gpio.e = 21;
|
||||||
|
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32S2) // ESP32-S2
|
||||||
|
|
||||||
|
// Huidu HD-WF1 ESP32-S2
|
||||||
|
// https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/issues/433
|
||||||
|
|
||||||
|
USER_PRINTLN("MatrixPanel_I2S_DMA - HD-WF1 S2 config");
|
||||||
|
|
||||||
|
mxconfig.gpio.r1 = 2;
|
||||||
|
mxconfig.gpio.g1 = 6;
|
||||||
|
mxconfig.gpio.b1 = 3;
|
||||||
|
mxconfig.gpio.r2 = 4;
|
||||||
|
mxconfig.gpio.g2 = 8;
|
||||||
|
mxconfig.gpio.b2 = 5;
|
||||||
|
|
||||||
|
mxconfig.gpio.lat = 33;
|
||||||
|
mxconfig.gpio.oe = 35;
|
||||||
|
mxconfig.gpio.clk = 34;
|
||||||
|
|
||||||
|
mxconfig.gpio.a = 39;
|
||||||
|
mxconfig.gpio.b = 38;
|
||||||
|
mxconfig.gpio.c = 37;
|
||||||
|
mxconfig.gpio.d = 36;
|
||||||
|
mxconfig.gpio.e = 12;
|
||||||
|
|
||||||
#elif defined(ESP32_FORUM_PINOUT) // Common format for boards designed for SmartMatrix
|
#elif defined(ESP32_FORUM_PINOUT) // Common format for boards designed for SmartMatrix
|
||||||
|
|
||||||
USER_PRINTLN("MatrixPanel_I2S_DMA - ESP32_FORUM_PINOUT");
|
USER_PRINTLN("MatrixPanel_I2S_DMA - ESP32_FORUM_PINOUT");
|
||||||
@@ -624,9 +739,8 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mxconfig.chain_length = max((u_int8_t) 1, min(bc.pins[0], (u_int8_t) 4)); // prevent bad data preventing boot due to low memory
|
USER_PRINTF("MatrixPanel_I2S_DMA config - %ux%u (type %u) length: %u, %u bits/pixel.\n", mxconfig.mx_width, mxconfig.mx_height, bc.type, mxconfig.chain_length, mxconfig.getPixelColorDepthBits() * 3);
|
||||||
|
DEBUG_PRINT(F("Free heap: ")); DEBUG_PRINTLN(ESP.getFreeHeap()); lastHeap = ESP.getFreeHeap();
|
||||||
USER_PRINTF("MatrixPanel_I2S_DMA config - %ux%u length: %u\n", mxconfig.mx_width, mxconfig.mx_height, mxconfig.chain_length);
|
|
||||||
|
|
||||||
// OK, now we can create our matrix object
|
// OK, now we can create our matrix object
|
||||||
display = new MatrixPanel_I2S_DMA(mxconfig);
|
display = new MatrixPanel_I2S_DMA(mxconfig);
|
||||||
@@ -655,14 +769,50 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh
|
|||||||
USER_PRINTLN("MatrixPanel_I2S_DMA created");
|
USER_PRINTLN("MatrixPanel_I2S_DMA created");
|
||||||
// let's adjust default brightness
|
// let's adjust default brightness
|
||||||
display->setBrightness8(25); // range is 0-255, 0 - 0%, 255 - 100%
|
display->setBrightness8(25); // range is 0-255, 0 - 0%, 255 - 100%
|
||||||
|
_bri = 25;
|
||||||
|
|
||||||
|
delay(24); // experimental
|
||||||
|
DEBUG_PRINT(F("heap usage: ")); DEBUG_PRINTLN(lastHeap - ESP.getFreeHeap());
|
||||||
// Allocate memory and start DMA display
|
// Allocate memory and start DMA display
|
||||||
if( not display->begin() ) {
|
if( not display->begin() ) {
|
||||||
USER_PRINTLN("****** MatrixPanel_I2S_DMA !KABOOM! I2S memory allocation failed ***********");
|
USER_PRINTLN("****** MatrixPanel_I2S_DMA !KABOOM! I2S memory allocation failed ***********");
|
||||||
|
USER_PRINT(F("heap usage: ")); USER_PRINTLN(lastHeap - ESP.getFreeHeap());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
USER_PRINTLN("MatrixPanel_I2S_DMA begin ok");
|
||||||
|
USER_PRINT(F("heap usage: ")); USER_PRINTLN(lastHeap - ESP.getFreeHeap());
|
||||||
|
delay(18); // experiment - give the driver a moment (~ one full frame @ 60hz) to settle
|
||||||
_valid = true;
|
_valid = true;
|
||||||
|
display->clearScreen(); // initially clear the screen buffer
|
||||||
|
USER_PRINTLN("MatrixPanel_I2S_DMA clear ok");
|
||||||
|
|
||||||
|
if (_ledBuffer) free(_ledBuffer); // should not happen
|
||||||
|
if (_ledsDirty) free(_ledsDirty); // should not happen
|
||||||
|
|
||||||
|
_ledsDirty = (byte*) malloc(getBitArrayBytes(_len)); // create LEDs dirty bits
|
||||||
|
|
||||||
|
if (_ledsDirty == nullptr) {
|
||||||
|
display->stopDMAoutput();
|
||||||
|
delete display; display = nullptr;
|
||||||
|
_valid = false;
|
||||||
|
USER_PRINTLN(F("MatrixPanel_I2S_DMA not started - not enough memory for dirty bits!"));
|
||||||
|
USER_PRINT(F("heap usage: ")); USER_PRINTLN(lastHeap - ESP.getFreeHeap());
|
||||||
|
return; // fail is we cannot get memory for the buffer
|
||||||
|
}
|
||||||
|
setBitArray(_ledsDirty, _len, false); // reset dirty bits
|
||||||
|
|
||||||
|
if (mxconfig.double_buff == false) {
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32S3) && CONFIG_SPIRAM_MODE_OCT && defined(BOARD_HAS_PSRAM) && (defined(WLED_USE_PSRAM) || defined(WLED_USE_PSRAM_JSON))
|
||||||
|
if (psramFound()) {
|
||||||
|
_ledBuffer = (CRGB*) ps_calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK)
|
||||||
|
} else {
|
||||||
|
_ledBuffer = (CRGB*) calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK)
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
_ledBuffer = (CRGB*) calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(bc.type) {
|
switch(bc.type) {
|
||||||
@@ -686,28 +836,134 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_valid) {
|
||||||
|
_panelWidth = fourScanPanel ? fourScanPanel->width() : display->width(); // cache width - it will never change
|
||||||
|
}
|
||||||
|
|
||||||
USER_PRINTLN("MatrixPanel_I2S_DMA started");
|
USER_PRINT(F("MatrixPanel_I2S_DMA "));
|
||||||
|
USER_PRINTF("%sstarted, width=%u, %u pixels.\n", _valid? "":"not ", _panelWidth, _len);
|
||||||
|
|
||||||
|
if (mxconfig.double_buff == true) USER_PRINTLN(F("MatrixPanel_I2S_DMA driver native double-buffering enabled."));
|
||||||
|
if (_ledBuffer != nullptr) USER_PRINTLN(F("MatrixPanel_I2S_DMA LEDS buffer enabled."));
|
||||||
|
if (_ledsDirty != nullptr) USER_PRINTLN(F("MatrixPanel_I2S_DMA LEDS dirty bit optimization enabled."));
|
||||||
|
if ((_ledBuffer != nullptr) || (_ledsDirty != nullptr)) {
|
||||||
|
USER_PRINT(F("MatrixPanel_I2S_DMA LEDS buffer uses "));
|
||||||
|
USER_PRINT((_ledBuffer? _len*sizeof(CRGB) :0) + (_ledsDirty? getBitArrayBytes(_len) :0));
|
||||||
|
USER_PRINTLN(F(" bytes."));
|
||||||
|
}
|
||||||
|
USER_PRINT(F("heap usage: ")); USER_PRINTLN(lastHeap - ESP.getFreeHeap());
|
||||||
}
|
}
|
||||||
|
|
||||||
void BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) {
|
void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) {
|
||||||
r = R(c);
|
if (!_valid || pix >= _len) return;
|
||||||
g = G(c);
|
// if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
||||||
b = B(c);
|
|
||||||
if(fourScanPanel != nullptr) {
|
if (_ledBuffer) {
|
||||||
x = pix % fourScanPanel->width();
|
CRGB fastled_col = CRGB(c);
|
||||||
y = floor(pix / fourScanPanel->width());
|
if (_ledBuffer[pix] != fastled_col) {
|
||||||
fourScanPanel->drawPixelRGB888(x, y, r, g, b);
|
_ledBuffer[pix] = fastled_col;
|
||||||
|
setBitInArray(_ledsDirty, pix, true); // flag pixel as "dirty"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
x = pix % display->width();
|
if ((c == BLACK) && (getBitFromArray(_ledsDirty, pix) == false)) return; // ignore black if pixel is already black
|
||||||
y = floor(pix / display->width());
|
setBitInArray(_ledsDirty, pix, c != BLACK); // dirty = true means "color is not BLACK"
|
||||||
display->drawPixelRGB888(x, y, r, g, b);
|
|
||||||
|
#ifndef NO_CIE1931
|
||||||
|
c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction
|
||||||
|
#endif
|
||||||
|
uint8_t r = R(c);
|
||||||
|
uint8_t g = G(c);
|
||||||
|
uint8_t b = B(c);
|
||||||
|
|
||||||
|
if(fourScanPanel != nullptr) {
|
||||||
|
int width = _panelWidth;
|
||||||
|
int x = pix % width;
|
||||||
|
int y = pix / width;
|
||||||
|
fourScanPanel->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b);
|
||||||
|
} else {
|
||||||
|
int width = _panelWidth;
|
||||||
|
int x = pix % width;
|
||||||
|
int y = pix / width;
|
||||||
|
display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t BusHub75Matrix::getPixelColor(uint16_t pix) const {
|
||||||
|
if (!_valid || pix >= _len) return BLACK;
|
||||||
|
if (_ledBuffer)
|
||||||
|
return uint32_t(_ledBuffer[pix].scale8(_bri)) & 0x00FFFFFF; // scale8() is needed to mimic NeoPixelBus, which returns scaled-down colours
|
||||||
|
else
|
||||||
|
return getBitFromArray(_ledsDirty, pix) ? DARKGREY: BLACK; // just a hack - we only know if the pixel is black or not
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t __attribute__((hot)) BusHub75Matrix::getPixelColorRestored(uint16_t pix) const {
|
||||||
|
if (!_valid || pix >= _len) return BLACK;
|
||||||
|
if (_ledBuffer)
|
||||||
|
return uint32_t(_ledBuffer[pix]) & 0x00FFFFFF;
|
||||||
|
else
|
||||||
|
return getBitFromArray(_ledsDirty, pix) ? DARKGREY: BLACK; // just a hack - we only know if the pixel is black or not
|
||||||
|
}
|
||||||
|
|
||||||
void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) {
|
void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) {
|
||||||
this->display->setBrightness(b);
|
_bri = b;
|
||||||
|
// if (_bri > 238) _bri=238; // not strictly needed. Enable this line if you see glitches at highest brightness.
|
||||||
|
display->setBrightness(_bri);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((hot)) BusHub75Matrix::show(void) {
|
||||||
|
if (!_valid) return;
|
||||||
|
display->setBrightness(_bri);
|
||||||
|
|
||||||
|
if (_ledBuffer) {
|
||||||
|
// write out buffered LEDs
|
||||||
|
bool isFourScan = (fourScanPanel != nullptr);
|
||||||
|
//if (isFourScan) fourScanPanel->setRotation(0);
|
||||||
|
unsigned height = isFourScan ? fourScanPanel->height() : display->height();
|
||||||
|
unsigned width = _panelWidth;
|
||||||
|
|
||||||
|
//while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker.
|
||||||
|
|
||||||
|
size_t pix = 0; // running pixel index
|
||||||
|
for (int y=0; y<height; y++) for (int x=0; x<width; x++) {
|
||||||
|
if (getBitFromArray(_ledsDirty, pix) == true) { // only repaint the "dirty" pixels
|
||||||
|
uint32_t c = uint32_t(_ledBuffer[pix]) & 0x00FFFFFF; // get RGB color, removing FastLED "alpha" component
|
||||||
|
#ifndef NO_CIE1931
|
||||||
|
c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction
|
||||||
|
#endif
|
||||||
|
uint8_t r = R(c);
|
||||||
|
uint8_t g = G(c);
|
||||||
|
uint8_t b = B(c);
|
||||||
|
if (isFourScan) fourScanPanel->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b);
|
||||||
|
else display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b);
|
||||||
|
}
|
||||||
|
pix ++;
|
||||||
|
}
|
||||||
|
setBitArray(_ledsDirty, _len, false); // buffer shown - reset all dirty bits
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mxconfig.double_buff) {
|
||||||
|
display->flipDMABuffer(); // Show the back buffer, set current output buffer to the back (i.e. no longer being sent to LED panels)
|
||||||
|
// while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker.
|
||||||
|
display->clearScreen(); // Now clear the back-buffer
|
||||||
|
setBitArray(_ledsDirty, _len, false); // dislay buffer is blank - reset all dirty bits
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BusHub75Matrix::cleanup() {
|
||||||
|
if (display && _valid) display->stopDMAoutput(); // terminate DMA driver (display goes black)
|
||||||
|
_valid = false;
|
||||||
|
_panelWidth = 0;
|
||||||
|
deallocatePins();
|
||||||
|
USER_PRINTLN("HUB75 output ended.");
|
||||||
|
|
||||||
|
//if (fourScanPanel != nullptr) delete fourScanPanel; // warning: deleting object of polymorphic class type 'VirtualMatrixPanel' which has non-virtual destructor might cause undefined behavior
|
||||||
|
delete display;
|
||||||
|
display = nullptr;
|
||||||
|
fourScanPanel = nullptr;
|
||||||
|
if (_ledBuffer != nullptr) free(_ledBuffer); _ledBuffer = nullptr;
|
||||||
|
if (_ledsDirty != nullptr) free(_ledsDirty); _ledsDirty = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BusHub75Matrix::deallocatePins() {
|
void BusHub75Matrix::deallocatePins() {
|
||||||
@@ -766,7 +1022,7 @@ int BusManager::add(BusConfig &bc) {
|
|||||||
busses[numBusses] = new BusHub75Matrix(bc);
|
busses[numBusses] = new BusHub75Matrix(bc);
|
||||||
USER_PRINTLN("[BusHub75Matrix] ");
|
USER_PRINTLN("[BusHub75Matrix] ");
|
||||||
#else
|
#else
|
||||||
USER_PRINTLN("[unsupported! BusHub75Matrix] ");
|
USER_PRINTLN("[unsupported! BusHub75Matrix - add flag -D WLED_ENABLE_HUB75MATRIX] ");
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
} else if (IS_DIGITAL(bc.type)) {
|
} else if (IS_DIGITAL(bc.type)) {
|
||||||
@@ -808,7 +1064,7 @@ void BusManager::setStatusPixel(uint32_t c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR BusManager::setPixelColor(uint16_t pix, uint32_t c, int16_t cct) {
|
void IRAM_ATTR __attribute__((hot)) BusManager::setPixelColor(uint16_t pix, uint32_t c, int16_t cct) {
|
||||||
if ((pix >= laststart) && (pix < lastend ) && (lastBus != nullptr)) {
|
if ((pix >= laststart) && (pix < lastend ) && (lastBus != nullptr)) {
|
||||||
// WLEDMM same bus as last time - no need to search again
|
// WLEDMM same bus as last time - no need to search again
|
||||||
lastBus->setPixelColor(pix - laststart, c);
|
lastBus->setPixelColor(pix - laststart, c);
|
||||||
@@ -836,7 +1092,7 @@ void BusManager::setBrightness(uint8_t b, bool immediate) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) {
|
void __attribute__((cold)) BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) {
|
||||||
if (cct > 255) cct = 255;
|
if (cct > 255) cct = 255;
|
||||||
if (cct >= 0) {
|
if (cct >= 0) {
|
||||||
//if white balance correction allowed, save as kelvin value instead of 0-255
|
//if white balance correction allowed, save as kelvin value instead of 0-255
|
||||||
@@ -845,7 +1101,7 @@ void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) {
|
|||||||
Bus::setCCT(cct);
|
Bus::setCCT(cct);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t IRAM_ATTR BusManager::getPixelColor(uint_fast16_t pix) { // WLEDMM use fast native types, IRAM_ATTR
|
uint32_t IRAM_ATTR __attribute__((hot)) BusManager::getPixelColor(uint_fast16_t pix) { // WLEDMM use fast native types, IRAM_ATTR
|
||||||
if ((pix >= laststart) && (pix < lastend ) && (lastBus != nullptr)) {
|
if ((pix >= laststart) && (pix < lastend ) && (lastBus != nullptr)) {
|
||||||
// WLEDMM same bus as last time - no need to search again
|
// WLEDMM same bus as last time - no need to search again
|
||||||
return lastBus->getPixelColor(pix - laststart);
|
return lastBus->getPixelColor(pix - laststart);
|
||||||
@@ -866,20 +1122,41 @@ uint32_t IRAM_ATTR BusManager::getPixelColor(uint_fast16_t pix) { // WLEDMM
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BusManager::canAllShow() {
|
uint32_t IRAM_ATTR __attribute__((hot)) BusManager::getPixelColorRestored(uint_fast16_t pix) { // WLEDMM uses bus::getPixelColorRestored()
|
||||||
|
if ((pix >= laststart) && (pix < lastend ) && (lastBus != nullptr)) {
|
||||||
|
// WLEDMM same bus as last time - no need to search again
|
||||||
|
return lastBus->getPixelColorRestored(pix - laststart);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint_fast8_t i = 0; i < numBusses; i++) {
|
||||||
|
Bus* b = busses[i];
|
||||||
|
uint_fast16_t bstart = b->getStart();
|
||||||
|
if (pix < bstart || pix >= bstart + b->getLength()) continue;
|
||||||
|
else {
|
||||||
|
// WLEDMM remember last Bus we took
|
||||||
|
lastBus = b;
|
||||||
|
laststart = bstart;
|
||||||
|
lastend = bstart + b->getLength();
|
||||||
|
return b->getPixelColorRestored(pix - bstart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BusManager::canAllShow() const {
|
||||||
for (uint8_t i = 0; i < numBusses; i++) {
|
for (uint8_t i = 0; i < numBusses; i++) {
|
||||||
if (!busses[i]->canShow()) return false;
|
if (!busses[i]->canShow()) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bus* BusManager::getBus(uint8_t busNr) {
|
Bus* BusManager::getBus(uint8_t busNr) const {
|
||||||
if (busNr >= numBusses) return nullptr;
|
if (busNr >= numBusses) return nullptr;
|
||||||
return busses[busNr];
|
return busses[busNr];
|
||||||
}
|
}
|
||||||
|
|
||||||
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
|
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
|
||||||
uint16_t BusManager::getTotalLength() {
|
uint16_t BusManager::getTotalLength() const {
|
||||||
uint_fast16_t len = 0;
|
uint_fast16_t len = 0;
|
||||||
for (uint_fast8_t i=0; i<numBusses; i++) len += busses[i]->getLength(); // WLEDMM use fast native types
|
for (uint_fast8_t i=0; i<numBusses; i++) len += busses[i]->getLength(); // WLEDMM use fast native types
|
||||||
return len;
|
return len;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#ifdef WLED_ENABLE_HUB75MATRIX
|
#ifdef WLED_ENABLE_HUB75MATRIX
|
||||||
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
|
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
|
||||||
#include <ESP32-VirtualMatrixPanel-I2S-DMA.h>
|
#include <ESP32-VirtualMatrixPanel-I2S-DMA.h>
|
||||||
|
//extern volatile bool previousBufferFree; // experimental
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* Class for addressing various light types
|
* Class for addressing various light types
|
||||||
@@ -11,6 +12,27 @@
|
|||||||
|
|
||||||
#include "const.h"
|
#include "const.h"
|
||||||
|
|
||||||
|
#if !defined(FASTLED_VERSION) // only pull in FastLED if we don't have it yet
|
||||||
|
#define FASTLED_INTERNAL
|
||||||
|
#include <FastLED.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//color mangling macros
|
||||||
|
#if !defined(RGBW32)
|
||||||
|
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
|
||||||
|
#define R(c) (byte((c) >> 16))
|
||||||
|
#define G(c) (byte((c) >> 8))
|
||||||
|
#define B(c) (byte(c))
|
||||||
|
#define W(c) (byte((c) >> 24))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// WLEDMM bitarray utilities
|
||||||
|
void setBitInArray(uint8_t* byteArray, size_t position, bool value); // set bit
|
||||||
|
bool getBitFromArray(const uint8_t* byteArray, size_t position) __attribute__((pure)); // get bit value
|
||||||
|
size_t getBitArrayBytes(size_t num_bits) __attribute__((const)); // number of bytes needed for an array with num_bits bits
|
||||||
|
void setBitArray(uint8_t* byteArray, size_t numBits, bool value); // set all bits to same value
|
||||||
|
|
||||||
|
|
||||||
#define GET_BIT(var,bit) (((var)>>(bit))&0x01)
|
#define GET_BIT(var,bit) (((var)>>(bit))&0x01)
|
||||||
#define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit)))
|
#define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit)))
|
||||||
#define UNSET_BIT(var,bit) ((var)&=(~(uint16_t)(0x0001<<(bit))))
|
#define UNSET_BIT(var,bit) ((var)&=(~(uint16_t)(0x0001<<(bit))))
|
||||||
@@ -32,18 +54,18 @@ struct BusConfig {
|
|||||||
uint8_t skipAmount;
|
uint8_t skipAmount;
|
||||||
bool refreshReq;
|
bool refreshReq;
|
||||||
uint8_t autoWhite;
|
uint8_t autoWhite;
|
||||||
uint8_t pins[5] = {LEDPIN, 255, 255, 255, 255};
|
uint8_t pins[5] = {LEDPIN, 255, 255, 255, 255}; // WLEDMM warning: this means that BusConfig cannot handle nore than 5 pins per bus!
|
||||||
uint16_t frequency;
|
uint16_t frequency;
|
||||||
BusConfig(uint8_t busType, uint8_t* ppins, uint16_t pstart, uint16_t len = 1, uint8_t pcolorOrder = COL_ORDER_GRB, bool rev = false, uint8_t skip = 0, byte aw=RGBW_MODE_MANUAL_ONLY, uint16_t clock_kHz=0U) {
|
BusConfig(uint8_t busType, uint8_t* ppins, uint16_t pstart, uint16_t len = 1, uint8_t pcolorOrder = COL_ORDER_GRB, bool rev = false, uint8_t skip = 0, byte aw=RGBW_MODE_MANUAL_ONLY, uint16_t clock_kHz=0U) {
|
||||||
refreshReq = (bool) GET_BIT(busType,7);
|
refreshReq = (bool) GET_BIT(busType,7);
|
||||||
type = busType & 0x7F; // bit 7 may be/is hacked to include refresh info (1=refresh in off state, 0=no refresh)
|
type = busType & 0x7F; // bit 7 may be/is hacked to include refresh info (1=refresh in off state, 0=no refresh)
|
||||||
count = len; start = pstart; colorOrder = pcolorOrder; reversed = rev; skipAmount = skip; autoWhite = aw; frequency = clock_kHz;
|
count = len; start = pstart; colorOrder = pcolorOrder; reversed = rev; skipAmount = skip; autoWhite = aw; frequency = clock_kHz;
|
||||||
uint8_t nPins = 1;
|
uint8_t nPins = 1; // default = only one pin (clockless LEDs like WS281x)
|
||||||
if (type >= TYPE_NET_DDP_RGB && type < 96) nPins = 4; //virtual network bus. 4 "pins" store IP address
|
if ((type >= TYPE_NET_DDP_RGB) && (type < (TYPE_NET_DDP_RGB + 16))) nPins = 4; // virtual network bus. 4 "pins" store IP address
|
||||||
else if (type > 47) nPins = 2;
|
else if ((type > 47) && (type < 63)) nPins = 2; // (data + clock / SPI) busses - two pins
|
||||||
else if (type > 40 && type < 46) nPins = NUM_PWM_PINS(type);
|
else if (IS_PWM(type)) nPins = NUM_PWM_PINS(type); // PWM needs 1..5 pins
|
||||||
else if (type >= TYPE_HUB75MATRIX && type <= (TYPE_HUB75MATRIX + 10)) nPins = 0;
|
else if (type >= TYPE_HUB75MATRIX && type <= (TYPE_HUB75MATRIX + 10)) nPins = 1; // HUB75 does not use LED pins, but we need to preserve the "chain length" parameter
|
||||||
for (uint8_t i = 0; i < nPins; i++) pins[i] = ppins[i];
|
for (uint8_t i = 0; i < min(unsigned(nPins), sizeof(pins)/sizeof(pins[0])); i++) pins[i] = ppins[i]; //softhack007 fix for potential array out-of-bounds access
|
||||||
}
|
}
|
||||||
|
|
||||||
//validates start and length and extends total if needed
|
//validates start and length and extends total if needed
|
||||||
@@ -112,35 +134,36 @@ class Bus {
|
|||||||
virtual bool canShow() { return true; }
|
virtual bool canShow() { return true; }
|
||||||
virtual void setStatusPixel(uint32_t c) {}
|
virtual void setStatusPixel(uint32_t c) {}
|
||||||
virtual void setPixelColor(uint16_t pix, uint32_t c) = 0;
|
virtual void setPixelColor(uint16_t pix, uint32_t c) = 0;
|
||||||
virtual uint32_t getPixelColor(uint16_t pix) { return 0; }
|
virtual uint32_t getPixelColor(uint16_t pix) const { return 0; }
|
||||||
virtual void setBrightness(uint8_t b, bool immediate=false) { _bri = b; };
|
virtual uint32_t getPixelColorRestored(uint16_t pix) const { return restore_Color_Lossy(getPixelColor(pix), _bri); } // override in case your bus has a lossless buffer (HUB75, FastLED, Art-Net)
|
||||||
|
virtual void setBrightness(uint8_t b, bool immediate=false) { _bri = b; }
|
||||||
virtual void cleanup() = 0;
|
virtual void cleanup() = 0;
|
||||||
virtual uint8_t getPins(uint8_t* pinArray) { return 0; }
|
virtual uint8_t getPins(uint8_t* pinArray) const { return 0; }
|
||||||
virtual uint16_t getLength() { return _len; }
|
virtual inline uint16_t getLength() const { return _len; }
|
||||||
virtual void setColorOrder() {}
|
virtual void setColorOrder() {}
|
||||||
virtual uint8_t getColorOrder() { return COL_ORDER_RGB; }
|
virtual uint8_t getColorOrder() const { return COL_ORDER_RGB; }
|
||||||
virtual uint8_t skippedLeds() { return 0; }
|
virtual uint8_t skippedLeds() const { return 0; }
|
||||||
virtual uint16_t getFrequency() { return 0U; }
|
virtual uint16_t getFrequency() const { return 0U; }
|
||||||
inline uint16_t getStart() { return _start; }
|
inline uint16_t getStart() const { return _start; }
|
||||||
inline void setStart(uint16_t start) { _start = start; }
|
inline void setStart(uint16_t start) { _start = start; }
|
||||||
inline uint8_t getType() { return _type; }
|
inline uint8_t getType() const { return _type; }
|
||||||
inline bool isOk() { return _valid; }
|
inline bool isOk() const { return _valid; }
|
||||||
inline bool isOffRefreshRequired() { return _needsRefresh; }
|
inline bool isOffRefreshRequired() const { return _needsRefresh; }
|
||||||
bool containsPixel(uint16_t pix) { return pix >= _start && pix < _start+_len; }
|
//inline bool containsPixel(uint16_t pix) const { return pix >= _start && pix < _start+_len; } // WLEDMM not used, plus wrong - it does not consider skipped pixels
|
||||||
virtual uint16_t getMaxPixels() { return MAX_LEDS_PER_BUS; };
|
virtual uint16_t getMaxPixels() const { return MAX_LEDS_PER_BUS; }
|
||||||
|
|
||||||
virtual bool hasRGB() {
|
virtual bool hasRGB() const {
|
||||||
if ((_type >= TYPE_WS2812_1CH && _type <= TYPE_WS2812_WWA) || _type == TYPE_ANALOG_1CH || _type == TYPE_ANALOG_2CH || _type == TYPE_ONOFF) return false;
|
if ((_type >= TYPE_WS2812_1CH && _type <= TYPE_WS2812_WWA) || _type == TYPE_ANALOG_1CH || _type == TYPE_ANALOG_2CH || _type == TYPE_ONOFF) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
virtual bool hasWhite() { return Bus::hasWhite(_type); }
|
virtual bool hasWhite() const { return Bus::hasWhite(_type); }
|
||||||
static bool hasWhite(uint8_t type) {
|
static bool hasWhite(uint8_t type) {
|
||||||
if ((type >= TYPE_WS2812_1CH && type <= TYPE_WS2812_WWA) || type == TYPE_SK6812_RGBW || type == TYPE_TM1814 || type == TYPE_UCS8904) return true; // digital types with white channel
|
if ((type >= TYPE_WS2812_1CH && type <= TYPE_WS2812_WWA) || type == TYPE_SK6812_RGBW || type == TYPE_TM1814 || type == TYPE_UCS8904) return true; // digital types with white channel
|
||||||
if (type > TYPE_ONOFF && type <= TYPE_ANALOG_5CH && type != TYPE_ANALOG_3CH) return true; // analog types with white channel
|
if (type > TYPE_ONOFF && type <= TYPE_ANALOG_5CH && type != TYPE_ANALOG_3CH) return true; // analog types with white channel
|
||||||
if (type == TYPE_NET_DDP_RGBW) return true; // network types with white channel
|
if (type == TYPE_NET_DDP_RGBW) return true; // network types with white channel
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual bool hasCCT() {
|
virtual bool hasCCT() const {
|
||||||
if (_type == TYPE_WS2812_2CH_X3 || _type == TYPE_WS2812_WWA ||
|
if (_type == TYPE_WS2812_2CH_X3 || _type == TYPE_WS2812_WWA ||
|
||||||
_type == TYPE_ANALOG_2CH || _type == TYPE_ANALOG_5CH) return true;
|
_type == TYPE_ANALOG_2CH || _type == TYPE_ANALOG_5CH) return true;
|
||||||
return false;
|
return false;
|
||||||
@@ -157,10 +180,21 @@ class Bus {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; }
|
inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; }
|
||||||
inline uint8_t getAutoWhiteMode() { return _autoWhiteMode; }
|
inline uint8_t getAutoWhiteMode() const { return _autoWhiteMode; }
|
||||||
inline static void setGlobalAWMode(uint8_t m) { if (m < 5) _gAWM = m; else _gAWM = AW_GLOBAL_DISABLED; }
|
inline static void setGlobalAWMode(uint8_t m) { if (m < 5) _gAWM = m; else _gAWM = AW_GLOBAL_DISABLED; }
|
||||||
inline static uint8_t getGlobalAWMode() { return _gAWM; }
|
inline static uint8_t getGlobalAWMode() { return _gAWM; }
|
||||||
|
|
||||||
|
inline uint32_t restore_Color_Lossy(uint32_t c, uint8_t restoreBri) const { // shamelessly grabbed from upstream, who grabbed from NPB, who ..
|
||||||
|
if (restoreBri < 255) {
|
||||||
|
uint8_t* chan = (uint8_t*) &c;
|
||||||
|
for (uint_fast8_t i=0; i<4; i++) {
|
||||||
|
uint_fast16_t val = chan[i];
|
||||||
|
chan[i] = ((val << 8) + restoreBri) / (restoreBri + 1); //adding _bri slightly improves recovery / stops degradation on re-scale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
bool reversed = false;
|
bool reversed = false;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -175,7 +209,7 @@ class Bus {
|
|||||||
static int16_t _cct;
|
static int16_t _cct;
|
||||||
static uint8_t _cctBlend;
|
static uint8_t _cctBlend;
|
||||||
|
|
||||||
uint32_t autoWhiteCalc(uint32_t c);
|
uint32_t autoWhiteCalc(uint32_t c) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -185,7 +219,7 @@ class BusDigital : public Bus {
|
|||||||
|
|
||||||
inline void show();
|
inline void show();
|
||||||
|
|
||||||
bool canShow();
|
bool canShow() override;
|
||||||
|
|
||||||
void setBrightness(uint8_t b, bool immediate);
|
void setBrightness(uint8_t b, bool immediate);
|
||||||
|
|
||||||
@@ -193,25 +227,25 @@ class BusDigital : public Bus {
|
|||||||
|
|
||||||
void setPixelColor(uint16_t pix, uint32_t c);
|
void setPixelColor(uint16_t pix, uint32_t c);
|
||||||
|
|
||||||
uint32_t getPixelColor(uint16_t pix);
|
uint32_t getPixelColor(uint16_t pix) const override;
|
||||||
|
|
||||||
uint8_t getColorOrder() {
|
uint8_t getColorOrder() const {
|
||||||
return _colorOrder;
|
return _colorOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t getLength() {
|
uint16_t getLength() const override {
|
||||||
return _len - _skip;
|
return _len - _skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getPins(uint8_t* pinArray);
|
uint8_t getPins(uint8_t* pinArray) const;
|
||||||
|
|
||||||
void setColorOrder(uint8_t colorOrder);
|
void setColorOrder(uint8_t colorOrder);
|
||||||
|
|
||||||
uint8_t skippedLeds() {
|
uint8_t skippedLeds() const override {
|
||||||
return _skip;
|
return _skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t getFrequency() { return _frequencykHz; }
|
uint16_t getFrequency() const override { return _frequencykHz; }
|
||||||
|
|
||||||
void reinit();
|
void reinit();
|
||||||
|
|
||||||
@@ -239,13 +273,13 @@ class BusPwm : public Bus {
|
|||||||
void setPixelColor(uint16_t pix, uint32_t c);
|
void setPixelColor(uint16_t pix, uint32_t c);
|
||||||
|
|
||||||
//does no index check
|
//does no index check
|
||||||
uint32_t getPixelColor(uint16_t pix);
|
uint32_t getPixelColor(uint16_t pix) const;
|
||||||
|
|
||||||
void show();
|
void show();
|
||||||
|
|
||||||
uint8_t getPins(uint8_t* pinArray);
|
uint8_t getPins(uint8_t* pinArray) const;
|
||||||
|
|
||||||
uint16_t getFrequency() { return _frequency; }
|
uint16_t getFrequency() const override { return _frequency; }
|
||||||
|
|
||||||
void cleanup() {
|
void cleanup() {
|
||||||
deallocatePins();
|
deallocatePins();
|
||||||
@@ -273,11 +307,12 @@ class BusOnOff : public Bus {
|
|||||||
|
|
||||||
void setPixelColor(uint16_t pix, uint32_t c);
|
void setPixelColor(uint16_t pix, uint32_t c);
|
||||||
|
|
||||||
uint32_t getPixelColor(uint16_t pix);
|
uint32_t getPixelColor(uint16_t pix) const;
|
||||||
|
uint32_t getPixelColorRestored(uint16_t pix) const override { return getPixelColor(pix);} // WLEDMM BusOnOff ignores brightness
|
||||||
|
|
||||||
void show();
|
void show();
|
||||||
|
|
||||||
uint8_t getPins(uint8_t* pinArray);
|
uint8_t getPins(uint8_t* pinArray) const;
|
||||||
|
|
||||||
void cleanup() {
|
void cleanup() {
|
||||||
pinManager.deallocatePin(_pin, PinOwner::BusOnOff);
|
pinManager.deallocatePin(_pin, PinOwner::BusOnOff);
|
||||||
@@ -297,24 +332,25 @@ class BusNetwork : public Bus {
|
|||||||
public:
|
public:
|
||||||
BusNetwork(BusConfig &bc);
|
BusNetwork(BusConfig &bc);
|
||||||
|
|
||||||
uint16_t getMaxPixels() override { return 4096; };
|
uint16_t getMaxPixels() const override { return 4096; };
|
||||||
bool hasRGB() { return true; }
|
bool hasRGB() const { return true; }
|
||||||
bool hasWhite() { return _rgbw; }
|
bool hasWhite() const { return _rgbw; }
|
||||||
|
|
||||||
void setPixelColor(uint16_t pix, uint32_t c);
|
void setPixelColor(uint16_t pix, uint32_t c);
|
||||||
|
|
||||||
uint32_t __attribute__((pure)) getPixelColor(uint16_t pix); // WLEDMM attribute added
|
uint32_t __attribute__((pure)) getPixelColor(uint16_t pix) const; // WLEDMM attribute added
|
||||||
|
uint32_t __attribute__((pure)) getPixelColorRestored(uint16_t pix) const override { return getPixelColor(pix);} // WLEDMM BusNetwork ignores brightness
|
||||||
|
|
||||||
void show();
|
void show();
|
||||||
|
|
||||||
bool canShow() {
|
bool canShow() override {
|
||||||
// this should be a return value from UDP routine if it is still sending data out
|
// this should be a return value from UDP routine if it is still sending data out
|
||||||
return !_broadcastLock;
|
return !_broadcastLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getPins(uint8_t* pinArray);
|
uint8_t getPins(uint8_t* pinArray) const;
|
||||||
|
|
||||||
uint16_t getLength() {
|
uint16_t getLength() const override {
|
||||||
return _len;
|
return _len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,36 +374,27 @@ class BusHub75Matrix : public Bus {
|
|||||||
public:
|
public:
|
||||||
BusHub75Matrix(BusConfig &bc);
|
BusHub75Matrix(BusConfig &bc);
|
||||||
|
|
||||||
uint16_t getMaxPixels() override { return 4096; };
|
uint16_t getMaxPixels() const override { return MAX_LEDS; };
|
||||||
|
|
||||||
bool hasRGB() { return true; }
|
bool hasRGB() const override { return true; }
|
||||||
bool hasWhite() { return false; }
|
bool hasWhite() const override { return false; }
|
||||||
|
|
||||||
void setPixelColor(uint16_t pix, uint32_t c);
|
void setPixelColor(uint16_t pix, uint32_t c) override;
|
||||||
|
uint32_t getPixelColor(uint16_t pix) const override;
|
||||||
|
uint32_t getPixelColorRestored(uint16_t pix) const override; // lossless getPixelColor supported
|
||||||
|
|
||||||
void show() {
|
void show(void) override;
|
||||||
if(mxconfig.double_buff) {
|
|
||||||
display->flipDMABuffer(); // Show the back buffer, set currently output buffer to the back (i.e. no longer being sent to LED panels)
|
|
||||||
display->clearScreen(); // Now clear the back-buffer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBrightness(uint8_t b, bool immediate);
|
void setBrightness(uint8_t b, bool immediate) override;
|
||||||
|
|
||||||
uint8_t getPins(uint8_t* pinArray) {
|
uint8_t getPins(uint8_t* pinArray) const override {
|
||||||
pinArray[0] = mxconfig.chain_length;
|
pinArray[0] = mxconfig.chain_length;
|
||||||
return 1;
|
return 1;
|
||||||
} // Fake value due to keep finaliseInit happy
|
} // Fake value due to keep finaliseInit happy
|
||||||
|
|
||||||
void deallocatePins();
|
void deallocatePins();
|
||||||
|
|
||||||
void cleanup() {
|
void cleanup(void) override;
|
||||||
deallocatePins();
|
|
||||||
fourScanPanel = nullptr;
|
|
||||||
// delete fourScanPanel;
|
|
||||||
delete display;
|
|
||||||
_valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
~BusHub75Matrix() {
|
~BusHub75Matrix() {
|
||||||
cleanup();
|
cleanup();
|
||||||
@@ -377,8 +404,9 @@ class BusHub75Matrix : public Bus {
|
|||||||
MatrixPanel_I2S_DMA *display = nullptr;
|
MatrixPanel_I2S_DMA *display = nullptr;
|
||||||
VirtualMatrixPanel *fourScanPanel = nullptr;
|
VirtualMatrixPanel *fourScanPanel = nullptr;
|
||||||
HUB75_I2S_CFG mxconfig;
|
HUB75_I2S_CFG mxconfig;
|
||||||
uint8_t r, g, b, x, y;
|
unsigned _panelWidth = 0;
|
||||||
|
CRGB *_ledBuffer = nullptr;
|
||||||
|
byte *_ledsDirty = nullptr;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -387,7 +415,7 @@ class BusManager {
|
|||||||
BusManager() {};
|
BusManager() {};
|
||||||
|
|
||||||
//utility to get the approx. memory usage of a given BusConfig
|
//utility to get the approx. memory usage of a given BusConfig
|
||||||
static uint32_t memUsage(BusConfig &bc);
|
static uint32_t memUsage(BusConfig &bc) __attribute__((pure));
|
||||||
|
|
||||||
int add(BusConfig &bc);
|
int add(BusConfig &bc);
|
||||||
|
|
||||||
@@ -405,13 +433,14 @@ class BusManager {
|
|||||||
void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
|
void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
|
||||||
|
|
||||||
uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t pix); // WLEDMM attribute added
|
uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t pix); // WLEDMM attribute added
|
||||||
|
uint32_t __attribute__((pure)) getPixelColorRestored(uint_fast16_t pix); // WLEDMM
|
||||||
|
|
||||||
bool canAllShow();
|
bool canAllShow() const;
|
||||||
|
|
||||||
Bus* getBus(uint8_t busNr);
|
Bus* getBus(uint8_t busNr) const;
|
||||||
|
|
||||||
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
|
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
|
||||||
uint16_t getTotalLength();
|
uint16_t getTotalLength() const;
|
||||||
|
|
||||||
inline void updateColorOrderMap(const ColorOrderMap &com) {
|
inline void updateColorOrderMap(const ColorOrderMap &com) {
|
||||||
memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap));
|
memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap));
|
||||||
@@ -421,7 +450,7 @@ class BusManager {
|
|||||||
return colorOrderMap;
|
return colorOrderMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t getNumBusses() {
|
inline uint8_t getNumBusses() const {
|
||||||
return numBusses;
|
return numBusses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,7 +463,7 @@ class BusManager {
|
|||||||
unsigned laststart = 0;
|
unsigned laststart = 0;
|
||||||
unsigned lastend = 0;
|
unsigned lastend = 0;
|
||||||
|
|
||||||
inline uint8_t getNumVirtualBusses() {
|
inline uint8_t getNumVirtualBusses() const {
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (int i=0; i<numBusses; i++) if (busses[i]->getType() >= TYPE_NET_DDP_RGB && busses[i]->getType() < 96) j++;
|
for (int i=0; i<numBusses; i++) if (busses[i]->getType() >= TYPE_NET_DDP_RGB && busses[i]->getType() < 96) j++;
|
||||||
return j;
|
return j;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
/*
|
/*
|
||||||
* color blend function
|
* color blend function
|
||||||
*/
|
*/
|
||||||
IRAM_ATTR_YN uint32_t color_blend(uint32_t color1, uint32_t color2, uint_fast16_t blend, bool b16) {
|
IRAM_ATTR_YN __attribute__((hot)) uint32_t color_blend(uint32_t color1, uint32_t color2, uint_fast16_t blend, bool b16) {
|
||||||
if(blend == 0) return color1;
|
if(blend == 0) return color1;
|
||||||
if (color1 == color2) return color1; // WLEDMM shortcut
|
if (color1 == color2) return color1; // WLEDMM shortcut
|
||||||
const uint_fast16_t blendmax = b16 ? 0xFFFF : 0xFF;
|
const uint_fast16_t blendmax = b16 ? 0xFFFF : 0xFF;
|
||||||
@@ -71,7 +71,7 @@ IRAM_ATTR_YN uint32_t color_add(uint32_t c1, uint32_t c2, bool fast) // WLEDMM
|
|||||||
* if using "video" method the resulting color will never become black unless it is already black
|
* if using "video" method the resulting color will never become black unless it is already black
|
||||||
*/
|
*/
|
||||||
|
|
||||||
IRAM_ATTR_YN uint32_t color_fade(uint32_t c1, uint8_t amount, bool video)
|
IRAM_ATTR_YN __attribute__((hot)) uint32_t color_fade(uint32_t c1, uint8_t amount, bool video)
|
||||||
{
|
{
|
||||||
if (amount == 0) return 0; // WLEDMM shortcut
|
if (amount == 0) return 0; // WLEDMM shortcut
|
||||||
|
|
||||||
@@ -297,7 +297,7 @@ static float maxf (float v, float w) // WLEDMM better use standard library fmax
|
|||||||
|
|
||||||
// adjust RGB values based on color temperature in K (range [2800-10200]) (https://en.wikipedia.org/wiki/Color_balance)
|
// adjust RGB values based on color temperature in K (range [2800-10200]) (https://en.wikipedia.org/wiki/Color_balance)
|
||||||
// called from bus manager when color correction is enabled!
|
// called from bus manager when color correction is enabled!
|
||||||
uint32_t IRAM_ATTR_YN colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb) // WLEDMM: IRAM_ATTR_YN
|
uint32_t __attribute__((hot)) IRAM_ATTR_YN colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb) // WLEDMM: IRAM_ATTR_YN
|
||||||
{
|
{
|
||||||
//remember so that slow colorKtoRGB() doesn't have to run for every setPixelColor()
|
//remember so that slow colorKtoRGB() doesn't have to run for every setPixelColor()
|
||||||
static byte correctionRGB[4] = {0,0,0,0};
|
static byte correctionRGB[4] = {0,0,0,0};
|
||||||
@@ -406,13 +406,19 @@ static void calcInvGammaTable(float gamma)
|
|||||||
gammaTinv[i] = (int)(powf((float)i / 255.0f, gammaInv) * 255.0f + 0.5f);
|
gammaTinv[i] = (int)(powf((float)i / 255.0f, gammaInv) * 255.0f + 0.5f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint8_t unGamma8(uint8_t value) {
|
uint8_t __attribute__((hot)) unGamma8(uint8_t value) {
|
||||||
//if (!gammaCorrectCol || (value == 0) || (value == 255)) return value;
|
//if (!gammaCorrectCol || (value == 0) || (value == 255)) return value;
|
||||||
if ((value == 0) || (value == 255)) return value;
|
if ((value == 0) || (value == 255)) return value;
|
||||||
if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) return value;
|
if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) return value;
|
||||||
if (gammaTinv[255] == 0) calcInvGammaTable(gammaCorrectVal);
|
if (gammaTinv[255] == 0) calcInvGammaTable(gammaCorrectVal);
|
||||||
return gammaTinv[value];
|
return gammaTinv[value];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t __attribute__((hot)) unGamma24(uint32_t c) {
|
||||||
|
if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) return c;
|
||||||
|
if (gammaTinv[255] == 0) calcInvGammaTable(gammaCorrectVal);
|
||||||
|
return RGBW32(gammaTinv[R(c)], gammaTinv[G(c)], gammaTinv[B(c)], W(c));
|
||||||
|
}
|
||||||
// wleDMM end
|
// wleDMM end
|
||||||
|
|
||||||
uint8_t gamma8_cal(uint8_t b, float gamma)
|
uint8_t gamma8_cal(uint8_t b, float gamma)
|
||||||
@@ -432,13 +438,13 @@ void calcGammaTable(float gamma)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// used for individual channel or brightness gamma correction
|
// used for individual channel or brightness gamma correction
|
||||||
IRAM_ATTR_YN uint8_t gamma8(uint8_t b) // WLEDMM added IRAM_ATTR_YN
|
IRAM_ATTR_YN __attribute__((hot)) uint8_t gamma8(uint8_t b) // WLEDMM added IRAM_ATTR_YN
|
||||||
{
|
{
|
||||||
return gammaT[b];
|
return gammaT[b];
|
||||||
}
|
}
|
||||||
|
|
||||||
// used for color gamma correction
|
// used for color gamma correction
|
||||||
uint32_t gamma32(uint32_t color)
|
uint32_t __attribute__((hot)) gamma32(uint32_t color)
|
||||||
{
|
{
|
||||||
if (!gammaCorrectCol) return color;
|
if (!gammaCorrectCol) return color;
|
||||||
uint8_t w = W(color);
|
uint8_t w = W(color);
|
||||||
|
|||||||
@@ -245,7 +245,9 @@
|
|||||||
#define TYPE_P9813 53
|
#define TYPE_P9813 53
|
||||||
#define TYPE_LPD6803 54
|
#define TYPE_LPD6803 54
|
||||||
|
|
||||||
|
// WLEDMM additional types
|
||||||
#define TYPE_HUB75MATRIX 100 // 100 - 110
|
#define TYPE_HUB75MATRIX 100 // 100 - 110
|
||||||
|
// WLEDMM caution - do not use bus types > 127
|
||||||
|
|
||||||
//Network types (master broadcast) (80-95)
|
//Network types (master broadcast) (80-95)
|
||||||
#define TYPE_NET_DDP_RGB 80 //network DDP RGB bus (master broadcast bus)
|
#define TYPE_NET_DDP_RGB 80 //network DDP RGB bus (master broadcast bus)
|
||||||
@@ -257,6 +259,8 @@
|
|||||||
#define IS_PWM(t) ((t) > 40 && (t) < 46)
|
#define IS_PWM(t) ((t) > 40 && (t) < 46)
|
||||||
#define NUM_PWM_PINS(t) ((t) - 40) //for analog PWM 41-45 only
|
#define NUM_PWM_PINS(t) ((t) - 40) //for analog PWM 41-45 only
|
||||||
#define IS_2PIN(t) ((t) > 47)
|
#define IS_2PIN(t) ((t) > 47)
|
||||||
|
#define IS_VIRTUAL(t) ( ((t) <= TYPE_RESERVED) || (((t) >= TYPE_NET_DDP_RGB) && ((t) < (TYPE_NET_DDP_RGB + 16))) ) // WLEDMM 80..95 are network "virtual" busses
|
||||||
|
#define EXCLUDE_FROM_ABL(t) ( IS_VIRTUAL(t) || ( (t) >= (TYPE_HUB75MATRIX) && (t) < (TYPE_HUB75MATRIX + 10))) // WLEDMM do not apply auto-brightness-limiter on these bus types
|
||||||
|
|
||||||
//Color orders
|
//Color orders
|
||||||
#define COL_ORDER_GRB 0 //GRB(w),defaut
|
#define COL_ORDER_GRB 0 //GRB(w),defaut
|
||||||
@@ -352,6 +356,7 @@
|
|||||||
#define ERR_LOW_SEG_MEM 34 // WLEDMM: low memory (segment data RAM)
|
#define ERR_LOW_SEG_MEM 34 // WLEDMM: low memory (segment data RAM)
|
||||||
#define ERR_LOW_WS_MEM 35 // WLEDMM: low memory (ws)
|
#define ERR_LOW_WS_MEM 35 // WLEDMM: low memory (ws)
|
||||||
#define ERR_LOW_AJAX_MEM 36 // WLEDMM: low memory (oappend)
|
#define ERR_LOW_AJAX_MEM 36 // WLEDMM: low memory (oappend)
|
||||||
|
#define ERR_LOW_BUF 37 // WLEDMM: low memory (LED buffer from allocLEDs)
|
||||||
|
|
||||||
// Timer mode types
|
// Timer mode types
|
||||||
#define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness
|
#define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness
|
||||||
@@ -425,13 +430,15 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WLED_USE_ETHERNET
|
#ifndef E131_MAX_UNIVERSE_COUNT
|
||||||
#define E131_MAX_UNIVERSE_COUNT 20
|
#ifdef WLED_USE_ETHERNET
|
||||||
#else
|
#define E131_MAX_UNIVERSE_COUNT 20
|
||||||
#ifdef ESP8266
|
|
||||||
#define E131_MAX_UNIVERSE_COUNT 9
|
|
||||||
#else
|
#else
|
||||||
#define E131_MAX_UNIVERSE_COUNT 12
|
#ifdef ESP8266
|
||||||
|
#define E131_MAX_UNIVERSE_COUNT 9
|
||||||
|
#else
|
||||||
|
#define E131_MAX_UNIVERSE_COUNT 12
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -478,7 +485,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define MIN_HEAP_SIZE (8k for AsyncWebServer)
|
//#define MIN_HEAP_SIZE (8k for AsyncWebServer)
|
||||||
|
#if !defined(MIN_HEAP_SIZE)
|
||||||
#define MIN_HEAP_SIZE 8192
|
#define MIN_HEAP_SIZE 8192
|
||||||
|
#endif
|
||||||
|
|
||||||
// Maximum size of node map (list of other WLED instances)
|
// Maximum size of node map (list of other WLED instances)
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ var cfg = {
|
|||||||
theme:{base:"dark", bg:{url:""}, alpha:{bg:0.6,tab:0.8}, color:{bg:""}},
|
theme:{base:"dark", bg:{url:""}, alpha:{bg:0.6,tab:0.8}, color:{bg:""}},
|
||||||
comp :{colors:{picker: true, rgb: false, quick: true, hex: false},
|
comp :{colors:{picker: true, rgb: false, quick: true, hex: false},
|
||||||
labels:true, pcmbot:false, pid:true, seglen:false, segpwr:false, segexp:true,
|
labels:true, pcmbot:false, pid:true, seglen:false, segpwr:false, segexp:true,
|
||||||
css:true, hdays:false, fxdef:true} //WLEDMM segexp true as default
|
css:true, hdays:false, fxdef:true, fxdef2:false} //WLEDMM segexp true as default, fxdef2 added
|
||||||
};
|
};
|
||||||
var hol = [
|
var hol = [
|
||||||
[0,11,24,4,"https://aircoookie.github.io/xmas.png"], // christmas
|
[0,11,24,4,"https://aircoookie.github.io/xmas.png"], // christmas
|
||||||
@@ -696,7 +696,7 @@ function populateInfo(i)
|
|||||||
if (i.ver.includes("0.14.0-b15.22")) vcn = "Lupo";
|
if (i.ver.includes("0.14.0-b15.22")) vcn = "Lupo";
|
||||||
if (i.ver.includes("0.14.1-b3")) vcn = "Fried Chicken"; // final line of "One Vision" by Queen
|
if (i.ver.includes("0.14.1-b3")) vcn = "Fried Chicken"; // final line of "One Vision" by Queen
|
||||||
if (i.ver.includes("0.14.3-b")) vcn = "Fried Chicken";
|
if (i.ver.includes("0.14.3-b")) vcn = "Fried Chicken";
|
||||||
cn += `v${i.ver} <i>"${vcn}"</i><p>(WLEDMM_${i.ver} ${i.rel}.bin)</p><p><em>build ${i.vid}</em></p><table>
|
cn += `v${i.ver} <i>"${vcn}"</i><p>(WLEDMM ${i.rel}.bin)</p><p><em>build ${i.vid}</em></p><table>
|
||||||
${urows}
|
${urows}
|
||||||
${urows===""?'':'<tr><td colspan=2><hr style="height:1px;border-width:0;color:SeaGreen;background-color:Seagreen"></td></tr>'}
|
${urows===""?'':'<tr><td colspan=2><hr style="height:1px;border-width:0;color:SeaGreen;background-color:Seagreen"></td></tr>'}
|
||||||
${i.opt&0x100?inforow("Net Print ☾","<button class=\"btn btn-xs\" onclick=\"requestJson({'netDebug':"+(i.opt&0x0080?"false":"true")+"});\"><i class=\"icons "+(i.opt&0x0080?"on":"off")+"\"></i></button>"):''}
|
${i.opt&0x100?inforow("Net Print ☾","<button class=\"btn btn-xs\" onclick=\"requestJson({'netDebug':"+(i.opt&0x0080?"false":"true")+"});\"><i class=\"icons "+(i.opt&0x0080?"on":"off")+"\"></i></button>"):''}
|
||||||
@@ -2008,6 +2008,9 @@ function readState(s,command=false)
|
|||||||
case 36:
|
case 36:
|
||||||
errstr = "Low Memory (oappend buffer).";
|
errstr = "Low Memory (oappend buffer).";
|
||||||
break;
|
break;
|
||||||
|
case 37:
|
||||||
|
errstr = "no memory for LEDs buffer.";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
showToast('Error ' + s.error + ": " + errstr, true);
|
showToast('Error ' + s.error + ": " + errstr, true);
|
||||||
}
|
}
|
||||||
@@ -2853,7 +2856,7 @@ function setFX(ind = null)
|
|||||||
} else {
|
} else {
|
||||||
d.querySelector(`#fxlist input[name="fx"][value="${ind}"]`).checked = true;
|
d.querySelector(`#fxlist input[name="fx"][value="${ind}"]`).checked = true;
|
||||||
}
|
}
|
||||||
var obj = {"seg": {"fx": parseInt(ind), "fxdef": cfg.comp.fxdef}}; // fxdef sets effect parameters to default values
|
var obj = {"seg": {"fx": parseInt(ind), "fxdef": cfg.comp.fxdef, "fxdef2": cfg.comp.fxdef2}}; // fxdef sets effect parameters to default values; WLEDMM fxdef2 only set slider defaults
|
||||||
requestJson(obj);
|
requestJson(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -250,7 +250,7 @@
|
|||||||
if (s+c > sLC) sLC = s+c; //update total count
|
if (s+c > sLC) sLC = s+c; //update total count
|
||||||
if(c>maxLC)maxLC=c; //max per output
|
if(c>maxLC)maxLC=c; //max per output
|
||||||
var t = parseInt(d.getElementsByName("LT"+n)[0].value); // LED type SELECT
|
var t = parseInt(d.getElementsByName("LT"+n)[0].value); // LED type SELECT
|
||||||
if (t<80) sPC+=c; //virtual out busses do not count towards physical LEDs
|
if ((t<128) && ((t<80) || ((t>99)))) sPC+=c; //virtual out busses do not count towards physical LEDs //WLEDMM include HUB75 (>=100)
|
||||||
} // increase led count
|
} // increase led count
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,8 @@
|
|||||||
"segexp" : "Always expand first segment",
|
"segexp" : "Always expand first segment",
|
||||||
"css": "Enable custom CSS",
|
"css": "Enable custom CSS",
|
||||||
"hdays": "Enable custom Holidays list",
|
"hdays": "Enable custom Holidays list",
|
||||||
"fxdef": "Use effect default parameters"
|
"fxdef": "Use effect default parameters",
|
||||||
|
"fxdef2": "Don't use effect palette and segment parameters"
|
||||||
},
|
},
|
||||||
"theme":{
|
"theme":{
|
||||||
"alpha": {
|
"alpha": {
|
||||||
|
|||||||
@@ -1135,7 +1135,7 @@ function setSegBri(s)
|
|||||||
function setEffect(ind = 0)
|
function setEffect(ind = 0)
|
||||||
{
|
{
|
||||||
tglFxDropdown();
|
tglFxDropdown();
|
||||||
var obj = {"seg": {"fx": parseInt(ind), "fxdef":true}}; // fxdef sets effect parameters to default values, TODO add client setting
|
var obj = {"seg": {"fx": parseInt(ind), "fxdef":true, "fxdef2":false}}; // fxdef sets effect parameters to default values, TODO add client setting
|
||||||
requestJson(obj);
|
requestJson(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -187,6 +187,9 @@ void DMXInput::updateInternal()
|
|||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
if (dmx_receive(inputPortNum, &packet, DMX_TIMEOUT_TICK)) {
|
if (dmx_receive(inputPortNum, &packet, DMX_TIMEOUT_TICK)) {
|
||||||
if (!packet.err) {
|
if (!packet.err) {
|
||||||
|
if(!connected) {
|
||||||
|
USER_PRINTLN("DMX Input - connected");
|
||||||
|
}
|
||||||
connected = true;
|
connected = true;
|
||||||
identify = isIdentifyOn();
|
identify = isIdentifyOn();
|
||||||
if (!packet.is_rdm) {
|
if (!packet.is_rdm) {
|
||||||
@@ -199,6 +202,9 @@ void DMXInput::updateInternal()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if(connected) {
|
||||||
|
USER_PRINTLN("DMX Input - disconnected");
|
||||||
|
}
|
||||||
connected = false;
|
connected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ void calcGammaTable(float gamma);
|
|||||||
uint8_t __attribute__((pure)) gamma8(uint8_t b); // WLEDMM: added attribute pure
|
uint8_t __attribute__((pure)) gamma8(uint8_t b); // WLEDMM: added attribute pure
|
||||||
uint32_t __attribute__((pure)) gamma32(uint32_t); // WLEDMM: added attribute pure
|
uint32_t __attribute__((pure)) gamma32(uint32_t); // WLEDMM: added attribute pure
|
||||||
uint8_t unGamma8(uint8_t value); // WLEDMM revert gamma correction
|
uint8_t unGamma8(uint8_t value); // WLEDMM revert gamma correction
|
||||||
|
uint32_t unGamma24(uint32_t c); // WLEDMM for 24bit color (white left as-is)
|
||||||
|
|
||||||
//dmx_output.cpp
|
//dmx_output.cpp
|
||||||
void initDMXOutput();
|
void initDMXOutput();
|
||||||
@@ -249,7 +250,7 @@ void refreshNodeList();
|
|||||||
void sendSysInfoUDP();
|
void sendSysInfoUDP();
|
||||||
|
|
||||||
//network.cpp
|
//network.cpp
|
||||||
int getSignalQuality(int rssi);
|
int getSignalQuality(int rssi) __attribute__((const));
|
||||||
void WiFiEvent(WiFiEvent_t event);
|
void WiFiEvent(WiFiEvent_t event);
|
||||||
|
|
||||||
//um_manager.cpp
|
//um_manager.cpp
|
||||||
@@ -298,6 +299,7 @@ class Usermod {
|
|||||||
virtual ~Usermod() { if (um_data) delete um_data; }
|
virtual ~Usermod() { if (um_data) delete um_data; }
|
||||||
virtual void setup() = 0; // pure virtual, has to be overriden
|
virtual void setup() = 0; // pure virtual, has to be overriden
|
||||||
virtual void loop() = 0; // pure virtual, has to be overriden
|
virtual void loop() = 0; // pure virtual, has to be overriden
|
||||||
|
virtual void loop2() {} // WLEDMM called just before effects will be processed
|
||||||
virtual void handleOverlayDraw() {} // called after all effects have been processed, just before strip.show()
|
virtual void handleOverlayDraw() {} // called after all effects have been processed, just before strip.show()
|
||||||
virtual bool handleButton(uint8_t b) { return false; } // button overrides are possible here
|
virtual bool handleButton(uint8_t b) { return false; } // button overrides are possible here
|
||||||
virtual bool getUMData(um_data_t **data) { if (data) *data = nullptr; return false; }; // usermod data exchange [see examples for audio effects]
|
virtual bool getUMData(um_data_t **data) { if (data) *data = nullptr; return false; }; // usermod data exchange [see examples for audio effects]
|
||||||
@@ -324,10 +326,11 @@ class Usermod {
|
|||||||
class UsermodManager {
|
class UsermodManager {
|
||||||
private:
|
private:
|
||||||
Usermod* ums[WLED_MAX_USERMODS];
|
Usermod* ums[WLED_MAX_USERMODS];
|
||||||
byte numMods = 0;
|
unsigned numMods = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void loop();
|
void loop();
|
||||||
|
void loop2(); // WLEDMM loop just before drawing effects (presets and everything already handled)
|
||||||
void handleOverlayDraw();
|
void handleOverlayDraw();
|
||||||
bool handleButton(uint8_t b);
|
bool handleButton(uint8_t b);
|
||||||
bool getUMData(um_data_t **um_data, uint8_t mod_id = USERMOD_ID_RESERVED); // USERMOD_ID_RESERVED will poll all usermods
|
bool getUMData(um_data_t **um_data, uint8_t mod_id = USERMOD_ID_RESERVED); // USERMOD_ID_RESERVED will poll all usermods
|
||||||
@@ -368,7 +371,7 @@ bool oappendi(int i); // append new number to temp buffer efficiently
|
|||||||
void sappend(char stype, const char* key, int val);
|
void sappend(char stype, const char* key, int val);
|
||||||
void sappends(char stype, const char* key, char* val);
|
void sappends(char stype, const char* key, char* val);
|
||||||
void prepareHostname(char* hostname);
|
void prepareHostname(char* hostname);
|
||||||
bool isAsterisksOnly(const char* str, byte maxLen);
|
bool isAsterisksOnly(const char* str, byte maxLen) __attribute__((pure));
|
||||||
bool requestJSONBufferLock(uint8_t module=255);
|
bool requestJSONBufferLock(uint8_t module=255);
|
||||||
void releaseJSONBufferLock();
|
void releaseJSONBufferLock();
|
||||||
uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen);
|
uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen);
|
||||||
@@ -409,13 +412,14 @@ void clearEEPROM();
|
|||||||
//wled_math.cpp
|
//wled_math.cpp
|
||||||
#ifndef WLED_USE_REAL_MATH
|
#ifndef WLED_USE_REAL_MATH
|
||||||
template <typename T> T atan_t(T x);
|
template <typename T> T atan_t(T x);
|
||||||
float cos_t(float phi);
|
float cos_t(float phi) __attribute__((const));
|
||||||
float sin_t(float x);
|
float sin_t(float x) __attribute__((const));
|
||||||
float tan_t(float x);
|
float tan_t(float x) __attribute__((const));
|
||||||
float acos_t(float x);
|
float acos_t(float x);
|
||||||
float asin_t(float x);
|
float asin_t(float x);
|
||||||
float floor_t(float x);
|
float atan_t(float x) __attribute__((const));
|
||||||
float fmod_t(float num, float denom);
|
float floor_t(float x) __attribute__((const));
|
||||||
|
float fmod_t(float num, float denom) __attribute__((const));
|
||||||
#else
|
#else
|
||||||
#include <math.h> // WLEDMM use "float" variants
|
#include <math.h> // WLEDMM use "float" variants
|
||||||
#define sin_t sinf
|
#define sin_t sinf
|
||||||
|
|||||||
@@ -211,7 +211,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[32];
|
char vString[32];
|
||||||
snprintf_P(vString, sizeof(vString)-1, PSTR("0.14.1-b32.40/%i"),VERSION);
|
snprintf_P(vString, sizeof(vString)-1, PSTR("0.14.1-b32.41/%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);
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
// end fix
|
// end fix
|
||||||
if (getVal(elem["fx"], &fx, 0, last)) { //load effect ('r' random, '~' inc/dec, 0-255 exact value, 5~10r pick random between 5 & 10)
|
if (getVal(elem["fx"], &fx, 0, last)) { //load effect ('r' random, '~' inc/dec, 0-255 exact value, 5~10r pick random between 5 & 10)
|
||||||
if (!presetId && currentPlaylist>=0) unloadPlaylist();
|
if (!presetId && currentPlaylist>=0) unloadPlaylist();
|
||||||
if (fx != seg.mode) seg.setMode(fx, elem[F("fxdef")]);
|
if (fx != seg.mode) seg.setMode(fx, elem[F("fxdef")], elem[F("fxdef2")]); // WLEDMM fxdef2 added
|
||||||
}
|
}
|
||||||
|
|
||||||
//getVal also supports inc/decrementing and random
|
//getVal also supports inc/decrementing and random
|
||||||
@@ -904,8 +904,8 @@ void serializeInfo(JsonObject root)
|
|||||||
|
|
||||||
JsonObject leds = root.createNestedObject("leds");
|
JsonObject leds = root.createNestedObject("leds");
|
||||||
leds[F("count")] = strip.getLengthTotal();
|
leds[F("count")] = strip.getLengthTotal();
|
||||||
leds[F("countP")] = strip.getLengthPhysical(); //WLEDMM
|
leds[F("countP")] = strip.getLengthPhysical2(); //WLEDMM - getLengthPhysical plus plysical busses not supporting ABL (i.e. HUB75)
|
||||||
leds[F("pwr")] = strip.currentMilliamps;
|
leds[F("pwr")] = strip.currentMilliamps > 100 ? strip.currentMilliamps : 0; // WLEDMM show "not calculated" for HUB75, or when all LEDs are out
|
||||||
leds["fps"] = strip.getFps();
|
leds["fps"] = strip.getFps();
|
||||||
leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;
|
leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;
|
||||||
leds[F("maxseg")] = strip.getMaxSegments();
|
leds[F("maxseg")] = strip.getMaxSegments();
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ void toggleOnOff()
|
|||||||
|
|
||||||
|
|
||||||
//scales the brightness with the briMultiplier factor
|
//scales the brightness with the briMultiplier factor
|
||||||
IRAM_ATTR_YN byte scaledBri(byte in) // WLEDMM added IRAM_ATTR_YN
|
IRAM_ATTR_YN __attribute__((hot)) byte scaledBri(byte in) // WLEDMM added IRAM_ATTR_YN
|
||||||
{
|
{
|
||||||
if (briMultiplier == 100) return(in); // WLEDMM shortcut
|
if (briMultiplier == 100) return(in); // WLEDMM shortcut
|
||||||
uint_fast16_t val = ((uint_fast16_t)in*(uint_fast16_t)briMultiplier)/100; // WLEDMM
|
uint_fast16_t val = ((uint_fast16_t)in*(uint_fast16_t)briMultiplier)/100; // WLEDMM
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ const ethernet_settings ethernetBoards[] = {
|
|||||||
|
|
||||||
// ESP32-ETHERNET-KIT-VE
|
// ESP32-ETHERNET-KIT-VE
|
||||||
{
|
{
|
||||||
0, // eth_address,
|
1, // eth_address, WLED-MM: Changed from 0 to 1 based on not working with 0 on same devkit.
|
||||||
5, // eth_power,
|
5, // eth_power,
|
||||||
23, // eth_mdc,
|
23, // eth_mdc,
|
||||||
18, // eth_mdio,
|
18, // eth_mdio,
|
||||||
|
|||||||
@@ -113,13 +113,18 @@ String PinManagerClass::getPinSpecialText(int gpio) { // special purpose PIN in
|
|||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
// ESP32-S3
|
// ESP32-S3
|
||||||
if (gpio > 18 && gpio < 21) return (F("USB (CDC) / JTAG"));
|
if (gpio > 18 && gpio < 21) return (F("USB (CDC) or JTAG"));
|
||||||
#if !defined(BOARD_HAS_PSRAM)
|
#if CONFIG_SPIRAM_MODE_OCT && defined(BOARD_HAS_PSRAM)
|
||||||
if (gpio > 32 && gpio < 38) return (F("(optional) Octal Flash or PSRAM"));
|
|
||||||
#else
|
|
||||||
if (gpio > 32 && gpio < 38) return (F("(reserved) Octal PSRAM or Octal Flash"));
|
if (gpio > 32 && gpio < 38) return (F("(reserved) Octal PSRAM or Octal Flash"));
|
||||||
#endif
|
#endif
|
||||||
//if (gpio == 0 || gpio == 3 || gpio == 45 || gpio == 46) return (F("(strapping pin)"));
|
//if (gpio == 0 || gpio == 3 || gpio == 45 || gpio == 46) return (F("(strapping pin)"));
|
||||||
|
#ifdef ARDUINO_TTGO_T7_S3
|
||||||
|
// experimental: a few special pins of the T7-S3 board
|
||||||
|
if (gpio == 2) return (F("(reserved) _VBAT voltage monitoring"));
|
||||||
|
if (gpio == 17) return (F("onboard LED"));
|
||||||
|
//if (gpio == 3) return (F("(cross-connected to pin 3-1)")); // WLEDMM experimental
|
||||||
|
//if (gpio == 12) return (F("(cross-connected to pin 12-1)")); // WLEDMM experimental
|
||||||
|
#endif
|
||||||
|
|
||||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
|
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
// ESP32-S2
|
// ESP32-S2
|
||||||
@@ -129,7 +134,7 @@ String PinManagerClass::getPinSpecialText(int gpio) { // special purpose PIN in
|
|||||||
|
|
||||||
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
// ESP32-C3
|
// ESP32-C3
|
||||||
if (gpio > 17 && gpio < 20) return (F("USB (CDC) / JTAG"));
|
if (gpio > 17 && gpio < 20) return (F("USB (CDC) or JTAG"));
|
||||||
//if (gpio == 2 || gpio == 8 || gpio == 9) return (F("(strapping pin)"));
|
//if (gpio == 2 || gpio == 8 || gpio == 9) return (F("(strapping pin)"));
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -723,19 +728,25 @@ bool PinManagerClass::joinWire(int8_t pinSDA, int8_t pinSCL) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Check if supplied GPIO is ok to use
|
// Check if supplied GPIO is ok to use
|
||||||
bool PinManagerClass::isPinOk(byte gpio, bool output)
|
bool PinManagerClass::isPinOk(byte gpio, bool output) const
|
||||||
{
|
{
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
if (digitalPinIsValid(gpio)) {
|
if (digitalPinIsValid(gpio)) {
|
||||||
#if defined(CONFIG_IDF_TARGET_ESP32C3)
|
#if defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
// strapping pins: 2, 8, & 9
|
// strapping pins: 2, 8, & 9
|
||||||
if (gpio > 11 && gpio < 18) return false; // 11-17 SPI FLASH
|
if (gpio > 11 && gpio < 18) return false; // 11-17 SPI FLASH
|
||||||
|
#if ARDUINO_USB_CDC_ON_BOOT == 1 || ARDUINO_USB_DFU_ON_BOOT == 1
|
||||||
if (gpio > 17 && gpio < 20) return false; // 18-19 USB-JTAG
|
if (gpio > 17 && gpio < 20) return false; // 18-19 USB-JTAG
|
||||||
|
#endif
|
||||||
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
// 00 to 18 are for general use. Be careful about straping pins GPIO0 and GPIO3 - these may be pulled-up or pulled-down on your board.
|
// 00 to 18 are for general use. Be careful about straping pins GPIO0 and GPIO3 - these may be pulled-up or pulled-down on your board.
|
||||||
|
#if ARDUINO_USB_CDC_ON_BOOT == 1 || ARDUINO_USB_DFU_ON_BOOT == 1
|
||||||
if (gpio > 18 && gpio < 21) return false; // 19 + 20 = USB-JTAG. Not recommended for other uses.
|
if (gpio > 18 && gpio < 21) return false; // 19 + 20 = USB-JTAG. Not recommended for other uses.
|
||||||
|
#endif
|
||||||
if (gpio > 21 && gpio < 33) return false; // 22 to 32: not connected + SPI FLASH
|
if (gpio > 21 && gpio < 33) return false; // 22 to 32: not connected + SPI FLASH
|
||||||
//if (gpio > 32 && gpio < 38) return false; // 33 to 37: not available if using _octal_ SPI Flash or _octal_ PSRAM
|
// #if CONFIG_SPIRAM_MODE_OCT && defined(BOARD_HAS_PSRAM)
|
||||||
|
// if (gpio > 32 && gpio < 38) return !psramFound(); // 33 to 37: not available if using _octal_ SPI Flash or _octal_ PSRAM
|
||||||
|
// #endif
|
||||||
// 38 to 48 are for general use. Be careful about straping pins GPIO45 and GPIO46 - these may be pull-up or pulled-down on your board.
|
// 38 to 48 are for general use. Be careful about straping pins GPIO45 and GPIO46 - these may be pull-up or pulled-down on your board.
|
||||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
|
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
// strapping pins: 0, 45 & 46
|
// strapping pins: 0, 45 & 46
|
||||||
@@ -757,7 +768,7 @@ bool PinManagerClass::isPinOk(byte gpio, bool output)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PinOwner PinManagerClass::getPinOwner(byte gpio) {
|
PinOwner PinManagerClass::getPinOwner(byte gpio) const {
|
||||||
if (gpio >= WLED_NUM_PINS) return PinOwner::None; // catch error case, to avoid array out-of-bounds access
|
if (gpio >= WLED_NUM_PINS) return PinOwner::None; // catch error case, to avoid array out-of-bounds access
|
||||||
if (!isPinOk(gpio, false)) return PinOwner::None;
|
if (!isPinOk(gpio, false)) return PinOwner::None;
|
||||||
return ownerTag[gpio];
|
return ownerTag[gpio];
|
||||||
|
|||||||
@@ -125,9 +125,9 @@ class PinManagerClass {
|
|||||||
// will return true for reserved pins
|
// will return true for reserved pins
|
||||||
bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None);
|
bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None);
|
||||||
// will return false for reserved pins
|
// will return false for reserved pins
|
||||||
bool isPinOk(byte gpio, bool output = true);
|
bool isPinOk(byte gpio, bool output = true) const;
|
||||||
|
|
||||||
PinOwner getPinOwner(byte gpio);
|
PinOwner getPinOwner(byte gpio) const;
|
||||||
|
|
||||||
// WLEDMM begin
|
// WLEDMM begin
|
||||||
String getOwnerText(PinOwner tag); // WLEDMM - return PIN owner tag as text
|
String getOwnerText(PinOwner tag); // WLEDMM - return PIN owner tag as text
|
||||||
|
|||||||
@@ -1062,7 +1062,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (i != selectedSeg && (singleSegment || !seg.isActive() || !seg.isSelected())) continue; // skip non main segments if not applying to all
|
if (i != selectedSeg && (singleSegment || !seg.isActive() || !seg.isSelected())) continue; // skip non main segments if not applying to all
|
||||||
if (fxModeChanged) seg.setMode(effectIn, req.indexOf(F("FXD="))>0); // apply defaults if FXD= is specified
|
if (fxModeChanged) seg.setMode(effectIn, req.indexOf(F("FXD="))>0, req.indexOf(F("FXD2="))>0); // apply defaults if FXD= is specified
|
||||||
if (speedChanged) seg.speed = speedIn;
|
if (speedChanged) seg.speed = speedIn;
|
||||||
if (intensityChanged) seg.intensity = intensityIn;
|
if (intensityChanged) seg.intensity = intensityIn;
|
||||||
if (paletteChanged) seg.setPalette(paletteIn);
|
if (paletteChanged) seg.setPalette(paletteIn);
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ char* dayShortStr(uint8_t day);
|
|||||||
|
|
||||||
/* low level functions to convert to and from system time */
|
/* low level functions to convert to and from system time */
|
||||||
void breakTime(time_t time, tmElements_t &tm); // break time_t into elements
|
void breakTime(time_t time, tmElements_t &tm); // break time_t into elements
|
||||||
time_t makeTime(tmElements_t &tm); // convert time elements into time_t
|
time_t makeTime(tmElements_t &tm) __attribute__((pure)); // convert time elements into time_t
|
||||||
|
|
||||||
} // extern "C++"
|
} // extern "C++"
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|||||||
@@ -4,49 +4,50 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//Usermod Manager internals
|
//Usermod Manager internals
|
||||||
void UsermodManager::setup() { for (byte i = 0; i < numMods; i++) ums[i]->setup(); }
|
void UsermodManager::setup() { for (unsigned i = 0; i < numMods; i++) ums[i]->setup(); }
|
||||||
void UsermodManager::connected() { for (byte i = 0; i < numMods; i++) ums[i]->connected(); }
|
void UsermodManager::connected() { for (unsigned i = 0; i < numMods; i++) ums[i]->connected(); }
|
||||||
void UsermodManager::loop() { for (byte i = 0; i < numMods; i++) ums[i]->loop(); }
|
void UsermodManager::loop() { for (unsigned i = 0; i < numMods; i++) ums[i]->loop(); }
|
||||||
void UsermodManager::handleOverlayDraw() { for (byte i = 0; i < numMods; i++) ums[i]->handleOverlayDraw(); }
|
void UsermodManager::loop2() { for (unsigned i = 0; i < numMods; i++) ums[i]->loop2(); }
|
||||||
// void UsermodManager::appendConfigData() { for (byte i = 0; i < numMods; i++) ums[i]->appendConfigData(); } //WLEDMM not used
|
void UsermodManager::handleOverlayDraw() { for (unsigned i = 0; i < numMods; i++) ums[i]->handleOverlayDraw(); }
|
||||||
|
// void UsermodManager::appendConfigData() { for (unsigned i = 0; i < numMods; i++) ums[i]->appendConfigData(); } //WLEDMM not used
|
||||||
bool UsermodManager::handleButton(uint8_t b) {
|
bool UsermodManager::handleButton(uint8_t b) {
|
||||||
bool overrideIO = false;
|
bool overrideIO = false;
|
||||||
for (byte i = 0; i < numMods; i++) {
|
for (unsigned i = 0; i < numMods; i++) {
|
||||||
if (ums[i]->handleButton(b)) overrideIO = true;
|
if (ums[i]->handleButton(b)) overrideIO = true;
|
||||||
}
|
}
|
||||||
return overrideIO;
|
return overrideIO;
|
||||||
}
|
}
|
||||||
bool UsermodManager::getUMData(um_data_t **data, uint8_t mod_id) {
|
bool UsermodManager::getUMData(um_data_t **data, uint8_t mod_id) {
|
||||||
for (byte i = 0; i < numMods; i++) {
|
for (unsigned i = 0; i < numMods; i++) {
|
||||||
if (mod_id > 0 && ums[i]->getId() != mod_id) continue; // only get data form requested usermod if provided
|
if (mod_id > 0 && ums[i]->getId() != mod_id) continue; // only get data form requested usermod if provided
|
||||||
if (ums[i]->getUMData(data)) return true; // if usermod does provide data return immediately (only one usermod can provide data at one time)
|
if (ums[i]->getUMData(data)) return true; // if usermod does provide data return immediately (only one usermod can provide data at one time)
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void UsermodManager::addToJsonState(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToJsonState(obj); }
|
void UsermodManager::addToJsonState(JsonObject& obj) { for (unsigned i = 0; i < numMods; i++) ums[i]->addToJsonState(obj); }
|
||||||
void UsermodManager::addToJsonInfo(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToJsonInfo(obj); }
|
void UsermodManager::addToJsonInfo(JsonObject& obj) { for (unsigned i = 0; i < numMods; i++) ums[i]->addToJsonInfo(obj); }
|
||||||
void UsermodManager::readFromJsonState(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->readFromJsonState(obj); }
|
void UsermodManager::readFromJsonState(JsonObject& obj) { for (unsigned i = 0; i < numMods; i++) ums[i]->readFromJsonState(obj); }
|
||||||
void UsermodManager::addToConfig(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToConfig(obj); }
|
void UsermodManager::addToConfig(JsonObject& obj) { for (unsigned i = 0; i < numMods; i++) ums[i]->addToConfig(obj); }
|
||||||
bool UsermodManager::readFromConfig(JsonObject& obj) {
|
bool UsermodManager::readFromConfig(JsonObject& obj) {
|
||||||
bool allComplete = true;
|
bool allComplete = true;
|
||||||
for (byte i = 0; i < numMods; i++) {
|
for (unsigned i = 0; i < numMods; i++) {
|
||||||
if (!ums[i]->readFromConfig(obj)) allComplete = false;
|
if (!ums[i]->readFromConfig(obj)) allComplete = false;
|
||||||
}
|
}
|
||||||
return allComplete;
|
return allComplete;
|
||||||
}
|
}
|
||||||
void UsermodManager::onMqttConnect(bool sessionPresent) { for (byte i = 0; i < numMods; i++) ums[i]->onMqttConnect(sessionPresent); }
|
void UsermodManager::onMqttConnect(bool sessionPresent) { for (unsigned i = 0; i < numMods; i++) ums[i]->onMqttConnect(sessionPresent); }
|
||||||
bool UsermodManager::onMqttMessage(char* topic, char* payload) {
|
bool UsermodManager::onMqttMessage(char* topic, char* payload) {
|
||||||
for (byte i = 0; i < numMods; i++) if (ums[i]->onMqttMessage(topic, payload)) return true;
|
for (unsigned i = 0; i < numMods; i++) if (ums[i]->onMqttMessage(topic, payload)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void UsermodManager::onUpdateBegin(bool init) { for (byte i = 0; i < numMods; i++) ums[i]->onUpdateBegin(init); } // notify usermods that update is to begin
|
void UsermodManager::onUpdateBegin(bool init) { for (unsigned i = 0; i < numMods; i++) ums[i]->onUpdateBegin(init); } // notify usermods that update is to begin
|
||||||
void UsermodManager::onStateChange(uint8_t mode) { for (byte i = 0; i < numMods; i++) ums[i]->onStateChange(mode); } // notify usermods that WLED state changed
|
void UsermodManager::onStateChange(uint8_t mode) { for (unsigned i = 0; i < numMods; i++) ums[i]->onStateChange(mode); } // notify usermods that WLED state changed
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enables usermods to lookup another Usermod.
|
* Enables usermods to lookup another Usermod.
|
||||||
*/
|
*/
|
||||||
Usermod* UsermodManager::lookup(uint16_t mod_id) {
|
Usermod* UsermodManager::lookup(uint16_t mod_id) {
|
||||||
for (byte i = 0; i < numMods; i++) {
|
for (unsigned i = 0; i < numMods; i++) {
|
||||||
if (ums[i]->getId() == mod_id) {
|
if (ums[i]->getId() == mod_id) {
|
||||||
return ums[i];
|
return ums[i];
|
||||||
}
|
}
|
||||||
@@ -57,7 +58,7 @@ Usermod* UsermodManager::lookup(uint16_t mod_id) {
|
|||||||
//WLEDMM: used by Usermods in xml.cpp
|
//WLEDMM: used by Usermods in xml.cpp
|
||||||
Usermod* UsermodManager::lookupName(const char *mod_name) {
|
Usermod* UsermodManager::lookupName(const char *mod_name) {
|
||||||
//WLEDMM: hack to get the usermod object with the mod_name (better would be to store the usermod name in the class but that requires change to all usermods)
|
//WLEDMM: hack to get the usermod object with the mod_name (better would be to store the usermod name in the class but that requires change to all usermods)
|
||||||
for (byte i = 0; i < numMods; i++) {
|
for (unsigned i = 0; i < numMods; i++) {
|
||||||
// StaticJsonDocument <1024> docx;
|
// StaticJsonDocument <1024> docx;
|
||||||
JsonObject um = doc.createNestedObject("um"); //WLEDMM reuse the global doc variable here
|
JsonObject um = doc.createNestedObject("um"); //WLEDMM reuse the global doc variable here
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
#include "wled_ethernet.h"
|
#include "wled_ethernet.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
|
#endif
|
||||||
#warning WLED-MM GPL-v3. By installing WLED MM you implicitly accept the terms!
|
#warning WLED-MM GPL-v3. By installing WLED MM you implicitly accept the terms!
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET)
|
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET)
|
||||||
@@ -211,6 +213,19 @@ void WLED::loop()
|
|||||||
handlePresets();
|
handlePresets();
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
|
#if defined(_MoonModules_WLED_) && defined(WLEDMM_FASTPATH)
|
||||||
|
#ifdef WLED_DEBUG
|
||||||
|
unsigned long usermod2Millis = millis();
|
||||||
|
#endif
|
||||||
|
usermods.loop2();
|
||||||
|
#ifdef WLED_DEBUG
|
||||||
|
usermod2Millis = millis() - usermod2Millis;
|
||||||
|
avgUsermodMillis += usermod2Millis;
|
||||||
|
if (usermod2Millis > maxUsermodMillis) maxUsermodMillis = usermod2Millis;
|
||||||
|
#endif
|
||||||
|
yield();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
unsigned long stripMillis = millis();
|
unsigned long stripMillis = millis();
|
||||||
#endif
|
#endif
|
||||||
@@ -293,6 +308,7 @@ void WLED::loop()
|
|||||||
delete busConfigs[i]; busConfigs[i] = nullptr;
|
delete busConfigs[i]; busConfigs[i] = nullptr;
|
||||||
}
|
}
|
||||||
strip.finalizeInit();
|
strip.finalizeInit();
|
||||||
|
busses.setBrightness(bri); // fix re-initialised bus' brightness #4005
|
||||||
loadLedmap = true;
|
loadLedmap = true;
|
||||||
if (aligned) strip.makeAutoSegments();
|
if (aligned) strip.makeAutoSegments();
|
||||||
else strip.fixInvalidSegments();
|
else strip.fixInvalidSegments();
|
||||||
@@ -448,6 +464,9 @@ void WLED::setup()
|
|||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
pinMode(hardwareRX, INPUT_PULLDOWN); delay(1); // suppress noise in case RX pin is floating (at low noise energy) - see issue #3128
|
pinMode(hardwareRX, INPUT_PULLDOWN); delay(1); // suppress noise in case RX pin is floating (at low noise energy) - see issue #3128
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WLED_BOOTUPDELAY
|
||||||
|
delay(WLED_BOOTUPDELAY); // delay to let voltage stabilize, helps with boot issues on some setups
|
||||||
|
#endif
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
if (!Serial) delay(1000); // WLEDMM make sure that Serial has initalized
|
if (!Serial) delay(1000); // WLEDMM make sure that Serial has initalized
|
||||||
|
|
||||||
@@ -498,7 +517,10 @@ void WLED::setup()
|
|||||||
#ifdef WLED_RELEASE_NAME
|
#ifdef WLED_RELEASE_NAME
|
||||||
USER_PRINTF(" WLEDMM_%s %s, build %s.\n", versionString, releaseString, TOSTRING(VERSION)); // WLEDMM specific
|
USER_PRINTF(" WLEDMM_%s %s, build %s.\n", versionString, releaseString, TOSTRING(VERSION)); // WLEDMM specific
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
const esp_partition_t *running_partition = esp_ota_get_running_partition();
|
||||||
|
USER_PRINTF("Running from: %s which is %u bytes and type %u subtype %u at address %x\n",running_partition->label,running_partition->size,running_partition->type,running_partition->subtype,running_partition->address);
|
||||||
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
DEBUG_PRINT(F("esp32 "));
|
DEBUG_PRINT(F("esp32 "));
|
||||||
DEBUG_PRINTLN(ESP.getSdkVersion());
|
DEBUG_PRINTLN(ESP.getSdkVersion());
|
||||||
@@ -586,9 +608,11 @@ void WLED::setup()
|
|||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
|
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
|
||||||
//psramInit(); //WLEDMM?? softhack007: not sure if explicit init is really needed ... lets disable it here and see if that works
|
//psramInit(); //WLEDMM?? softhack007: not sure if explicit init is really needed ... lets disable it here and see if that works
|
||||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
// S3: reserve GPIO 33-37 for "octal" PSRAM
|
#if CONFIG_SPIRAM_MODE_OCT && defined(BOARD_HAS_PSRAM)
|
||||||
managed_pin_type pins[] = { {33, true}, {34, true}, {35, true}, {36, true}, {37, true} };
|
// S3: reserve GPIO 33-37 for "octal" PSRAM
|
||||||
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
|
managed_pin_type pins[] = { {33, true}, {34, true}, {35, true}, {36, true}, {37, true} };
|
||||||
|
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
|
||||||
|
#endif
|
||||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
|
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
// S2: reserve GPIO 26-32 for PSRAM (may fail due to isPinOk() but that will also prevent other allocation)
|
// S2: reserve GPIO 26-32 for PSRAM (may fail due to isPinOk() but that will also prevent other allocation)
|
||||||
//managed_pin_type pins[] = { {26, true}, {27, true}, {28, true}, {29, true}, {30, true}, {31, true}, {32, true} };
|
//managed_pin_type pins[] = { {26, true}, {27, true}, {28, true}, {29, true}, {30, true}, {31, true}, {32, true} };
|
||||||
@@ -807,7 +831,11 @@ void WLED::setup()
|
|||||||
USER_PRINTLN(F("\nGPIO\t| Assigned to\t\t| Info"));
|
USER_PRINTLN(F("\nGPIO\t| Assigned to\t\t| Info"));
|
||||||
USER_PRINTLN(F("--------|-----------------------|------------"));
|
USER_PRINTLN(F("--------|-----------------------|------------"));
|
||||||
for(int pinNr = 0; pinNr < WLED_NUM_PINS; pinNr++) { // 49 = highest PIN on ESP32-S3
|
for(int pinNr = 0; pinNr < WLED_NUM_PINS; pinNr++) { // 49 = highest PIN on ESP32-S3
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
|
if((pinManager.isPinOk(pinNr, false)) || (pinNr > 18 && pinNr < 21)) { // softhack007: list USB pins
|
||||||
|
#else
|
||||||
if(pinManager.isPinOk(pinNr, false)) {
|
if(pinManager.isPinOk(pinNr, false)) {
|
||||||
|
#endif
|
||||||
//if ((!pinManager.isPinAllocated(pinNr)) && (pinManager.getPinSpecialText(pinNr).length() == 0)) continue; // un-comment to hide no-name,unused GPIO pins
|
//if ((!pinManager.isPinAllocated(pinNr)) && (pinManager.getPinSpecialText(pinNr).length() == 0)) continue; // un-comment to hide no-name,unused GPIO pins
|
||||||
bool is_inOut = pinManager.isPinOk(pinNr, true);
|
bool is_inOut = pinManager.isPinOk(pinNr, true);
|
||||||
#if 0 // for testing
|
#if 0 // for testing
|
||||||
@@ -849,6 +877,7 @@ void WLED::setup()
|
|||||||
USER_PRINTLN(F("\n"));
|
USER_PRINTLN(F("\n"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
USER_PRINT(F("Free heap ")); USER_PRINTLN(ESP.getFreeHeap());USER_PRINTLN();
|
||||||
USER_PRINTLN(F("WLED initialization done.\n"));
|
USER_PRINTLN(F("WLED initialization done.\n"));
|
||||||
delay(50);
|
delay(50);
|
||||||
// repeat Ada prompt
|
// repeat Ada prompt
|
||||||
@@ -1217,7 +1246,7 @@ void WLED::handleConnection()
|
|||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
// reconnect WiFi to clear stale allocations if heap gets too low
|
// reconnect WiFi to clear stale allocations if heap gets too low
|
||||||
if ((!strip.isUpdating()) && (now - heapTime > 5000)) { // WLEDMM: updated with better logic for small heap available by block, not total. // WLEDMM trying to use a moment when the strip is idle
|
if ((!strip.isUpdating()) && (now - heapTime > 5000)) { // WLEDMM: updated with better logic for small heap available by block, not total. // WLEDMM trying to use a moment when the strip is idle
|
||||||
#if defined(ARDUINO_ARCH_ESP32S2)
|
#if defined(ARDUINO_ARCH_ESP32S2) || defined(WLED_ENABLE_HUB75MATRIX)
|
||||||
uint32_t heap = ESP.getFreeHeap(); // WLEDMM works better on -S2
|
uint32_t heap = ESP.getFreeHeap(); // WLEDMM works better on -S2
|
||||||
#else
|
#else
|
||||||
uint32_t heap = heap_caps_get_largest_free_block(0x1800); // WLEDMM: This is a better metric for free heap.
|
uint32_t heap = heap_caps_get_largest_free_block(0x1800); // WLEDMM: This is a better metric for free heap.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2407171
|
#define VERSION 2409280
|
||||||
|
|
||||||
// WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED.
|
// WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED.
|
||||||
#define _MoonModules_WLED_
|
#define _MoonModules_WLED_
|
||||||
@@ -928,9 +928,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// boot starts here
|
// boot starts here
|
||||||
void setup();
|
void setup() __attribute__((used));
|
||||||
|
|
||||||
void loop();
|
void loop() __attribute__((used));
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
void beginStrip();
|
void beginStrip();
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ void esp_heap_trace_free_hook(void* ptr)
|
|||||||
unsigned long lastMillis = 0; //WLEDMM
|
unsigned long lastMillis = 0; //WLEDMM
|
||||||
unsigned long loopCounter = 0; //WLEDMM
|
unsigned long loopCounter = 0; //WLEDMM
|
||||||
|
|
||||||
|
void setup() __attribute__((used)); // needed for -flto
|
||||||
void setup() {
|
void setup() {
|
||||||
#ifdef WLED_DEBUG_HEAP
|
#ifdef WLED_DEBUG_HEAP
|
||||||
esp_err_t error = heap_caps_register_failed_alloc_callback(heap_caps_alloc_failed_hook);
|
esp_err_t error = heap_caps_register_failed_alloc_callback(heap_caps_alloc_failed_hook);
|
||||||
@@ -68,6 +69,7 @@ void setup() {
|
|||||||
WLED::instance().setup();
|
WLED::instance().setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loop() __attribute__((used)); // needed for -flto
|
||||||
void loop() {
|
void loop() {
|
||||||
//WLEDMM show loops per second
|
//WLEDMM show loops per second
|
||||||
loopCounter++;
|
loopCounter++;
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adalight and TPM2 handler
|
* Adalight and TPM2 handler
|
||||||
@@ -119,6 +122,34 @@ void handleSerial()
|
|||||||
} else if (next == 'v') {
|
} else if (next == 'v') {
|
||||||
Serial.print("WLED"); Serial.write(' '); Serial.println(VERSION);
|
Serial.print("WLED"); Serial.write(' '); Serial.println(VERSION);
|
||||||
|
|
||||||
|
} else if (next == '^') {
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
esp_err_t err;
|
||||||
|
const esp_partition_t *boot_partition = esp_ota_get_boot_partition();
|
||||||
|
const esp_partition_t *running_partition = esp_ota_get_running_partition();
|
||||||
|
USER_PRINTF("Running on %s and we should have booted from %s. This %s\n",running_partition->label,boot_partition->label,(String(running_partition->label) == String(boot_partition->label))?"is what we expect.":"means OTA messed up!");
|
||||||
|
if (String(running_partition->label) == String(boot_partition->label)) {
|
||||||
|
esp_partition_iterator_t new_boot_partition_iterator = NULL;
|
||||||
|
if (boot_partition->subtype == ESP_PARTITION_SUBTYPE_APP_OTA_0) {
|
||||||
|
new_boot_partition_iterator = esp_partition_find(ESP_PARTITION_TYPE_APP,ESP_PARTITION_SUBTYPE_APP_OTA_1,"app1");
|
||||||
|
} else {
|
||||||
|
new_boot_partition_iterator = esp_partition_find(ESP_PARTITION_TYPE_APP,ESP_PARTITION_SUBTYPE_APP_OTA_0,"app0");
|
||||||
|
}
|
||||||
|
const esp_partition_t* new_boot_partition = esp_partition_get(new_boot_partition_iterator);
|
||||||
|
err = esp_ota_set_boot_partition(new_boot_partition);
|
||||||
|
if (err == ESP_OK) {
|
||||||
|
USER_PRINTF("Switching boot partitions from %s to %s in 3 seconds!\n",boot_partition->label,new_boot_partition->label);
|
||||||
|
delay(3000);
|
||||||
|
esp_restart();
|
||||||
|
} else {
|
||||||
|
USER_PRINTF("Looks like the other app partition (%s) is invalid. Ignoring.\n",new_boot_partition->label);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
USER_PRINTF("Looks like the other partion is invalid as we exepected %s but we booted failsafe to %s. Ignoring boot change.\n",boot_partition->label,running_partition->label);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
USER_PRINTLN("Boot partition switching is only available for ESP32 and newer boards.");
|
||||||
|
#endif
|
||||||
} else if (next == 'X') {
|
} else if (next == 'X') {
|
||||||
forceReconnect = true; // WLEDMM - force reconnect via Serial
|
forceReconnect = true; // WLEDMM - force reconnect via Serial
|
||||||
} else if (next == 0xB0) {updateBaudRate( 115200);
|
} else if (next == 0xB0) {updateBaudRate( 115200);
|
||||||
|
|||||||
@@ -10,9 +10,11 @@ static volatile unsigned long wsLastLiveTime = 0; // WLEDMM
|
|||||||
//uint8_t* wsFrameBuffer = nullptr;
|
//uint8_t* wsFrameBuffer = nullptr;
|
||||||
|
|
||||||
#if !defined(ARDUINO_ARCH_ESP32) || defined(WLEDMM_FASTPATH) // WLEDMM
|
#if !defined(ARDUINO_ARCH_ESP32) || defined(WLEDMM_FASTPATH) // WLEDMM
|
||||||
#define WS_LIVE_INTERVAL 120
|
#define WS_LIVE_INTERVAL_MAX 120
|
||||||
|
#define WS_LIVE_INTERVAL_MIN 25
|
||||||
#else
|
#else
|
||||||
#define WS_LIVE_INTERVAL 80
|
#define WS_LIVE_INTERVAL_MAX 80
|
||||||
|
#define WS_LIVE_INTERVAL_MIN 40
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len)
|
void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len)
|
||||||
@@ -215,7 +217,11 @@ static bool sendLiveLedsWs(uint32_t wsClient) // WLEDMM added "static"
|
|||||||
if ((bufSize < 1) || (used < 1)) return(false); // WLEDMM should not happen
|
if ((bufSize < 1) || (used < 1)) return(false); // WLEDMM should not happen
|
||||||
AsyncWebSocketBuffer wsBuf(bufSize);
|
AsyncWebSocketBuffer wsBuf(bufSize);
|
||||||
if (!wsBuf) {
|
if (!wsBuf) {
|
||||||
USER_PRINTLN(F("WS buffer allocation failed."));
|
static unsigned long last_err_time = 0;
|
||||||
|
if (millis() - last_err_time > 300) { // WLEDMM limit to 3 messages per second
|
||||||
|
USER_PRINTF("WS buffer allocation failed (!wsBuf %u bytes).\n", bufSize);
|
||||||
|
last_err_time = millis();
|
||||||
|
}
|
||||||
errorFlag = ERR_LOW_WS_MEM;
|
errorFlag = ERR_LOW_WS_MEM;
|
||||||
return false; //out of memory
|
return false; //out of memory
|
||||||
}
|
}
|
||||||
@@ -247,6 +253,7 @@ static bool sendLiveLedsWs(uint32_t wsClient) // WLEDMM added "static"
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
uint32_t c = restoreColorLossy(strip.getPixelColor(i), stripBrightness); // WLEDMM full bright preview - does _not_ recover ABL reductions
|
uint32_t c = restoreColorLossy(strip.getPixelColor(i), stripBrightness); // WLEDMM full bright preview - does _not_ recover ABL reductions
|
||||||
|
//uint32_t c = strip.getPixelColorRestored(i);
|
||||||
// WLEDMM begin: preview with color gamma correction
|
// WLEDMM begin: preview with color gamma correction
|
||||||
if (gammaCorrectPreview) {
|
if (gammaCorrectPreview) {
|
||||||
uint8_t w = W(c); // not sure why, but it looks better if using "white" without corrections
|
uint8_t w = W(c); // not sure why, but it looks better if using "white" without corrections
|
||||||
@@ -269,7 +276,7 @@ static bool sendLiveLedsWs(uint32_t wsClient) // WLEDMM added "static"
|
|||||||
|
|
||||||
void handleWs()
|
void handleWs()
|
||||||
{
|
{
|
||||||
if ((millis() - wsLastLiveTime) > (unsigned long)(max((strip.getLengthTotal()/20), WS_LIVE_INTERVAL))) //WLEDMM dynamic nr of peek frames per second
|
if ((millis() - wsLastLiveTime) > (unsigned long)(max(WS_LIVE_INTERVAL_MIN, min((strip.getLengthTotal()/80), WS_LIVE_INTERVAL_MAX)))) //WLEDMM dynamic nr of peek frames per second
|
||||||
{
|
{
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
ws.cleanupClients(3);
|
ws.cleanupClients(3);
|
||||||
|
|||||||
Reference in New Issue
Block a user