Porównaj commity

...

95 Commity

Autor SHA1 Wiadomość Data
James Myatt 78f539ba22 Use product name to identify OTA-compatible releases 2024-04-22 21:38:20 +00:00
Blaz Kristan 6f3d7e76c9 Fix for #3919 2024-04-19 22:54:25 +02:00
Frank 57665e8964
audioreactive readme - removed UM_AUDIOREACTIVE_USE_NEW_FFT
The customized library is not needed / supported any more in 0_15.
2024-04-18 12:16:04 +02:00
Blaz Kristan 3e20724058 ArduinoFFT update
shadow variables
2024-04-17 18:52:35 +02:00
Blaž Kristan d126611e87
Merge pull request #3904 from DedeHai/FX_fcn_improvements
added improvements to color scaling and blurring
2024-04-16 17:41:20 +02:00
Blaž Kristan 1b75be5710
Update FX_2Dfcn.cpp
Undo indent
2024-04-16 17:37:48 +02:00
Damian Schneider 084fc2fcd1 bugfix & code formatting, removed color_scale
also replaced scale8_video with 32bit calculation in color_fade for consistency and speed.
2024-04-16 10:43:06 +02:00
Damian Schneider 459156fe57 added improvements to color scaling and blurring
-changes save roughly 600bytes of flash
-made blurring faster by not writing the color and then reading it back but keeping it as a variable: on a C3, FX black hole goes from 55FPS to 71FPS
-added optional parameter to blur (smear) that can be used in combination with SEGMENT.clear(), blurring the frame without dimming the current frame (repeated calls without clearing will result in white). this is useful to blur without 'motion blurring' being added
-scale8 is inlined and repeated calls uses flash, plus it is slower than native 32bit, so I added 'color_scale' function which is native 32bit and scales 32bit colors (RGBW).
2024-04-15 21:20:45 +02:00
Blaz Kristan 94cdd88474 Version bump B3
- fix for #3896
- fix WS2815 current
- conditional AA setPixelColor()
2024-04-13 18:25:25 +02:00
Blaz Kristan 30435e6406 2D compile fix 2024-04-11 20:11:29 +02:00
Blaz Kristan bd1c06a7a7 Changelog update 2024-04-10 20:06:46 +02:00
Blaž Kristan ff3cce0ed2
Merge pull request #3763 from Aircoookie/new-KITT
Effect: modified KITT (Scanner)
2024-04-10 19:40:37 +02:00
Blaz Kristan 38539aac74 Merge branch '0_15' into new-KITT 2024-04-09 16:36:18 +02:00
Blaz Kristan 58e8346209 Fix for #3889 2024-04-09 08:25:07 +02:00
Blaz Kristan ba9ce4adf2 PIO env. PSRAM fix for S3 & S3 with 4M flash
- audioreactive always included for S3 & S2
2024-04-08 16:32:21 +02:00
Blaž Kristan bd60fe5a13
Merge pull request #3798 from DedeHai/ESP32_S3_TouchFix
Esp32 s3 touch fix
2024-04-07 22:24:32 +02:00
Blaž Kristan b72f3baab7
Update set.cpp
Compile fix
2024-04-07 22:21:41 +02:00
Blaž Kristan d1d54ce9c8
Update cfg.cpp
Indentation fix
2024-04-07 22:15:58 +02:00
Blaž Kristan 954f26308b
Update button.cpp
Indentation fix
2024-04-07 22:12:01 +02:00
Blaž Kristan 1cafa0b33f
Merge pull request #3880 from DedeHai/harmonic-random-palette-generator
Added fix for #3870
2024-04-07 22:03:59 +02:00
Damian Schneider 18c17168e1 replaced &0xFFFF with explicit casts 2024-04-07 16:07:37 +02:00
Damian Schneider d3a97f1062 removed detachinterrupt from pin manager, added it to set.cpp instead 2024-04-07 13:49:17 +02:00
Blaž Kristan d18f078b1e
Merge pull request #3887 from gaaat98/0_15
fix for #3884
2024-04-06 16:47:18 +02:00
gaaat98 9ffcde878a
fix for #3884 2024-04-06 15:40:32 +02:00
Blaz Kristan aa970d6ca5 Extend JSON API info object
- add "clock" - CPU clock in MHz
- add "flash" - flash size in MB
Fix for #3879
2024-04-05 19:26:09 +02:00
Damian Schneider 503c68320a Bugfix: millis rollover (fix for #3870)
millis()/1000 rollover after 18h was not handled, truncating to 16bits after division fixes it.
2024-04-05 07:23:28 +02:00
Blaz Kristan a106342439 PICO & WROVER runtime support
return of GPIO16
2024-04-04 23:09:59 +02:00
Blaž Kristan 3b0e6ec65c
Merge pull request #3667 from ccruz09/main
usermod support for Adafruit MAX17048 module
2024-04-04 20:25:14 +02:00
Blaž Kristan 8691ddc081
Merge pull request #3875 from w00000dy/cdata
Update cdata.js to rebuild if package.json changes
2024-04-04 20:21:27 +02:00
Blaz Kristan 24c5935661 Fix for missing firmware build
updated changelog (missing credit)
2024-04-03 18:31:17 +02:00
Woody 78b37b592e
backup & restore package.json in cdata tests 2024-04-02 20:59:31 +02:00
Woody 4db88cf86b
update cdata.js to rebuild if package.json changes 2024-04-02 20:38:56 +02:00
Woody a7e17eabff
add cdata test for package.json & fix a small bug 2024-04-02 20:12:14 +02:00
Blaž Kristan 93d9ce18b2
Merge pull request #3873 from willmmiles/aws-v2.2.1
Update to AsyncWebServer v2.2.1
2024-04-02 07:13:00 +02:00
Will Miles 6f7ac93d84 Update to AsyncWebServer v2.2.1
Fix use-after-free issue and slightly improve code size.  Note that the
version is changed to a hard pin, so future updates can be validated
before getting picked up by new clones, and old version builds
are reproducible.
2024-04-01 11:25:31 -04:00
Carlos Cruz fa5d60ca26
Merge branch '0_15' into main 2024-04-01 11:02:02 -04:00
Blaz Kristan 20ed81cd86 Prefer I2S1 over RMT on ESP32
- remove Audioreactive limitation
2024-03-30 11:02:28 +01:00
Blaž Kristan 6f38874096
Merge pull request #3862 from willmmiles/fix-esp8266-platform-selection
Fix ESP8266 framework version selection
2024-03-29 21:01:21 +01:00
Blaž Kristan b7db5be4df
Merge pull request #3859 from w00000dy/serg
Only create bin.gz files for esp8266
2024-03-29 21:00:43 +01:00
Blaz Kristan 157dbffc59 Changelog update 2024-03-29 18:56:43 +01:00
Blaz Kristan f21ab3588d Individual color channel control for JSON API
- fixes #3860
- debug verbose
- PSRAM detection
2024-03-29 16:43:37 +01:00
Will Miles 2900bda8f9 Select ESP8266 framework version via platform
By explicitly listing an unversioned framework dependency in
'platform_packages', we were overriding the selection via the 'platform'
specification, allowing PlatformIO to select any random version.
Remove this line to allow 'platform' to add the framework dependency
with the expected version.
2024-03-29 09:33:12 -04:00
Blaz Kristan 5f37c19d42 PSRAM fix & CCT IC
- prevent PSRAM use on ESP32 rev.1 without compile fix
- add runtime selection for CCT IC (Athom 15W bulb)
2024-03-28 16:03:06 +01:00
Woody 6f6356e617
fix print output for bin.gz file 2024-03-27 21:34:51 +01:00
Woody 5d152baac0
Do not create release_gz folder 2024-03-27 21:19:03 +01:00
Woody d7739f9764
Revert "Change path for ESP02-binary"
This reverts commit e3271b8082.
2024-03-26 17:41:28 +01:00
Woody d6e73fde50
only create bin.gz files for esp8266 2024-03-26 17:34:01 +01:00
Blaz Kristan fd149b3f46 fileDoc removal (optimisation) 2024-03-26 17:18:52 +01:00
Blaž Kristan d1d45e7166
Merge pull request #3850 from w00000dy/GitHub-Actions
Use npm ci instead of npm install & Remove zlib dependency from package.json
2024-03-25 08:46:40 +01:00
Blaz Kristan 4b19759dd6 Rotary encoder palette count bugfix 2024-03-24 20:34:22 +01:00
Blaz Kristan 47f44680a3 Multi-update
- 0.15.0-b2
- WS2805 support (NeoPixelBus 2.7.9)
- generic PSRAM support (ESP32 rev.1 still needs compile fix)
- BREAKING: default LEDPIN 2 (due to PSRAM)
- PinManager optimisations
2024-03-24 17:37:11 +01:00
Woody 0a344ada97
Add bin.gz binaries for 160mhz builds 2024-03-24 15:23:33 +01:00
Woody 3b98d01f71
Merge branch '0_15' into serg 2024-03-24 14:42:06 +01:00
Woody 23d8000239
Remove accidental space in cdata.js 2024-03-24 14:34:17 +01:00
Woody c32ee40ca0
add node: prefix to Core modules
The node: prefix makes it clear that you’re importing a built-in module, not a user-defined or third-party module. This can help avoid confusion.
2024-03-24 14:19:49 +01:00
Woody 213f45494f
Merge branch '0_15' into GitHub-Actions 2024-03-24 13:38:36 +01:00
Frank 85a51e6c42
Update requirements.txt to solve CI build errors
use latest platformIO package, to avoid build errors due to missing 'scons'

> Tool Manager: Installing platformio/tool-scons @ ~4.40400.0 
> Error: Could not find the package with 'platformio/tool-scons @ ~4.40400.0' requirements for your system 'linux_x86_64' 

> Error: Process completed with exit code 1.
2024-03-24 12:27:32 +01:00
Blaz Kristan ecfdc6f0a8 Bugfixes:
- #3843
- #3844
- network scan on new install
- misc optimization
2024-03-22 20:49:13 +01:00
Woody 1c1c3fd832
Use npm ci instead of npm install 2024-03-21 12:03:35 +01:00
Woody 7bafe995e5
Remove zlib dependency from package.json 2024-03-21 12:00:18 +01:00
Blaž Kristan 3c23672347
Merge pull request #3836 from THATDONFC/0_15
Add SSD1309_64 I2C Support for FLD Usermod
2024-03-21 05:48:42 +01:00
thatdonfc 33fe68d7eb
Revert breaking change 2024-03-20 13:48:15 -07:00
Blaz Kristan b031fa1531 Palette cycling fix.
Updated getPaletteCount() to return count of all available palettes, including custom ones.
2024-03-20 20:12:21 +01:00
Blaž Kristan dab4dc3f41
Merge pull request #3810 from deece/fw1906_0_15
Fw1906 Support (based on 0-15)
2024-03-20 19:57:10 +01:00
Blaž Kristan 78096803ea
Merge branch '0_15' into fw1906_0_15 2024-03-20 19:51:32 +01:00
Blaž Kristan f1987b9544
Merge pull request #3828 from willmmiles/0_15-asyncwebserver-2.2.0-features
ESPAsyncWebServer 2.2.0 + features
2024-03-20 19:50:06 +01:00
Will Miles 8b6bf08a23 serveLiveLeds: Use variable buffer size
Allocate the serialization buffer size at the required length, rather
than always allocating the maximum size.
2024-03-19 23:50:32 -04:00
Will Miles 2640203c88 wled_server: Remove local content type variables
Use the CONTENT_TYPEs exported by AsyncWebServer directly.
2024-03-19 23:46:55 -04:00
thatdonfc 2dafa9644f
Update Readme for Rotary Encoder Usermod
Add example platformio_override.sample.ini
2024-03-19 14:48:51 -07:00
thatdonfc 92ebeddcb0
Update Readme for Four Line Display Usermod 2024-03-19 14:48:04 -07:00
thatdonfc ecee073e08
Fix palette names when palette ID > 58 and not custom 2024-03-19 14:04:24 -07:00
thatdonfc 6d1b9ffad2
Add SSD1309_64 I2C Support to FDL Usermod 2024-03-19 14:04:09 -07:00
Woody 7ee4b54154
optimize output_bins.py 2024-03-19 20:06:09 +01:00
Woody e3271b8082
Change path for ESP02-binary 2024-03-19 18:15:18 +01:00
Woody c6ff45f959
Merge branch '0_15' into serg 2024-03-19 17:49:56 +01:00
Blaz Kristan 7a9eff7f35 Fix. 2024-03-18 20:23:30 +01:00
Will Miles 5f2480c3d9 serveLiveLeds: Use dynamic buffer
There were three problems here:
- AsyncWebServer is going to copy to a heap buffer anyways, so we might
   as well just pass it one it can use
- The buffer size estimate was wrong -- we need 9 bytes per pixel
   ("RRGGBB",), so the buffer could overflow, and it was not
   considering the extra 2D requirements
- On ESP8266, the stack allocation was overflowing the stack, causing
  corruption and crashes.
2024-03-16 12:16:36 -04:00
Will Miles 0593a078c6 handleFileRead: Leverage AWS code
No need to filter or look up content type, just pitch it over the wall.
Also fixes .gz'd content processing.
2024-03-16 12:12:48 -04:00
Will Miles 323c70dcdf Update for new AsyncWebSocketBuffer
Eliminate the extra indirection and allocate shared buffers directly.
2024-03-16 12:12:48 -04:00
Will Miles a1b0f84444 Pass PROGMEM type to server.on()
Rather than relying on the exception handler, indicate the
__FlashStringHelper type so the correct String constructor is
used.
2024-03-16 12:12:48 -04:00
Will Miles df6c271830 Use web server ContentType symbols
These were mostly PROGMEM already, but every little bit helps.
2024-03-16 12:12:48 -04:00
Will Miles 12bf04826a Update ESPAsyncWebServer to v2.2.0 2024-03-16 12:12:48 -04:00
Blaz Kristan 0dcb56eab5 Modify Bus & BusManager to accommodate digital CCT
- additional fix in hasWhite() & setCCT() & hasCCT()
2024-03-16 12:36:05 +01:00
Blaž Kristan 505768db04 Some fixes & implement recommendation from @Aircoookie
https://github.com/Aircoookie/WLED/pull/3298#issuecomment-1651910418
2024-03-13 20:44:34 +11:00
Robert c74db95c14 Add FW1906 support 2024-03-13 20:44:33 +11:00
Robert af3f27feae Move CTT calculation from BusPwm to Bus class.
This enable it to other bus types.
2024-03-13 20:26:58 +11:00
Damian Schneider 0637c1c9d4 bugfixes
-added minimum threshold, had some crashes when setting threshold to zero before
-moved interrupt detach to GPIO deallocation where it belongs
-added check for touchbutton before detaching interrupt
-moved thochThreshold readout up so it gets updated before passing it to the system call
2024-03-10 19:44:27 +01:00
Damian Schneider 0453a5fb3d added interrupt detach to cfg.cpp 2024-03-10 16:54:25 +01:00
Carlos Cruz ab13db73e7
Added files to usermod directory and changes to platform.ini to support Adafruit MAX17048 module. (#2)
Co-authored-by: Azots <78281612+Azots@users.noreply.github.com>
2024-03-09 13:06:30 -05:00
Damian Schneider 509675fe66 added touch interrupt activation to set.cpp for S2/S3 2024-03-09 16:03:01 +01:00
Damian Schneider 5c09ee29db removed notes 2024-03-04 14:42:50 +01:00
Damian Schneider 15526bd6e8 some tuning for touch buttons on S2/S3
now better fits the default threshold value of 32
2024-03-04 14:38:51 +01:00
Damian Schneider c8f48168b4 fixed touch buttons for ESP32 S2 and S3
touch is implemented differently on S2 and S3, these changes make touch buttons work on S2 and S3
2024-03-04 14:38:37 +01:00
Blaz Kristan f2c30ba3f7 Effect: modified KITT (Scanner)
- add delay
- add dual checkmark
- rename Fade rate to Trail (inverse)
- makes Scanner Dual obsolete
2024-02-17 12:58:04 +01:00
Woody 1eaac0072d
Add a separate folder for .gz release files 2024-02-03 00:44:38 +01:00
52 zmienionych plików z 1762 dodań i 1059 usunięć

Wyświetl plik

@ -37,7 +37,7 @@ jobs:
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
cache: 'npm' cache: 'npm'
- run: npm install - run: npm ci
- name: Cache PlatformIO - name: Cache PlatformIO
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
@ -61,7 +61,7 @@ jobs:
name: firmware-${{ matrix.environment }} name: firmware-${{ matrix.environment }}
path: | path: |
build_output/release/*.bin build_output/release/*.bin
build_output/release/*_ESP02.bin.gz build_output/release/*_ESP02*.bin.gz
release: release:
name: Create Release name: Create Release
runs-on: ubuntu-latest runs-on: ubuntu-latest

Wyświetl plik

@ -1,5 +1,51 @@
## WLED changelog ## WLED changelog
#### Build 2404120
- v0.15.0-b3
- fix for #3896 & WS2815 current saving
- conditional compile for AA setPixelColor()
#### Build 2404100
- Internals: #3859, #3862, #3873, #3875
- Prefer I2S1 over RMT on ESP32
- usermod for Adafruit MAX17048 (#3667 by @ccruz09)
- Runtime detection of ESP32 PICO, general PSRAM support
- Extend JSON API "info" object
- add "clock" - CPU clock in MHz
- add "flash" - flash size in MB
- Fix for #3879
- Analog PWM fix for ESP8266 (#3887 by @gaaat98)
- Fix for #3870 (#3880 by @DedeHai)
- ESP32 S3/S2 touch fix (#3798 by @DedeHai)
- PIO env. PSRAM fix for S3 & S3 with 4M flash
- audioreactive always included for S3 & S2
- Fix for #3889
- BREAKING: Effect: modified KITT (Scanner) (#3763)
#### Build 2403280
- Individual color channel control for JSON API (fixes #3860)
- "col":[int|string|object|array, int|string|object|array, int|string|object|array]
int = Kelvin temperature or 0 for black
string = hex representation of [WW]RRGGBB
object = individual channel control {"r":0,"g":127,"b":255,"w":255}, each being optional (valid to send {})
array = direct channel values [r,g,b,w] (w element being optional)
- runtime selection for CCT IC (Athom 15W bulb)
- #3850 (by @w00000dy)
- Rotary encoder palette count bugfix
- bugfixes and optimisations
#### Build 2403240
- v0.15.0-b2
- WS2805 support (RGB + WW + CW, 600kbps)
- Unified PSRAM use
- NeoPixelBus v2.7.9
- Ubiquitous PSRAM mode for all variants of ESP32
- SSD1309_64 I2C Support for FLD Usermod (#3836 by @THATDONFC)
- Palette cycling fix (add support for `{"seg":[{"pal":"X~Y~"}]}` or `{"seg":[{"pal":"X~Yr"}]}`)
- FW1906 Support (#3810 by @deece and @Robert-github-com)
- ESPAsyncWebServer 2.2.0 (#3828 by @willmmiles)
- Bugfixes: #3843, #3844
#### Build 2403190 #### Build 2403190
- limit max PWM frequency (fix incorrect PWM resolution) - limit max PWM frequency (fix incorrect PWM resolution)
- Segment UI bugfix - Segment UI bugfix
@ -52,7 +98,7 @@
#### Build 2309120 till build 2402010 #### Build 2309120 till build 2402010
- WLED version 0.15.0-a0 - WLED version 0.15.0-a0
- Multi-WiFi support. Add up to 3 (or more via cusom compile) WiFis to connect to - Multi-WiFi support. Add up to 3 (or more via cusom compile) WiFis to connect to (with help from @JPZV)
- Temporary AP. Use your WLED in public with temporary AP. - Temporary AP. Use your WLED in public with temporary AP.
- Github CI build system enhancements (#3718 by @WoodyLetsCode) - Github CI build system enhancements (#3718 by @WoodyLetsCode)
- Accessibility: Node list ( #3715 by @WoodyLetsCode) - Accessibility: Node list ( #3715 by @WoodyLetsCode)

567
package-lock.json wygenerowano

Plik diff jest za duży Load Diff

Wyświetl plik

@ -1,6 +1,6 @@
{ {
"name": "wled", "name": "wled",
"version": "0.15.0-b1", "version": "0.15.0-b3",
"description": "Tools for WLED project", "description": "Tools for WLED project",
"main": "tools/cdata.js", "main": "tools/cdata.js",
"directories": { "directories": {
@ -26,7 +26,6 @@
"clean-css": "^5.3.3", "clean-css": "^5.3.3",
"html-minifier-terser": "^7.2.0", "html-minifier-terser": "^7.2.0",
"inliner": "^1.13.1", "inliner": "^1.13.1",
"nodemon": "^3.0.2", "nodemon": "^3.0.2"
"zlib": "^1.0.5"
} }
} }

Wyświetl plik

@ -4,6 +4,7 @@ import shutil
import gzip import gzip
OUTPUT_DIR = "build_output{}".format(os.path.sep) OUTPUT_DIR = "build_output{}".format(os.path.sep)
#OUTPUT_DIR = os.path.join("build_output")
def _get_cpp_define_value(env, define): def _get_cpp_define_value(env, define):
define_list = [item[-1] for item in env["CPPDEFINES"] if item[0] == define] define_list = [item[-1] for item in env["CPPDEFINES"] if item[0] == define]
@ -13,24 +14,24 @@ def _get_cpp_define_value(env, define):
return None return None
def _create_dirs(dirs=["firmware", "map"]): def _create_dirs(dirs=["map", "release", "firmware"]):
# check if output directories exist and create if necessary
if not os.path.isdir(OUTPUT_DIR):
os.mkdir(OUTPUT_DIR)
for d in dirs: for d in dirs:
if not os.path.isdir("{}{}".format(OUTPUT_DIR, d)): os.makedirs(os.path.join(OUTPUT_DIR, d), exist_ok=True)
os.mkdir("{}{}".format(OUTPUT_DIR, d))
def create_release(source): def create_release(source):
release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME") release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME")
if release_name: if release_name:
_create_dirs(["release"])
version = _get_cpp_define_value(env, "WLED_VERSION") version = _get_cpp_define_value(env, "WLED_VERSION")
# get file extension of source file (.bin or .bin.gz) release_file = os.path.join(OUTPUT_DIR, "release", f"WLED_{version}_{release_name}.bin")
ext = source.split(".", 1)[1] release_gz_file = release_file + ".gz"
release_file = "{}release{}WLED_{}_{}.{}".format(OUTPUT_DIR, os.path.sep, version, release_name, ext) print(f"Copying {source} to {release_file}")
shutil.copy(source, release_file) shutil.copy(source, release_file)
bin_gzip(release_file, release_gz_file)
else:
variant = env["PIOENV"]
bin_file = "{}firmware{}{}.bin".format(OUTPUT_DIR, os.path.sep, variant)
print(f"Copying {source} to {bin_file}")
shutil.copy(source, bin_file)
def bin_rename_copy(source, target, env): def bin_rename_copy(source, target, env):
_create_dirs() _create_dirs()
@ -38,38 +39,21 @@ def bin_rename_copy(source, target, env):
# create string with location and file names based on variant # create string with location and file names based on variant
map_file = "{}map{}{}.map".format(OUTPUT_DIR, os.path.sep, variant) map_file = "{}map{}{}.map".format(OUTPUT_DIR, os.path.sep, variant)
bin_file = "{}firmware{}{}.bin".format(OUTPUT_DIR, os.path.sep, variant)
# check if new target files exist and remove if necessary create_release(str(target[0]))
for f in [map_file, bin_file]:
if os.path.isfile(f):
os.remove(f)
# copy firmware.bin to firmware/<variant>.bin
shutil.copy(str(target[0]), bin_file)
create_release(bin_file)
# copy firmware.map to map/<variant>.map # copy firmware.map to map/<variant>.map
if os.path.isfile("firmware.map"): if os.path.isfile("firmware.map"):
shutil.move("firmware.map", map_file) shutil.move("firmware.map", map_file)
def bin_gzip(source, target, env): def bin_gzip(source, target):
_create_dirs() # only create gzip for esp8266
variant = env["PIOENV"] if not env["PIOPLATFORM"] == "espressif8266":
return
# create string with location and file names based on variant
bin_file = "{}firmware{}{}.bin".format(OUTPUT_DIR, os.path.sep, variant) print(f"Creating gzip file {target} from {source}")
gzip_file = "{}firmware{}{}.bin.gz".format(OUTPUT_DIR, os.path.sep, variant) with open(source,"rb") as fp:
with gzip.open(target, "wb", compresslevel = 9) as f:
# check if new target files exist and remove if necessary
if os.path.isfile(gzip_file): os.remove(gzip_file)
# write gzip firmware file
with open(bin_file,"rb") as fp:
with gzip.open(gzip_file, "wb", compresslevel = 9) as f:
shutil.copyfileobj(fp, f) shutil.copyfileobj(fp, f)
create_release(gzip_file) env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", bin_rename_copy)
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [bin_rename_copy, bin_gzip])

Wyświetl plik

@ -10,7 +10,11 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# CI/release binaries # CI/release binaries
default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, nodemcuv2_160, esp8266_2m_160, esp01_1m_full_160, esp32dev, esp32_eth, esp32dev_audioreactive, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB, esp32s3dev_8MB_PSRAM_opi, esp32_wrover default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, nodemcuv2_160, esp8266_2m_160, esp01_1m_full_160, esp32dev, esp32_eth, esp32dev_audioreactive, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB, esp32s3dev_8MB_PSRAM_opi, esp32s3_4M_PSRAM_qspi, esp32_wrover
# Note that the combination of WLED_BRAND_NAME, WLED_PRODUCT_NAME and ESP architecture
# (JSON API info fields: "brand", "product", "arch") must identify OTA-compatible official releases.
# This may be used by third-party tools to automate identifying and applying OTA updates.
src_dir = ./wled00 src_dir = ./wled00
data_dir = ./wled00/data data_dir = ./wled00/data
@ -41,14 +45,13 @@ arduino_core_git = https://github.com/platformio/platform-espressif8266#feature/
platform_wled_default = ${common.arduino_core_3_1_2} platform_wled_default = ${common.arduino_core_3_1_2}
# We use 2.7.4.7 for all, includes PWM flicker fix and Wstring optimization # We use 2.7.4.7 for all, includes PWM flicker fix and Wstring optimization
#platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7 #platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7
platform_packages = platformio/framework-arduinoespressif8266 platform_packages = platformio/toolchain-xtensa @ ~2.100300.220621 #2.40802.200502
platformio/toolchain-xtensa @ ~2.100300.220621 #2.40802.200502
platformio/tool-esptool #@ ~1.413.0 platformio/tool-esptool #@ ~1.413.0
platformio/tool-esptoolpy #@ ~1.30000.0 platformio/tool-esptoolpy #@ ~1.30000.0
## previous platform for 8266, in case of problems with the new one ## previous platform for 8266, in case of problems with the new one
## you'll need makuna/NeoPixelBus@ 2.6.9 for arduino_core_3_2_0, which does not support Ucs890x ## you'll need makuna/NeoPixelBus@ 2.6.9 for arduino_core_3_0_2, which does not support Ucs890x
;; platform_wled_default = ${common.arduino_core_3_2_0} ;; platform_wled_default = ${common.arduino_core_3_0_2}
;; platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7 ;; platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7
;; platformio/toolchain-xtensa @ ~2.40802.200502 ;; platformio/toolchain-xtensa @ ~2.40802.200502
;; platformio/tool-esptool @ ~1.413.0 ;; platformio/tool-esptool @ ~1.413.0
@ -143,8 +146,8 @@ lib_compat_mode = strict
lib_deps = lib_deps =
fastled/FastLED @ 3.6.0 fastled/FastLED @ 3.6.0
IRremoteESP8266 @ 2.8.2 IRremoteESP8266 @ 2.8.2
makuna/NeoPixelBus @ 2.7.5 makuna/NeoPixelBus @ 2.7.9
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ^2.1.0 https://github.com/Aircoookie/ESPAsyncWebServer.git @ 2.2.1
# for I2C interface # for I2C interface
;Wire ;Wire
# ESP-NOW library # ESP-NOW library
@ -164,6 +167,9 @@ lib_deps =
#For ADS1115 sensor uncomment following #For ADS1115 sensor uncomment following
;adafruit/Adafruit BusIO @ 1.13.2 ;adafruit/Adafruit BusIO @ 1.13.2
;adafruit/Adafruit ADS1X15 @ 2.4.0 ;adafruit/Adafruit ADS1X15 @ 2.4.0
#For MAX1704x Lipo Monitor / Fuel Gauge uncomment following
; https://github.com/adafruit/Adafruit_BusIO @ 1.14.5
; https://github.com/adafruit/Adafruit_MAX1704X @ 1.0.2
#For MPU6050 IMU uncomment follwoing #For MPU6050 IMU uncomment follwoing
;electroniccats/MPU6050 @1.0.1 ;electroniccats/MPU6050 @1.0.1
# For -D USERMOD_ANIMARTRIX # For -D USERMOD_ANIMARTRIX
@ -172,7 +178,7 @@ lib_deps =
# SHT85 # SHT85
;robtillaart/SHT85@~0.3.3 ;robtillaart/SHT85@~0.3.3
# Audioreactive usermod # Audioreactive usermod
;kosme/arduinoFFT @ 2.0.0 ;kosme/arduinoFFT @ 2.0.1
extra_scripts = ${scripts_defaults.extra_scripts} extra_scripts = ${scripts_defaults.extra_scripts}
@ -223,7 +229,7 @@ lib_deps =
${env.lib_deps} ${env.lib_deps}
# additional build flags for audioreactive # additional build flags for audioreactive
AR_build_flags = -D USERMOD_AUDIOREACTIVE AR_build_flags = -D USERMOD_AUDIOREACTIVE
AR_lib_deps = kosme/arduinoFFT @ 2.0.0 AR_lib_deps = kosme/arduinoFFT @ 2.0.1
[esp32_idf_V4] [esp32_idf_V4]
;; experimental build environment for ESP32 using ESP-IDF 4.4.x / arduino-esp32 v2.0.5 ;; experimental build environment for ESP32 using ESP-IDF 4.4.x / arduino-esp32 v2.0.5
@ -236,7 +242,6 @@ platform_packages =
build_flags = -g build_flags = -g
-Wshadow=compatible-local ;; emit warning in case a local variable "shadows" another local one -Wshadow=compatible-local ;; emit warning in case a local variable "shadows" another local one
-DARDUINO_ARCH_ESP32 -DESP32 -DARDUINO_ARCH_ESP32 -DESP32
#-DCONFIG_LITTLEFS_FOR_IDF_3_2
-D CONFIG_ASYNC_TCP_USE_WDT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0
-DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3 -DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3
default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
@ -310,14 +315,14 @@ platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages} platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_4m1m} board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 #-DWLED_DISABLE_2D build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D WLED_PRODUCT_NAME=FOSS #-DWLED_DISABLE_2D
lib_deps = ${esp8266.lib_deps} lib_deps = ${esp8266.lib_deps}
monitor_filters = esp8266_exception_decoder monitor_filters = esp8266_exception_decoder
[env:nodemcuv2_160] [env:nodemcuv2_160]
extends = env:nodemcuv2 extends = env:nodemcuv2
board_build.f_cpu = 160000000L board_build.f_cpu = 160000000L
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266_160 #-DWLED_DISABLE_2D build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266_160 -D WLED_PRODUCT_NAME=FOSS_OC #-DWLED_DISABLE_2D
[env:esp8266_2m] [env:esp8266_2m]
board = esp_wroom_02 board = esp_wroom_02
@ -325,13 +330,13 @@ platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages} platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k} board_build.ldscript = ${common.ldscript_2m512k}
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP02 build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP02 -D WLED_PRODUCT_NAME=FOSS
lib_deps = ${esp8266.lib_deps} lib_deps = ${esp8266.lib_deps}
[env:esp8266_2m_160] [env:esp8266_2m_160]
extends = env:esp8266_2m extends = env:esp8266_2m
board_build.f_cpu = 160000000L board_build.f_cpu = 160000000L
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP02_160 build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP02_160 -D WLED_PRODUCT_NAME=FOSS_OC
[env:esp01_1m_full] [env:esp01_1m_full]
board = esp01_1m board = esp01_1m
@ -339,14 +344,14 @@ platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages} platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_1m128k} board_build.ldscript = ${common.ldscript_1m128k}
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01 -D WLED_DISABLE_OTA build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01 -D WLED_PRODUCT_NAME=FOSS -D WLED_DISABLE_OTA
; -D WLED_USE_UNREAL_MATH ;; may cause wrong sunset/sunrise times, but saves 7064 bytes FLASH and 975 bytes RAM ; -D WLED_USE_UNREAL_MATH ;; may cause wrong sunset/sunrise times, but saves 7064 bytes FLASH and 975 bytes RAM
lib_deps = ${esp8266.lib_deps} lib_deps = ${esp8266.lib_deps}
[env:esp01_1m_full_160] [env:esp01_1m_full_160]
extends = env:esp01_1m_full extends = env:esp01_1m_full
board_build.f_cpu = 160000000L board_build.f_cpu = 160000000L
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01_160 -D WLED_DISABLE_OTA build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01_160 -D WLED_PRODUCT_NAME=FOSS_OC -D WLED_DISABLE_OTA
; -D WLED_USE_UNREAL_MATH ;; may cause wrong sunset/sunrise times, but saves 7064 bytes FLASH and 975 bytes RAM ; -D WLED_USE_UNREAL_MATH ;; may cause wrong sunset/sunrise times, but saves 7064 bytes FLASH and 975 bytes RAM
[env:esp32dev] [env:esp32dev]
@ -354,7 +359,7 @@ board = esp32dev
platform = ${esp32.platform} platform = ${esp32.platform}
platform_packages = ${esp32.platform_packages} platform_packages = ${esp32.platform_packages}
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32 #-D WLED_DISABLE_BROWNOUT_DET build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32 -D WLED_PRODUCT_NAME=FOSS #-D WLED_DISABLE_BROWNOUT_DET
lib_deps = ${esp32.lib_deps} lib_deps = ${esp32.lib_deps}
monitor_filters = esp32_exception_decoder monitor_filters = esp32_exception_decoder
board_build.partitions = ${esp32.default_partitions} board_build.partitions = ${esp32.default_partitions}
@ -364,7 +369,7 @@ board = esp32dev
platform = ${esp32.platform} platform = ${esp32.platform}
platform_packages = ${esp32.platform_packages} platform_packages = ${esp32.platform_packages}
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_audioreactive #-D WLED_DISABLE_BROWNOUT_DET build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_audioreactive -D WLED_PRODUCT_NAME=FOSS_AR #-D WLED_DISABLE_BROWNOUT_DET
${esp32.AR_build_flags} ${esp32.AR_build_flags}
lib_deps = ${esp32.lib_deps} lib_deps = ${esp32.lib_deps}
${esp32.AR_lib_deps} ${esp32.AR_lib_deps}
@ -379,7 +384,7 @@ platform = ${esp32.platform}
platform_packages = ${esp32.platform_packages} platform_packages = ${esp32.platform_packages}
upload_speed = 921600 upload_speed = 921600
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet -D WLED_PRODUCT_NAME=FOSS_Eth -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1
-D WLED_DISABLE_ESPNOW ;; ESP-NOW requires wifi, may crash with ethernet only -D WLED_DISABLE_ESPNOW ;; ESP-NOW requires wifi, may crash with ethernet only
lib_deps = ${esp32.lib_deps} lib_deps = ${esp32.lib_deps}
board_build.partitions = ${esp32.default_partitions} board_build.partitions = ${esp32.default_partitions}
@ -389,11 +394,10 @@ platform = ${esp32.platform}
board = ttgo-t7-v14-mini32 board = ttgo-t7-v14-mini32
board_build.f_flash = 80000000L board_build.f_flash = 80000000L
board_build.flash_mode = qio board_build.flash_mode = qio
board_build.partitions = ${esp32.default_partitions} board_build.partitions = tools/WLED_ESP32-wrover_4MB.csv
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_WROVER build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_WROVER -D WLED_PRODUCT_NAME=FOSS_PSRAM
-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue ;; Older ESP32 (rev.<3) need a PSRAM fix (increases static RAM used) https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/external-ram.html
-D WLED_USE_PSRAM
-D LEDPIN=25 -D LEDPIN=25
lib_deps = ${esp32.lib_deps} lib_deps = ${esp32.lib_deps}
@ -404,7 +408,7 @@ platform_packages = ${esp32c3.platform_packages}
framework = arduino framework = arduino
board = esp32-c3-devkitm-1 board = esp32-c3-devkitm-1
board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
build_flags = ${common.build_flags} ${esp32c3.build_flags} -D WLED_RELEASE_NAME=ESP32-C3 build_flags = ${common.build_flags} ${esp32c3.build_flags} -D WLED_RELEASE_NAME=ESP32-C3 -D WLED_PRODUCT_NAME=FOSS
-D WLED_WATCHDOG_TIMEOUT=0 -D WLED_WATCHDOG_TIMEOUT=0
-DLOLIN_WIFI_FIX ; seems to work much better with this -DLOLIN_WIFI_FIX ; seems to work much better with this
-DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB -DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB
@ -420,12 +424,13 @@ platform = ${esp32s3.platform}
platform_packages = ${esp32s3.platform_packages} platform_packages = ${esp32s3.platform_packages}
upload_speed = 921600 ; or 460800 upload_speed = 921600 ; or 460800
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_8MB build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_8MB -D WLED_PRODUCT_NAME=FOSS
-D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0
-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip -D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
;-D ARDUINO_USB_CDC_ON_BOOT=1 ;; -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") ;-D ARDUINO_USB_CDC_ON_BOOT=1 ;; -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
;-D WLED_DEBUG ${esp32.AR_build_flags}
lib_deps = ${esp32s3.lib_deps} lib_deps = ${esp32s3.lib_deps}
${esp32.AR_lib_deps}
board_build.partitions = tools/WLED_ESP32_8MB.csv board_build.partitions = tools/WLED_ESP32_8MB.csv
board_build.f_flash = 80000000L board_build.f_flash = 80000000L
board_build.flash_mode = qio board_build.flash_mode = qio
@ -440,18 +445,39 @@ platform = ${esp32s3.platform}
platform_packages = ${esp32s3.platform_packages} platform_packages = ${esp32s3.platform_packages}
upload_speed = 921600 upload_speed = 921600
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_8MB_PSRAM_opi build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_8MB_PSRAM_opi -D WLED_PRODUCT_NAME=FOSS_PSRAM
-D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0
;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip ;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
; -D WLED_RELEASE_NAME=ESP32-S3_PSRAM -DBOARD_HAS_PSRAM
-D WLED_USE_PSRAM -DBOARD_HAS_PSRAM ; tells WLED that PSRAM shall be used ${esp32.AR_build_flags}
lib_deps = ${esp32s3.lib_deps} lib_deps = ${esp32s3.lib_deps}
${esp32.AR_lib_deps}
board_build.partitions = tools/WLED_ESP32_8MB.csv board_build.partitions = tools/WLED_ESP32_8MB.csv
board_build.f_flash = 80000000L board_build.f_flash = 80000000L
board_build.flash_mode = qio board_build.flash_mode = qio
monitor_filters = esp32_exception_decoder monitor_filters = esp32_exception_decoder
[env:esp32s3_4M_PSRAM_qspi]
;; ESP32-S3, with 4MB FLASH and <= 4MB PSRAM (memory_type: qio_qspi)
board = esp32-s3-devkitc-1 ;; generic dev board; the next line adds PSRAM support
board_build.arduino.memory_type = qio_qspi ;; use with PSRAM: 2MB or 4MB
platform = ${esp32s3.platform}
platform_packages = ${esp32s3.platform_packages}
upload_speed = 921600
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_4M_PSRAM_qspi -D WLED_PRODUCT_NAME=FOSS_PSRAM
-DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
-DBOARD_HAS_PSRAM
-D WLED_WATCHDOG_TIMEOUT=0
${esp32.AR_build_flags}
lib_deps = ${esp32s3.lib_deps}
${esp32.AR_lib_deps}
board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
board_build.f_flash = 80000000L
board_build.flash_mode = qio
monitor_filters = esp32_exception_decoder
[env:lolin_s2_mini] [env:lolin_s2_mini]
platform = ${esp32s2.platform} platform = ${esp32s2.platform}
platform_packages = ${esp32s2.platform_packages} platform_packages = ${esp32s2.platform_packages}
@ -460,13 +486,12 @@ board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
;board_build.flash_mode = qio ;board_build.flash_mode = qio
;board_build.f_flash = 80000000L ;board_build.f_flash = 80000000L
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=ESP32-S2 build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=ESP32-S2 -D WLED_PRODUCT_NAME=FOSS_PSRAM
-DBOARD_HAS_PSRAM
-DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_CDC_ON_BOOT=1
-DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0
-DARDUINO_USB_DFU_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0
-DBOARD_HAS_PSRAM
-DLOLIN_WIFI_FIX ; seems to work much better with this -DLOLIN_WIFI_FIX ; seems to work much better with this
-D WLED_USE_PSRAM
-D WLED_WATCHDOG_TIMEOUT=0 -D WLED_WATCHDOG_TIMEOUT=0
-D CONFIG_ASYNC_TCP_USE_WDT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0
-D LEDPIN=16 -D LEDPIN=16
@ -476,4 +501,6 @@ build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=
-D HW_PIN_DATASPI=11 -D HW_PIN_DATASPI=11
-D HW_PIN_MISOSPI=9 -D HW_PIN_MISOSPI=9
; -D STATUSLED=15 ; -D STATUSLED=15
${esp32.AR_build_flags}
lib_deps = ${esp32s2.lib_deps} lib_deps = ${esp32s2.lib_deps}
${esp32.AR_lib_deps}

Wyświetl plik

@ -155,9 +155,8 @@ build_flags = ${common.build_flags_esp8266}
; set default color order of your led strip ; set default color order of your led strip
; -D DEFAULT_LED_COLOR_ORDER=COL_ORDER_GRB ; -D DEFAULT_LED_COLOR_ORDER=COL_ORDER_GRB
; ;
; use PSRAM if a device (ESP) has one ; use PSRAM on classic ESP32 rev.1 (rev.3 or above has no issues)
; -DBOARD_HAS_PSRAM ; -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue
; -D WLED_USE_PSRAM
; ;
; configure I2C and SPI interface (for various hardware) ; configure I2C and SPI interface (for various hardware)
; -D I2CSDAPIN=33 # initialise interface ; -D I2CSDAPIN=33 # initialise interface

Wyświetl plik

@ -36,7 +36,7 @@ marshmallow==3.19.0
# via platformio # via platformio
packaging==23.1 packaging==23.1
# via marshmallow # via marshmallow
platformio==6.1.6 platformio==6.1.14
# via -r requirements.in # via -r requirements.in
pyelftools==0.29 pyelftools==0.29
# via platformio # via platformio

Wyświetl plik

@ -1,6 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags # Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000, nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000, otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x180000, app0, app, ota_0, 0x10000, 0x1A0000,
app1, app, ota_1, 0x190000,0x180000, app1, app, ota_1, 0x1B0000,0x1A0000,
spiffs, data, spiffs, 0x310000,0xF0000, spiffs, data, spiffs, 0x350000,0xB0000,

1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x5000
3 otadata data ota 0xe000 0x2000
4 app0 app ota_0 0x10000 0x180000 0x1A0000
5 app1 app ota_1 0x190000 0x1B0000 0x180000 0x1A0000
6 spiffs data spiffs 0x310000 0x350000 0xF0000 0xB0000

Wyświetl plik

@ -83,6 +83,7 @@ describe('Script', () => {
// Backup files // Backup files
fs.cpSync("wled00/data", "wled00Backup", { recursive: true }); fs.cpSync("wled00/data", "wled00Backup", { recursive: true });
fs.cpSync("tools/cdata.js", "cdata.bak.js"); fs.cpSync("tools/cdata.js", "cdata.bak.js");
fs.cpSync("package.json", "package.bak.json");
}); });
after(() => { after(() => {
// Restore backup // Restore backup
@ -90,6 +91,8 @@ describe('Script', () => {
fs.renameSync("wled00Backup", "wled00/data"); fs.renameSync("wled00Backup", "wled00/data");
fs.rmSync("tools/cdata.js"); fs.rmSync("tools/cdata.js");
fs.renameSync("cdata.bak.js", "tools/cdata.js"); fs.renameSync("cdata.bak.js", "tools/cdata.js");
fs.rmSync("package.json");
fs.renameSync("package.bak.json", "package.json");
}); });
// delete all html_*.h files // delete all html_*.h files
@ -131,7 +134,7 @@ describe('Script', () => {
// run script cdata.js again and wait for it to finish // run script cdata.js again and wait for it to finish
await execPromise('node tools/cdata.js'); await execPromise('node tools/cdata.js');
checkIfFileWasNewlyCreated(path.join(folderPath, resultFile)); await checkIfFileWasNewlyCreated(path.join(folderPath, resultFile));
} }
describe('should build if', () => { describe('should build if', () => {
@ -182,6 +185,10 @@ describe('Script', () => {
it('cdata.js changes', async () => { it('cdata.js changes', async () => {
await testFileModification('tools/cdata.js', 'html_ui.h'); await testFileModification('tools/cdata.js', 'html_ui.h');
}); });
it('package.json changes', async () => {
await testFileModification('package.json', 'html_ui.h');
});
}); });
describe('should not build if', () => { describe('should not build if', () => {

Wyświetl plik

@ -2,7 +2,7 @@
* Writes compressed C arrays of data files (web interface) * Writes compressed C arrays of data files (web interface)
* How to use it? * How to use it?
* *
* 1) Install Node 11+ and npm * 1) Install Node 20+ and npm
* 2) npm install * 2) npm install
* 3) npm run build * 3) npm run build
* *
@ -15,10 +15,10 @@
* It uses NodeJS packages to inline, minify and GZIP files. See writeHtmlGzipped and writeChunks invocations at the bottom of the page. * It uses NodeJS packages to inline, minify and GZIP files. See writeHtmlGzipped and writeChunks invocations at the bottom of the page.
*/ */
const fs = require("fs"); const fs = require("node:fs");
const path = require("path"); const path = require("path");
const inliner = require("inliner"); const inliner = require("inliner");
const zlib = require("zlib"); const zlib = require("node:zlib");
const CleanCSS = require("clean-css"); const CleanCSS = require("clean-css");
const minifyHtml = require("html-minifier-terser").minify; const minifyHtml = require("html-minifier-terser").minify;
const packageJson = require("../package.json"); const packageJson = require("../package.json");
@ -207,7 +207,7 @@ function isAnyFileInFolderNewerThan(folderPath, time) {
} }
// Check if the web UI is already built // Check if the web UI is already built
function isAlreadyBuilt(folderPath) { function isAlreadyBuilt(webUIPath, packageJsonPath = "package.json") {
let lastBuildTime = Infinity; let lastBuildTime = Infinity;
for (const file of output) { for (const file of output) {
@ -220,7 +220,7 @@ function isAlreadyBuilt(folderPath) {
} }
} }
return !isAnyFileInFolderNewerThan(folderPath, lastBuildTime) && !isFileNewerThan("tools/cdata.js", lastBuildTime); return !isAnyFileInFolderNewerThan(webUIPath, lastBuildTime) && !isFileNewerThan(packageJsonPath, lastBuildTime) && !isFileNewerThan(__filename, lastBuildTime);
} }
// Don't run this script if we're in a test environment // Don't run this script if we're in a test environment

Wyświetl plik

@ -0,0 +1,64 @@
# Adafruit MAX17048 Usermod (LiPo & LiIon Battery Monitor & Fuel Gauge)
This usermod reads information from an Adafruit MAX17048 and outputs the following:
- Battery Voltage
- Battery Level Percentage
## Dependencies
Libraries:
- `Adafruit_BusIO@~1.14.5` (by [adafruit](https://github.com/adafruit/Adafruit_BusIO))
- `Adafruit_MAX1704X@~1.0.2` (by [adafruit](https://github.com/adafruit/Adafruit_MAX1704X))
These must be added under `lib_deps` in your `platform.ini` (or `platform_override.ini`).
Data is published over MQTT - make sure you've enabled the MQTT sync interface.
## Compilation
To enable, compile with `USERMOD_MAX17048` define in the build_flags (e.g. in `platformio.ini` or `platformio_override.ini`) such as in the example below:
```ini
[env:usermod_max17048_d1_mini]
extends = env:d1_mini
build_flags =
${common.build_flags_esp8266}
-D USERMOD_MAX17048
lib_deps =
${esp8266.lib_deps}
https://github.com/adafruit/Adafruit_BusIO @ 1.14.5
https://github.com/adafruit/Adafruit_MAX1704X @ 1.0.2
```
### Configuration Options
The following settings can be set at compile-time but are configurable on the usermod menu (except First Monitor time):
- USERMOD_MAX17048_MIN_MONITOR_INTERVAL (the min number of milliseconds between checks, defaults to 10,000 ms)
- USERMOD_MAX17048_MAX_MONITOR_INTERVAL (the max number of milliseconds between checks, defaults to 10,000 ms)
- USERMOD_MAX17048_FIRST_MONITOR_AT
Additionally, the Usermod Menu allows you to:
- Enable or Disable the usermod
- Enable or Disable Home Assistant Discovery (turn on/off to sent MQTT Discovery entries for Home Assistant)
- Configure SCL/SDA GPIO Pins
## API
The following method is available to interact with the usermod from other code modules:
- `getBatteryVoltageV` read the last battery voltage (in Volt) obtained from the sensor
- `getBatteryPercent` reads the last battery percentage obtained from the sensor
## MQTT
MQTT topics are as follows (`<deviceTopic>` is set in MQTT section of Sync Setup menu):
Measurement type | MQTT topic
--- | ---
Battery Voltage | `<deviceTopic>/batteryVoltage`
Battery Percent | `<deviceTopic>/batteryPercent`
## Authors
Carlos Cruz [@ccruz09](https://github.com/ccruz09)
## Revision History
Jan 2024
- Added Home Assistant Discovery
- Implemented PinManager to register pins
- Added API call for other modules to read battery voltage and percentage
- Added info-screen outputs
- Updated `readme.md`

Wyświetl plik

@ -0,0 +1,281 @@
// force the compiler to show a warning to confirm that this file is included
#warning **** Included USERMOD_MAX17048 V2.0 ****
#pragma once
#include "wled.h"
#include "Adafruit_MAX1704X.h"
// the max interval to check battery level, 10 seconds
#ifndef USERMOD_MAX17048_MAX_MONITOR_INTERVAL
#define USERMOD_MAX17048_MAX_MONITOR_INTERVAL 10000
#endif
// the min interval to check battery level, 500 ms
#ifndef USERMOD_MAX17048_MIN_MONITOR_INTERVAL
#define USERMOD_MAX17048_MIN_MONITOR_INTERVAL 500
#endif
// how many seconds after boot to perform the first check, 10 seconds
#ifndef USERMOD_MAX17048_FIRST_MONITOR_AT
#define USERMOD_MAX17048_FIRST_MONITOR_AT 10000
#endif
/*
* Usermod to display Battery Life using Adafruit's MAX17048 LiPoly/ LiIon Fuel Gauge and Battery Monitor.
*/
class Usermod_MAX17048 : public Usermod {
private:
bool enabled = true;
unsigned long maxReadingInterval = USERMOD_MAX17048_MAX_MONITOR_INTERVAL;
unsigned long minReadingInterval = USERMOD_MAX17048_MIN_MONITOR_INTERVAL;
unsigned long lastCheck = UINT32_MAX - (USERMOD_MAX17048_MAX_MONITOR_INTERVAL - USERMOD_MAX17048_FIRST_MONITOR_AT);
unsigned long lastSend = UINT32_MAX - (USERMOD_MAX17048_MAX_MONITOR_INTERVAL - USERMOD_MAX17048_FIRST_MONITOR_AT);
uint8_t VoltageDecimals = 3; // Number of decimal places in published voltage values
uint8_t PercentDecimals = 1; // Number of decimal places in published percent values
// string that are used multiple time (this will save some flash memory)
static const char _name[];
static const char _enabled[];
static const char _maxReadInterval[];
static const char _minReadInterval[];
static const char _HomeAssistantDiscovery[];
bool monitorFound = false;
bool firstReadComplete = false;
bool initDone = false;
Adafruit_MAX17048 maxLipo;
float lastBattVoltage = -10;
float lastBattPercent = -1;
// MQTT and Home Assistant Variables
bool HomeAssistantDiscovery = false; // Publish Home Assistant Device Information
bool mqttInitialized = false;
void _mqttInitialize()
{
char mqttBatteryVoltageTopic[128];
char mqttBatteryPercentTopic[128];
snprintf_P(mqttBatteryVoltageTopic, 127, PSTR("%s/batteryVoltage"), mqttDeviceTopic);
snprintf_P(mqttBatteryPercentTopic, 127, PSTR("%s/batteryPercent"), mqttDeviceTopic);
if (HomeAssistantDiscovery) {
_createMqttSensor(F("BatteryVoltage"), mqttBatteryVoltageTopic, "voltage", F("V"));
_createMqttSensor(F("BatteryPercent"), mqttBatteryPercentTopic, "battery", F("%"));
}
}
void _createMqttSensor(const String &name, const String &topic, const String &deviceClass, const String &unitOfMeasurement)
{
String t = String(F("homeassistant/sensor/")) + mqttClientID + F("/") + name + F("/config");
StaticJsonDocument<600> doc;
doc[F("name")] = String(serverDescription) + " " + name;
doc[F("state_topic")] = topic;
doc[F("unique_id")] = String(mqttClientID) + name;
if (unitOfMeasurement != "")
doc[F("unit_of_measurement")] = unitOfMeasurement;
if (deviceClass != "")
doc[F("device_class")] = deviceClass;
doc[F("expire_after")] = 1800;
JsonObject device = doc.createNestedObject(F("device")); // attach the sensor to the same device
device[F("name")] = serverDescription;
device[F("identifiers")] = "wled-sensor-" + String(mqttClientID);
device[F("manufacturer")] = F("WLED");
device[F("model")] = F("FOSS");
device[F("sw_version")] = versionString;
String temp;
serializeJson(doc, temp);
DEBUG_PRINTLN(t);
DEBUG_PRINTLN(temp);
mqtt->publish(t.c_str(), 0, true, temp.c_str());
}
void publishMqtt(const char *topic, const char* state) {
#ifndef WLED_DISABLE_MQTT
//Check if MQTT Connected, otherwise it will crash the 8266
if (WLED_MQTT_CONNECTED){
char subuf[128];
snprintf_P(subuf, 127, PSTR("%s/%s"), mqttDeviceTopic, topic);
mqtt->publish(subuf, 0, false, state);
}
#endif
}
public:
inline void enable(bool enable) { enabled = enable; }
inline bool isEnabled() { return enabled; }
void setup() {
// do your set-up here
if (i2c_scl<0 || i2c_sda<0) { enabled = false; return; }
monitorFound = maxLipo.begin();
initDone = true;
}
void loop() {
// if usermod is disabled or called during strip updating just exit
// NOTE: on very long strips strip.isUpdating() may always return true so update accordingly
if (!enabled || strip.isUpdating()) return;
unsigned long now = millis();
if (now - lastCheck < minReadingInterval) { return; }
bool shouldUpdate = now - lastSend > maxReadingInterval;
float battVoltage = maxLipo.cellVoltage();
float battPercent = maxLipo.cellPercent();
lastCheck = millis();
firstReadComplete = true;
if (shouldUpdate)
{
lastBattVoltage = roundf(battVoltage * powf(10, VoltageDecimals)) / powf(10, VoltageDecimals);
lastBattPercent = roundf(battPercent * powf(10, PercentDecimals)) / powf(10, PercentDecimals);
lastSend = millis();
publishMqtt("batteryVoltage", String(lastBattVoltage, VoltageDecimals).c_str());
publishMqtt("batteryPercent", String(lastBattPercent, PercentDecimals).c_str());
DEBUG_PRINTLN(F("Battery Voltage: ") + String(lastBattVoltage, VoltageDecimals) + F("V"));
DEBUG_PRINTLN(F("Battery Percent: ") + String(lastBattPercent, PercentDecimals) + F("%"));
}
}
void onMqttConnect(bool sessionPresent)
{
if (WLED_MQTT_CONNECTED && !mqttInitialized)
{
_mqttInitialize();
mqttInitialized = true;
}
}
inline float getBatteryVoltageV() {
return (float) lastBattVoltage;
}
inline float getBatteryPercent() {
return (float) lastBattPercent;
}
void addToJsonInfo(JsonObject& root)
{
// if "u" object does not exist yet wee need to create it
JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u");
JsonArray battery_json = user.createNestedArray(F("Battery Monitor"));
if (!enabled) {
battery_json.add(F("Disabled"));
}
else if(!monitorFound) {
battery_json.add(F("MAX17048 Not Found"));
}
else if (!firstReadComplete) {
// if we haven't read the sensor yet, let the user know
// that we are still waiting for the first measurement
battery_json.add((USERMOD_MAX17048_FIRST_MONITOR_AT - millis()) / 1000);
battery_json.add(F(" sec until read"));
} else {
battery_json.add(F("Enabled"));
JsonArray voltage_json = user.createNestedArray(F("Battery Voltage"));
voltage_json.add(lastBattVoltage);
voltage_json.add(F("V"));
JsonArray percent_json = user.createNestedArray(F("Battery Percent"));
percent_json.add(lastBattPercent);
percent_json.add(F("%"));
}
}
void addToJsonState(JsonObject& root)
{
JsonObject usermod = root[FPSTR(_name)];
if (usermod.isNull())
{
usermod = root.createNestedObject(FPSTR(_name));
}
usermod[FPSTR(_enabled)] = enabled;
}
void readFromJsonState(JsonObject& root)
{
JsonObject usermod = root[FPSTR(_name)];
if (!usermod.isNull())
{
if (usermod[FPSTR(_enabled)].is<bool>())
{
enabled = usermod[FPSTR(_enabled)].as<bool>();
}
}
}
void addToConfig(JsonObject& root)
{
JsonObject top = root.createNestedObject(FPSTR(_name));
top[FPSTR(_enabled)] = enabled;
top[FPSTR(_maxReadInterval)] = maxReadingInterval;
top[FPSTR(_minReadInterval)] = minReadingInterval;
top[FPSTR(_HomeAssistantDiscovery)] = HomeAssistantDiscovery;
DEBUG_PRINT(F(_name));
DEBUG_PRINTLN(F(" config saved."));
}
bool readFromConfig(JsonObject& root)
{
JsonObject top = root[FPSTR(_name)];
if (top.isNull()) {
DEBUG_PRINT(F(_name));
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
return false;
}
bool configComplete = !top.isNull();
configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled);
configComplete &= getJsonValue(top[FPSTR(_maxReadInterval)], maxReadingInterval, USERMOD_MAX17048_MAX_MONITOR_INTERVAL);
configComplete &= getJsonValue(top[FPSTR(_minReadInterval)], minReadingInterval, USERMOD_MAX17048_MIN_MONITOR_INTERVAL);
configComplete &= getJsonValue(top[FPSTR(_HomeAssistantDiscovery)], HomeAssistantDiscovery, false);
DEBUG_PRINT(FPSTR(_name));
if (!initDone) {
// first run: reading from cfg.json
DEBUG_PRINTLN(F(" config loaded."));
} else {
DEBUG_PRINTLN(F(" config (re)loaded."));
// changing parameters from settings page
}
return configComplete;
}
uint16_t getId()
{
return USERMOD_ID_MAX17048;
}
};
// add more strings here to reduce flash memory usage
const char Usermod_MAX17048::_name[] PROGMEM = "Adafruit MAX17048 Battery Monitor";
const char Usermod_MAX17048::_enabled[] PROGMEM = "enabled";
const char Usermod_MAX17048::_maxReadInterval[] PROGMEM = "max-read-interval-ms";
const char Usermod_MAX17048::_minReadInterval[] PROGMEM = "min-read-interval-ms";
const char Usermod_MAX17048::_HomeAssistantDiscovery[] PROGMEM = "HomeAssistantDiscovery";

Wyświetl plik

@ -27,18 +27,11 @@ Currently ESP8266 is not supported, due to low speed and small RAM of this chip.
There are however plans to create a lightweight audioreactive for the 8266, with reduced features. There are however plans to create a lightweight audioreactive for the 8266, with reduced features.
## Installation ## Installation
### using customised _arduinoFFT_ library for use with this usermod ### using latest _arduinoFFT_ library version 2.x
Add `-D USERMOD_AUDIOREACTIVE` to your PlatformIO environment `build_flags`, as well as `https://github.com/blazoncek/arduinoFFT.git` to your `lib_deps`. The latest arduinoFFT release version should be used for audioreactive.
If you are not using PlatformIO (which you should) try adding `#define USERMOD_AUDIOREACTIVE` to *my_config.h* and make sure you have _arduinoFFT_ library downloaded and installed.
Customised _arduinoFFT_ library for use with this usermod can be found at https://github.com/blazoncek/arduinoFFT.git * `build_flags` = `-D USERMOD_AUDIOREACTIVE`
* `lib_deps`= `kosme/arduinoFFT @ 2.0.1`
### using latest (develop) _arduinoFFT_ library
Alternatively, you can use the latest arduinoFFT development version.
ArduinoFFT `develop` library is slightly more accurate, and slightly faster than our customised library, however also needs additional 2kB RAM.
* `build_flags` = `-D USERMOD_AUDIOREACTIVE` `-D UM_AUDIOREACTIVE_USE_NEW_FFT`
* `lib_deps`= `https://github.com/kosme/arduinoFFT#develop @ 1.9.2`
## Configuration ## Configuration

Wyświetl plik

@ -667,7 +667,7 @@ void MultiRelay::addToJsonInfo(JsonObject &root) {
for (int i=0; i<MULTI_RELAY_MAX_RELAYS; i++) { for (int i=0; i<MULTI_RELAY_MAX_RELAYS; i++) {
if (_relay[i].pin<0 || !_relay[i].external) continue; if (_relay[i].pin<0 || !_relay[i].external) continue;
uiDomString = F("Relay "); uiDomString += i; uiDomString = F("Relay "); uiDomString += i;
JsonArray infoArr = user.createNestedArray(uiDomString); // timer value infoArr = user.createNestedArray(uiDomString); // timer value
uiDomString = F("<button class=\"btn btn-xs\" onclick=\"requestJson({"); uiDomString = F("<button class=\"btn btn-xs\" onclick=\"requestJson({");
uiDomString += FPSTR(_name); uiDomString += FPSTR(_name);

Wyświetl plik

@ -1,4 +1,4 @@
# I2C 4 Line Display Usermod ALT # I2C/SPI 4 Line Display Usermod ALT
Thank you to the authors of the original version of these usermods. It would not have been possible without them! Thank you to the authors of the original version of these usermods. It would not have been possible without them!
"usermod_v2_four_line_display" "usermod_v2_four_line_display"
@ -8,21 +8,20 @@ The core of these usermods are a copy of the originals. The main changes are to
The display usermod UI has been completely changed. The display usermod UI has been completely changed.
The changes made to the RotaryEncoder usermod were made to support the new UI in the display usermod. The changes made to the RotaryEncoder usermod were made to support the new UI in the display usermod.
Without the display it, functions identical to the original. Without the display, it functions identical to the original.
The original "usermod_v2_auto_save" will not work with the display just yet. The original "usermod_v2_auto_save" will not work with the display just yet.
Press the encoder to cycle through the options: Press the encoder to cycle through the options:
*Brightness * Brightness
*Speed * Speed
*Intensity * Intensity
*Palette * Palette
*Effect * Effect
*Main Color (only if display is used) * Main Color (only if display is used)
*Saturation (only if display is used) * Saturation (only if display is used)
Press and hold the encoder to display Network Info Press and hold the encoder to display Network Info. If AP is active, it will display AP, SSID and password
if AP is active, it will display AP, SSID and password
Also shows if the timer is enabled Also shows if the timer is enabled
@ -30,11 +29,47 @@ Also shows if the timer is enabled
## Installation ## Installation
Please refer to the original `usermod_v2_rotary_encoder_ui` readme for the main instructions Please refer to the original `usermod_v2_rotary_encoder_ui` readme for the main instructions.
Then to activate this alternative usermod add `#define USE_ALT_DISPlAY` to the `usermods_list.cpp` file,
Copy the example `platformio_override.sample.ini` from the usermod_v2_rotary_encoder_ui_ALT folder to the root directory of your particular build and rename it to `platformio_override.ini`.
This file should be placed in the same directory as `platformio.ini`.
Then, to activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE SENSITIVE) to the `usermods_list.cpp` file,
or add `-D USE_ALT_DISPlAY` to the original `platformio_override.ini.sample` file or add `-D USE_ALT_DISPlAY` to the original `platformio_override.ini.sample` file
## Configuration
These options are configurable in Config > Usermods
### Usermod Setup
* Global I2C GPIOs (HW) - Set the SDA and SCL pins
### 4LineDisplay
* `enabled` - enable/disable usermod
* `type` - display type in numeric format
* 1 = I2C SSD1306 128x32
* 2 = I2C SH1106 128x32
* 3 = I2C SSD1306 128x64 (4 double-height lines)
* 4 = I2C SSD1305 128x32
* 5 = I2C SSD1305 128x64 (4 double-height lines)
* 6 = SPI SSD1306 128x32
* 7 = SPI SSD1306 128x64 (4 double-height lines)
* 8 = SPI SSD1309 128x64 (4 double-height lines)
* 9 = I2C SSD1309 128x64 (4 double-height lines)
* `pin` - GPIO pins used for display; SPI displays can use SCK, MOSI, CS, DC & RST
* `flip` - flip/rotate display 180°
* `contrast` - set display contrast (higher contrast may reduce display lifetime)
* `screenTimeOutSec` - screen saver time-out in seconds
* `sleepMode` - enable/disable screen saver
* `clockMode` - enable/disable clock display in screen saver mode
* `showSeconds` - Show seconds on the clock display
* `i2c-freq-kHz` - I2C clock frequency in kHz (may help reduce dropped frames, range: 400-3400)
### PlatformIO requirements ### PlatformIO requirements
Note: the Four Line Display usermod requires the libraries `U8g2` and `Wire`. Note: the Four Line Display usermod requires the libraries `U8g2` and `Wire`.

Wyświetl plik

@ -17,7 +17,7 @@
// for WLED. // for WLED.
// //
// Dependencies // Dependencies
// * This Usermod works best, by far, when coupled // * This Usermod works best, by far, when coupled
// with RotaryEncoderUI ALT Usermod. // with RotaryEncoderUI ALT Usermod.
// //
// Make sure to enable NTP and set your time zone in WLED Config | Time. // Make sure to enable NTP and set your time zone in WLED Config | Time.
@ -89,7 +89,8 @@ typedef enum {
SSD1305_64, // U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C SSD1305_64, // U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C
SSD1306_SPI, // U8X8_SSD1306_128X32_NONAME_HW_SPI SSD1306_SPI, // U8X8_SSD1306_128X32_NONAME_HW_SPI
SSD1306_SPI64, // U8X8_SSD1306_128X64_NONAME_HW_SPI SSD1306_SPI64, // U8X8_SSD1306_128X64_NONAME_HW_SPI
SSD1309_SPI64 // U8X8_SSD1309_128X64_NONAME0_4W_HW_SPI SSD1309_SPI64, // U8X8_SSD1309_128X64_NONAME0_4W_HW_SPI
SSD1309_64 // U8X8_SSD1309_128X64_NONAME0_HW_I2C
} DisplayType; } DisplayType;
@ -235,7 +236,7 @@ class FourLineDisplayUsermod : public Usermod {
void updateSpeed(); void updateSpeed();
void updateIntensity(); void updateIntensity();
void drawStatusIcons(); void drawStatusIcons();
/** /**
* marks the position of the arrow showing * marks the position of the arrow showing
* the current setting being changed * the current setting being changed
@ -246,8 +247,8 @@ class FourLineDisplayUsermod : public Usermod {
//Draw the arrow for the current setting being changed //Draw the arrow for the current setting being changed
void drawArrow(); void drawArrow();
//Display the current effect or palette (desiredEntry) //Display the current effect or palette (desiredEntry)
// on the appropriate line (row). // on the appropriate line (row).
void showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row); void showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row);
/** /**
@ -314,14 +315,14 @@ class FourLineDisplayUsermod : public Usermod {
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object. * addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
* It will be called by WLED when settings are actually saved (for example, LED settings are saved) * It will be called by WLED when settings are actually saved (for example, LED settings are saved)
* If you want to force saving the current state, use serializeConfig() in your loop(). * If you want to force saving the current state, use serializeConfig() in your loop().
* *
* CAUTION: serializeConfig() will initiate a filesystem write operation. * CAUTION: serializeConfig() will initiate a filesystem write operation.
* It might cause the LEDs to stutter and will cause flash wear if called too often. * It might cause the LEDs to stutter and will cause flash wear if called too often.
* Use it sparingly and always in the loop, never in network callbacks! * Use it sparingly and always in the loop, never in network callbacks!
* *
* addToConfig() will also not yet add your setting to one of the settings pages automatically. * addToConfig() will also not yet add your setting to one of the settings pages automatically.
* To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually. * To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually.
* *
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings! * I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/ */
void addToConfig(JsonObject& root) override; void addToConfig(JsonObject& root) override;
@ -329,7 +330,7 @@ class FourLineDisplayUsermod : public Usermod {
/* /*
* readFromConfig() can be used to read back the custom settings you added with addToConfig(). * readFromConfig() can be used to read back the custom settings you added with addToConfig().
* This is called by WLED when settings are loaded (currently this only happens once immediately after boot) * This is called by WLED when settings are loaded (currently this only happens once immediately after boot)
* *
* readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes), * readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes),
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup. * but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :) * If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
@ -494,7 +495,7 @@ void FourLineDisplayUsermod::showTime() {
} }
if (knownHour != hourCurrent) { if (knownHour != hourCurrent) {
// only update date when hour changes // only update date when hour changes
sprintf_P(lineBuffer, PSTR("%s %2d "), monthShortStr(month(localTime)), day(localTime)); sprintf_P(lineBuffer, PSTR("%s %2d "), monthShortStr(month(localTime)), day(localTime));
draw2x2String(2, lineHeight==1 ? 0 : lineHeight, lineBuffer); // adjust for 8 line displays, draw month and day draw2x2String(2, lineHeight==1 ? 0 : lineHeight, lineBuffer); // adjust for 8 line displays, draw month and day
} }
sprintf_P(lineBuffer,PSTR("%2d:%02d"), (useAMPM ? AmPmHour : hourCurrent), minuteCurrent); sprintf_P(lineBuffer,PSTR("%2d:%02d"), (useAMPM ? AmPmHour : hourCurrent), minuteCurrent);
@ -556,6 +557,7 @@ void FourLineDisplayUsermod::setup() {
case SSD1306_64: u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_HW_I2C(); break; case SSD1306_64: u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_HW_I2C(); break;
case SSD1305: u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C(); break; case SSD1305: u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C(); break;
case SSD1305_64: u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C(); break; case SSD1305_64: u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C(); break;
case SSD1309_64: u8x8 = (U8X8 *) new U8X8_SSD1309_128X64_NONAME0_HW_I2C(); break;
// U8X8 uses global SPI variable that is attached to VSPI bus on ESP32 // U8X8 uses global SPI variable that is attached to VSPI bus on ESP32
case SSD1306_SPI: u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_HW_SPI(ioPin[0], ioPin[1], ioPin[2]); break; // Pins are cs, dc, reset case SSD1306_SPI: u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_HW_SPI(ioPin[0], ioPin[1], ioPin[2]); break; // Pins are cs, dc, reset
case SSD1306_SPI64: u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_HW_SPI(ioPin[0], ioPin[1], ioPin[2]); break; // Pins are cs, dc, reset case SSD1306_SPI64: u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_HW_SPI(ioPin[0], ioPin[1], ioPin[2]); break; // Pins are cs, dc, reset
@ -581,7 +583,7 @@ void FourLineDisplayUsermod::setup() {
// gets called every time WiFi is (re-)connected. Initialize own network // gets called every time WiFi is (re-)connected. Initialize own network
// interfaces here // interfaces here
void FourLineDisplayUsermod::connected() { void FourLineDisplayUsermod::connected() {
knownSsid = WiFi.SSID(); //apActive ? apSSID : WiFi.SSID(); //apActive ? WiFi.softAPSSID() : knownSsid = WiFi.SSID(); //apActive ? apSSID : WiFi.SSID(); //apActive ? WiFi.softAPSSID() :
knownIp = Network.localIP(); //apActive ? IPAddress(4, 3, 2, 1) : Network.localIP(); knownIp = Network.localIP(); //apActive ? IPAddress(4, 3, 2, 1) : Network.localIP();
networkOverlay(PSTR("NETWORK INFO"),7000); networkOverlay(PSTR("NETWORK INFO"),7000);
} }
@ -637,7 +639,7 @@ void FourLineDisplayUsermod::redraw(bool forceRedraw) {
powerON = !powerON; powerON = !powerON;
drawStatusIcons(); drawStatusIcons();
return; return;
} else if (knownnightlight != nightlightActive) { //trigger moon icon } else if (knownnightlight != nightlightActive) { //trigger moon icon
knownnightlight = nightlightActive; knownnightlight = nightlightActive;
drawStatusIcons(); drawStatusIcons();
if (knownnightlight) { if (knownnightlight) {
@ -652,7 +654,7 @@ void FourLineDisplayUsermod::redraw(bool forceRedraw) {
return; return;
} else if (knownMode != effectCurrent || knownPalette != effectPalette) { } else if (knownMode != effectCurrent || knownPalette != effectPalette) {
if (displayTurnedOff) needRedraw = true; if (displayTurnedOff) needRedraw = true;
else { else {
if (knownPalette != effectPalette) { showCurrentEffectOrPalette(effectPalette, JSON_palette_names, 2); knownPalette = effectPalette; } if (knownPalette != effectPalette) { showCurrentEffectOrPalette(effectPalette, JSON_palette_names, 2); knownPalette = effectPalette; }
if (knownMode != effectCurrent) { showCurrentEffectOrPalette(effectCurrent, JSON_mode_names, 3); knownMode = effectCurrent; } if (knownMode != effectCurrent) { showCurrentEffectOrPalette(effectCurrent, JSON_mode_names, 3); knownMode = effectCurrent; }
lastRedraw = now; lastRedraw = now;
@ -703,7 +705,7 @@ void FourLineDisplayUsermod::redraw(bool forceRedraw) {
drawArrow(); drawArrow();
drawStatusIcons(); drawStatusIcons();
// Second row // Second row
updateBrightness(); updateBrightness();
updateSpeed(); updateSpeed();
updateIntensity(); updateIntensity();
@ -805,8 +807,8 @@ void FourLineDisplayUsermod::drawArrow() {
lockRedraw = false; lockRedraw = false;
} }
//Display the current effect or palette (desiredEntry) //Display the current effect or palette (desiredEntry)
// on the appropriate line (row). // on the appropriate line (row).
void FourLineDisplayUsermod::showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row) { void FourLineDisplayUsermod::showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row) {
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS) #if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
unsigned long now = millis(); unsigned long now = millis();
@ -857,7 +859,7 @@ void FourLineDisplayUsermod::showCurrentEffectOrPalette(int inputEffPal, const c
while (smallChars1 < (MAX_MODE_LINE_SPACE-1)) smallBuffer1[smallChars1++]=' '; while (smallChars1 < (MAX_MODE_LINE_SPACE-1)) smallBuffer1[smallChars1++]=' ';
smallBuffer1[smallChars1] = 0; smallBuffer1[smallChars1] = 0;
drawString(1, row*lineHeight, smallBuffer1, true); drawString(1, row*lineHeight, smallBuffer1, true);
while (smallChars2 < (MAX_MODE_LINE_SPACE-1)) smallBuffer2[smallChars2++]=' '; while (smallChars2 < (MAX_MODE_LINE_SPACE-1)) smallBuffer2[smallChars2++]=' ';
smallBuffer2[smallChars2] = 0; smallBuffer2[smallChars2] = 0;
drawString(1, row*lineHeight+1, smallBuffer2, true); drawString(1, row*lineHeight+1, smallBuffer2, true);
} }
@ -1150,7 +1152,7 @@ void FourLineDisplayUsermod::onUpdateBegin(bool init) {
xTaskCreatePinnedToCore( xTaskCreatePinnedToCore(
[](void * par) { // Function to implement the task [](void * par) { // Function to implement the task
// see https://www.freertos.org/vtaskdelayuntil.html // see https://www.freertos.org/vtaskdelayuntil.html
const TickType_t xFrequency = REFRESH_RATE_MS * portTICK_PERIOD_MS / 2; const TickType_t xFrequency = REFRESH_RATE_MS * portTICK_PERIOD_MS / 2;
TickType_t xLastWakeTime = xTaskGetTickCount(); TickType_t xLastWakeTime = xTaskGetTickCount();
for(;;) { for(;;) {
delay(1); // DO NOT DELETE THIS LINE! It is needed to give the IDLE(0) task enough time and to keep the watchdog happy. delay(1); // DO NOT DELETE THIS LINE! It is needed to give the IDLE(0) task enough time and to keep the watchdog happy.
@ -1205,6 +1207,7 @@ void FourLineDisplayUsermod::appendConfigData() {
oappend(SET_F("addOption(dd,'SSD1306 128x64',3);")); oappend(SET_F("addOption(dd,'SSD1306 128x64',3);"));
oappend(SET_F("addOption(dd,'SSD1305',4);")); oappend(SET_F("addOption(dd,'SSD1305',4);"));
oappend(SET_F("addOption(dd,'SSD1305 128x64',5);")); oappend(SET_F("addOption(dd,'SSD1305 128x64',5);"));
oappend(SET_F("addOption(dd,'SSD1309 128x64',9);"));
oappend(SET_F("addOption(dd,'SSD1306 SPI',6);")); oappend(SET_F("addOption(dd,'SSD1306 SPI',6);"));
oappend(SET_F("addOption(dd,'SSD1306 SPI 128x64',7);")); oappend(SET_F("addOption(dd,'SSD1306 SPI 128x64',7);"));
oappend(SET_F("addOption(dd,'SSD1309 SPI 128x64',8);")); oappend(SET_F("addOption(dd,'SSD1309 SPI 128x64',8);"));
@ -1218,14 +1221,14 @@ void FourLineDisplayUsermod::appendConfigData() {
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object. * addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
* It will be called by WLED when settings are actually saved (for example, LED settings are saved) * It will be called by WLED when settings are actually saved (for example, LED settings are saved)
* If you want to force saving the current state, use serializeConfig() in your loop(). * If you want to force saving the current state, use serializeConfig() in your loop().
* *
* CAUTION: serializeConfig() will initiate a filesystem write operation. * CAUTION: serializeConfig() will initiate a filesystem write operation.
* It might cause the LEDs to stutter and will cause flash wear if called too often. * It might cause the LEDs to stutter and will cause flash wear if called too often.
* Use it sparingly and always in the loop, never in network callbacks! * Use it sparingly and always in the loop, never in network callbacks!
* *
* addToConfig() will also not yet add your setting to one of the settings pages automatically. * addToConfig() will also not yet add your setting to one of the settings pages automatically.
* To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually. * To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually.
* *
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings! * I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/ */
void FourLineDisplayUsermod::addToConfig(JsonObject& root) { void FourLineDisplayUsermod::addToConfig(JsonObject& root) {
@ -1252,7 +1255,7 @@ void FourLineDisplayUsermod::addToConfig(JsonObject& root) {
/* /*
* readFromConfig() can be used to read back the custom settings you added with addToConfig(). * readFromConfig() can be used to read back the custom settings you added with addToConfig().
* This is called by WLED when settings are loaded (currently this only happens once immediately after boot) * This is called by WLED when settings are loaded (currently this only happens once immediately after boot)
* *
* readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes), * readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes),
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup. * but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :) * If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
@ -1346,6 +1349,10 @@ bool FourLineDisplayUsermod::readFromConfig(JsonObject& root) {
u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1305_128x64_adafruit, u8x8_cad_ssd13xx_fast_i2c, u8x8_byte_arduino_hw_i2c, u8x8_gpio_and_delay_arduino); u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1305_128x64_adafruit, u8x8_cad_ssd13xx_fast_i2c, u8x8_byte_arduino_hw_i2c, u8x8_gpio_and_delay_arduino);
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE); u8x8_SetPin_HW_I2C(u8x8->getU8x8(), U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE);
break; break;
case SSD1309_64:
u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1309_128x64_noname0, u8x8_cad_ssd13xx_fast_i2c, u8x8_byte_arduino_hw_i2c, u8x8_gpio_and_delay_arduino);
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE);
break;
case SSD1306_SPI: case SSD1306_SPI:
u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1306_128x32_univision, u8x8_cad_001, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay_arduino); u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1306_128x32_univision, u8x8_cad_001, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay_arduino);
u8x8_SetPin_4Wire_HW_SPI(u8x8->getU8x8(), ioPin[0], ioPin[1], ioPin[2]); // Pins are cs, dc, reset u8x8_SetPin_4Wire_HW_SPI(u8x8->getU8x8(), ioPin[0], ioPin[1], ioPin[2]); // Pins are cs, dc, reset

Wyświetl plik

@ -0,0 +1,17 @@
[platformio]
default_envs = esp32dev
[env:esp32dev]
board = esp32dev
platform = ${esp32.platform}
build_unflags = ${common.build_unflags}
build_flags =
${common.build_flags_esp32}
-D USERMOD_FOUR_LINE_DISPLAY -D USE_ALT_DISPlAY
-D USERMOD_ROTARY_ENCODER_UI -D ENCODER_DT_PIN=18 -D ENCODER_CLK_PIN=5 -D ENCODER_SW_PIN=19
upload_speed = 460800
lib_deps =
${esp32.lib_deps}
U8g2@~2.34.4
Wire

Wyświetl plik

@ -8,18 +8,18 @@ The core of these usermods are a copy of the originals. The main changes are to
The display usermod UI has been completely changed. The display usermod UI has been completely changed.
The changes made to the RotaryEncoder usermod were made to support the new UI in the display usermod. The changes made to the RotaryEncoder usermod were made to support the new UI in the display usermod.
Without the display, it functions identical to the original. Without the display, it functions identical to the original.
The original "usermod_v2_auto_save" will not work with the display just yet. The original "usermod_v2_auto_save" will not work with the display just yet.
Press the encoder to cycle through the options: Press the encoder to cycle through the options:
*Brightness * Brightness
*Speed * Speed
*Intensity * Intensity
*Palette * Palette
*Effect * Effect
*Main Color (only if display is used) * Main Color (only if display is used)
*Saturation (only if display is used) * Saturation (only if display is used)
Press and hold the encoder to display Network Info Press and hold the encoder to display Network Info
if AP is active, it will display the AP, SSID and Password if AP is active, it will display the AP, SSID and Password
@ -30,10 +30,23 @@ Also shows if the timer is enabled.
## Installation ## Installation
Please refer to the original `usermod_v2_rotary_encoder_ui` readme for the main instructions.<br/> Copy the example `platformio_override.sample.ini` to the root directory of your particular build and rename it to `platformio_override.ini`.
To activate this alternative usermod, add `#define USE_ALT_DISPlAY` to the `usermods_list.cpp` file,
or add `-D USE_ALT_DISPlAY` to the original `platformio_override.ini.sample` file.
To activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE SENSITIVE) to the `usermods_list.cpp` file, or add `-D USE_ALT_DISPlAY` to your `platformio_override.ini` file
### Define Your Options
* `USERMOD_ROTARY_ENCODER_UI` - define this to have this user mod included wled00\usermods_list.cpp
* `USERMOD_FOUR_LINE_DISPLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp
also tells this usermod that the display is available
(see the Four Line Display usermod `readme.md` for more details)
* `USE_ALT_DISPlAY` - Mandatory to use Four Line Display
* `ENCODER_DT_PIN` - defaults to 18
* `ENCODER_CLK_PIN` - defaults to 5
* `ENCODER_SW_PIN` - defaults to 19
* `USERMOD_ROTARY_ENCODER_GPIO` - GPIO functionality:
`INPUT_PULLUP` to use internal pull-up
`INPUT` to use pull-up on the PCB
### PlatformIO requirements ### PlatformIO requirements

Wyświetl plik

@ -392,26 +392,26 @@ byte RotaryEncoderUIUsermod::readPin(uint8_t pin) {
* modes_alpha_indexes and palettes_alpha_indexes. * modes_alpha_indexes and palettes_alpha_indexes.
*/ */
void RotaryEncoderUIUsermod::sortModesAndPalettes() { void RotaryEncoderUIUsermod::sortModesAndPalettes() {
DEBUG_PRINTLN(F("Sorting modes and palettes.")); DEBUG_PRINT(F("Sorting modes: ")); DEBUG_PRINTLN(strip.getModeCount());
//modes_qstrings = re_findModeStrings(JSON_mode_names, strip.getModeCount()); //modes_qstrings = re_findModeStrings(JSON_mode_names, strip.getModeCount());
modes_qstrings = strip.getModeDataSrc(); modes_qstrings = strip.getModeDataSrc();
modes_alpha_indexes = re_initIndexArray(strip.getModeCount()); modes_alpha_indexes = re_initIndexArray(strip.getModeCount());
re_sortModes(modes_qstrings, modes_alpha_indexes, strip.getModeCount(), MODE_SORT_SKIP_COUNT); re_sortModes(modes_qstrings, modes_alpha_indexes, strip.getModeCount(), MODE_SORT_SKIP_COUNT);
palettes_qstrings = re_findModeStrings(JSON_palette_names, strip.getPaletteCount()+strip.customPalettes.size()); DEBUG_PRINT(F("Sorting palettes: ")); DEBUG_PRINT(strip.getPaletteCount()); DEBUG_PRINT('/'); DEBUG_PRINTLN(strip.customPalettes.size());
palettes_alpha_indexes = re_initIndexArray(strip.getPaletteCount()+strip.customPalettes.size()); palettes_qstrings = re_findModeStrings(JSON_palette_names, strip.getPaletteCount());
palettes_alpha_indexes = re_initIndexArray(strip.getPaletteCount());
if (strip.customPalettes.size()) { if (strip.customPalettes.size()) {
for (int i=0; i<strip.customPalettes.size(); i++) { for (int i=0; i<strip.customPalettes.size(); i++) {
palettes_alpha_indexes[strip.getPaletteCount()+i] = 255-i; palettes_alpha_indexes[strip.getPaletteCount()-strip.customPalettes.size()+i] = 255-i;
palettes_qstrings[strip.getPaletteCount()+i] = PSTR("~Custom~"); palettes_qstrings[strip.getPaletteCount()-strip.customPalettes.size()+i] = PSTR("~Custom~");
} }
} }
// How many palette names start with '*' and should not be sorted? // How many palette names start with '*' and should not be sorted?
// (Also skipping the first one, 'Default'). // (Also skipping the first one, 'Default').
int skipPaletteCount = 1; int skipPaletteCount = 1;
while (pgm_read_byte_near(palettes_qstrings[skipPaletteCount++]) == '*') ; while (pgm_read_byte_near(palettes_qstrings[skipPaletteCount]) == '*') skipPaletteCount++;
re_sortModes(palettes_qstrings, palettes_alpha_indexes, strip.getPaletteCount(), skipPaletteCount); re_sortModes(palettes_qstrings, palettes_alpha_indexes, strip.getPaletteCount()-strip.customPalettes.size(), skipPaletteCount);
} }
byte *RotaryEncoderUIUsermod::re_initIndexArray(int numModes) { byte *RotaryEncoderUIUsermod::re_initIndexArray(int numModes) {

Wyświetl plik

@ -1125,57 +1125,62 @@ uint16_t mode_running_random(void) {
static const char _data_FX_MODE_RUNNING_RANDOM[] PROGMEM = "Stream@!,Zone size;;!"; static const char _data_FX_MODE_RUNNING_RANDOM[] PROGMEM = "Stream@!,Zone size;;!";
uint16_t larson_scanner(bool dual) {
if (SEGLEN == 1) return mode_static();
uint16_t counter = strip.now * ((SEGMENT.speed >> 2) +8);
uint16_t index = (counter * SEGLEN) >> 16;
SEGMENT.fade_out(SEGMENT.intensity);
if (SEGENV.step > index && SEGENV.step - index > SEGLEN/2) {
SEGENV.aux0 = !SEGENV.aux0;
}
for (int i = SEGENV.step; i < index; i++) {
uint16_t j = (SEGENV.aux0)?i:SEGLEN-1-i;
SEGMENT.setPixelColor( j, SEGMENT.color_from_palette(j, true, PALETTE_SOLID_WRAP, 0));
}
if (dual) {
uint32_t c;
if (SEGCOLOR(2) != 0) {
c = SEGCOLOR(2);
} else {
c = SEGMENT.color_from_palette(index, true, PALETTE_SOLID_WRAP, 0);
}
for (int i = SEGENV.step; i < index; i++) {
uint16_t j = (SEGENV.aux0)?SEGLEN-1-i:i;
SEGMENT.setPixelColor(j, c);
}
}
SEGENV.step = index;
return FRAMETIME;
}
/* /*
* K.I.T.T. * K.I.T.T.
*/ */
uint16_t mode_larson_scanner(void){ uint16_t mode_larson_scanner(void){
return larson_scanner(false); if (SEGLEN == 1) return mode_static();
}
static const char _data_FX_MODE_LARSON_SCANNER[] PROGMEM = "Scanner@!,Fade rate;!,!;!;;m12=0";
const unsigned speed = FRAMETIME * map(SEGMENT.speed, 0, 255, 96, 2); // map into useful range
const unsigned pixels = SEGLEN / speed; // how many pixels to advance per frame
SEGMENT.fade_out(255-SEGMENT.intensity);
if (SEGENV.step > strip.now) return FRAMETIME; // we have a pause
unsigned index = SEGENV.aux1 + pixels;
// are we slow enough to use frames per pixel?
if (pixels == 0) {
const unsigned frames = speed / SEGLEN; // how many frames per 1 pixel
if (SEGENV.step++ < frames) return FRAMETIME;
SEGENV.step = 0;
index++;
}
if (index > SEGLEN) {
SEGENV.aux0 = !SEGENV.aux0; // change direction
SEGENV.aux1 = 0; // reset position
// set delay
if (SEGENV.aux0 || SEGMENT.check2) SEGENV.step = strip.now + SEGMENT.custom1 * 25; // multiply by 25ms
else SEGENV.step = 0;
} else {
// paint as many pixels as needed
for (unsigned i = SEGENV.aux1; i < index; i++) {
unsigned j = (SEGENV.aux0) ? i : SEGLEN - 1 - i;
uint32_t c = SEGMENT.color_from_palette(j, true, PALETTE_SOLID_WRAP, 0);
SEGMENT.setPixelColor(j, c);
if (SEGMENT.check1) {
SEGMENT.setPixelColor(SEGLEN - 1 - j, SEGCOLOR(2) ? SEGCOLOR(2) : c);
}
}
SEGENV.aux1 = index;
}
return FRAMETIME;
}
static const char _data_FX_MODE_LARSON_SCANNER[] PROGMEM = "Scanner@!,Trail,Delay,,,Dual,Bi-delay;!,!,!;!;;m12=0,c1=0";
/* /*
* Creates two Larson scanners moving in opposite directions * Creates two Larson scanners moving in opposite directions
* Custom mode by Keith Lord: https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/DualLarson.h * Custom mode by Keith Lord: https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/DualLarson.h
*/ */
uint16_t mode_dual_larson_scanner(void){ uint16_t mode_dual_larson_scanner(void){
return larson_scanner(true); SEGMENT.check1 = true;
return mode_larson_scanner();
} }
static const char _data_FX_MODE_DUAL_LARSON_SCANNER[] PROGMEM = "Scanner Dual@!,Fade rate;!,!,!;!;;m12=0"; static const char _data_FX_MODE_DUAL_LARSON_SCANNER[] PROGMEM = "Scanner Dual@!,Trail,Delay,,,Dual,Bi-delay;!,!,!;!;;m12=0,c1=0";
/* /*
@ -3013,8 +3018,12 @@ uint16_t mode_bouncing_balls(void) {
} }
int pos = roundf(balls[i].height * (SEGLEN - 1)); int pos = roundf(balls[i].height * (SEGLEN - 1));
#ifdef WLED_USE_AA_PIXELS
if (SEGLEN<32) SEGMENT.setPixelColor(indexToVStrip(pos, stripNr), color); // encode virtual strip into index if (SEGLEN<32) SEGMENT.setPixelColor(indexToVStrip(pos, stripNr), color); // encode virtual strip into index
else SEGMENT.setPixelColor(balls[i].height + (stripNr+1)*10.0f, color); else SEGMENT.setPixelColor(balls[i].height + (stripNr+1)*10.0f, color);
#else
SEGMENT.setPixelColor(indexToVStrip(pos, stripNr), color); // encode virtual strip into index
#endif
} }
} }
}; };
@ -6047,8 +6056,8 @@ uint16_t mode_2Dfloatingblobs(void) {
} }
} }
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.fill_circle(blob->x[i], blob->y[i], roundf(blob->r[i]), c); if (blob->r[i] > 1.f) SEGMENT.fill_circle(roundf(blob->x[i]), roundf(blob->y[i]), roundf(blob->r[i]), c);
else SEGMENT.setPixelColorXY(blob->x[i], 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));
else if (blob->x[i] - blob->r[i] <= 0) blob->x[i] += (blob->sX[i] * (blob->x[i] / blob->r[i] + 0.005f)); else if (blob->x[i] - blob->r[i] <= 0) blob->x[i] += (blob->sX[i] * (blob->x[i] / blob->r[i] + 0.005f));

Wyświetl plik

@ -59,13 +59,12 @@
/* Not used in all effects yet */ /* Not used in all effects yet */
#define WLED_FPS 42 #define WLED_FPS 42
#define FRAMETIME_FIXED (1000/WLED_FPS) #define FRAMETIME_FIXED (1000/WLED_FPS)
//#define FRAMETIME _frametime
#define FRAMETIME strip.getFrameTime() #define FRAMETIME strip.getFrameTime()
/* each segment uses 82 bytes of SRAM memory, so if you're application fails because of /* each segment uses 82 bytes of SRAM memory, so if you're application fails because of
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
#ifdef ESP8266 #ifdef ESP8266
#define MAX_NUM_SEGMENTS 12 #define MAX_NUM_SEGMENTS 16
/* How much data bytes all segments combined may allocate */ /* How much data bytes all segments combined may allocate */
#define MAX_SEGMENT_DATA 5120 #define MAX_SEGMENT_DATA 5120
#else #else
@ -73,11 +72,7 @@
#define MAX_NUM_SEGMENTS 32 #define MAX_NUM_SEGMENTS 32
#endif #endif
#if defined(ARDUINO_ARCH_ESP32S2) #if defined(ARDUINO_ARCH_ESP32S2)
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM) #define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*768 // 24k by default (S2 is short on free RAM)
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*1024 // 32k by default
#else
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*768 // 24k by default
#endif
#else #else
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*1280 // 40k by default #define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*1280 // 40k by default
#endif #endif
@ -187,7 +182,7 @@
#define FX_MODE_LIGHTNING 57 #define FX_MODE_LIGHTNING 57
#define FX_MODE_ICU 58 #define FX_MODE_ICU 58
#define FX_MODE_MULTI_COMET 59 #define FX_MODE_MULTI_COMET 59
#define FX_MODE_DUAL_LARSON_SCANNER 60 #define FX_MODE_DUAL_LARSON_SCANNER 60 // candidate for removal (use Scanner with with check 1)
#define FX_MODE_RANDOM_CHASE 61 #define FX_MODE_RANDOM_CHASE 61
#define FX_MODE_OSCILLATE 62 #define FX_MODE_OSCILLATE 62
#define FX_MODE_PRIDE_2015 63 #define FX_MODE_PRIDE_2015 63
@ -580,12 +575,14 @@ typedef struct Segment {
inline void setPixelColor(unsigned n, uint32_t c) { setPixelColor(int(n), c); } inline void setPixelColor(unsigned n, uint32_t c) { setPixelColor(int(n), c); }
inline void setPixelColor(int n, byte r, byte g, byte b, byte w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); } inline void setPixelColor(int n, byte r, byte g, byte b, byte w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); }
inline void setPixelColor(int n, CRGB c) { setPixelColor(n, RGBW32(c.r,c.g,c.b,0)); } inline void setPixelColor(int n, CRGB c) { setPixelColor(n, RGBW32(c.r,c.g,c.b,0)); }
#ifdef WLED_USE_AA_PIXELS
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); }
#endif
uint32_t getPixelColor(int i); uint32_t getPixelColor(int i);
// 1D support functions (some implement 2D as well) // 1D support functions (some implement 2D as well)
void blur(uint8_t); void blur(uint8_t, bool smear = false);
void fill(uint32_t c); void fill(uint32_t c);
void fade_out(uint8_t r); void fade_out(uint8_t r);
void fadeToBlackBy(uint8_t fadeBy); void fadeToBlackBy(uint8_t fadeBy);
@ -608,10 +605,12 @@ typedef struct Segment {
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)); }
#ifdef WLED_USE_AA_PIXELS
void setPixelColorXY(float x, float y, uint32_t c, bool aa = true); void setPixelColorXY(float x, float y, uint32_t c, bool aa = true);
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); }
uint32_t getPixelColorXY(uint16_t x, uint16_t y); #endif
uint32_t getPixelColorXY(int x, int y);
// 2D support functions // 2D support functions
inline void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend) { setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend)); } inline void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend) { setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, 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); }
@ -620,8 +619,8 @@ typedef struct Segment {
inline void addPixelColorXY(int x, int y, CRGB c, bool fast = false) { addPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), fast); } inline void addPixelColorXY(int x, int y, CRGB c, bool fast = false) { addPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), fast); }
inline void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { setPixelColorXY(x, y, color_fade(getPixelColorXY(x,y), fade, true)); } inline void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { setPixelColorXY(x, y, color_fade(getPixelColorXY(x,y), fade, true)); }
void box_blur(uint16_t i, bool vertical, fract8 blur_amount); // 1D box blur (with weight) void box_blur(uint16_t i, bool vertical, fract8 blur_amount); // 1D box blur (with weight)
void blurRow(uint16_t row, fract8 blur_amount); void blurRow(uint32_t row, fract8 blur_amount, bool smear = false);
void blurCol(uint16_t col, fract8 blur_amount); void blurCol(uint32_t col, fract8 blur_amount, bool smear = false);
void moveX(int8_t delta, bool wrap = false); void moveX(int8_t delta, bool wrap = false);
void moveY(int8_t delta, bool wrap = false); void moveY(int8_t delta, bool wrap = false);
void move(uint8_t dir, uint8_t delta, bool wrap = false); void move(uint8_t dir, uint8_t delta, bool wrap = false);
@ -640,11 +639,14 @@ typedef struct Segment {
#else #else
inline uint16_t XY(uint16_t x, uint16_t y) { return x; } inline uint16_t XY(uint16_t x, uint16_t y) { return x; }
inline void setPixelColorXY(int x, int y, uint32_t c) { setPixelColor(x, c); } inline void setPixelColorXY(int x, int y, uint32_t c) { setPixelColor(x, c); }
inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColor(int(x), c); }
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColor(x, RGBW32(r,g,b,w)); } inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColor(x, RGBW32(r,g,b,w)); }
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColor(x, RGBW32(c.r,c.g,c.b,0)); } inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColor(x, RGBW32(c.r,c.g,c.b,0)); }
#ifdef WLED_USE_AA_PIXELS
inline void setPixelColorXY(float x, float y, uint32_t c, bool aa = true) { setPixelColor(x, c, aa); } inline void setPixelColorXY(float x, float y, uint32_t c, bool aa = true) { setPixelColor(x, c, aa); }
inline void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColor(x, 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) { setPixelColor(x, RGBW32(r,g,b,w), aa); }
inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColor(x, RGBW32(c.r,c.g,c.b,0), aa); } inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColor(x, RGBW32(c.r,c.g,c.b,0), aa); }
#endif
inline uint32_t getPixelColorXY(uint16_t x, uint16_t y) { return getPixelColor(x); } inline uint32_t getPixelColorXY(uint16_t x, uint16_t y) { return getPixelColor(x); }
inline void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t c, uint8_t blend) { blendPixelColor(x, c, blend); } inline void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t c, uint8_t blend) { blendPixelColor(x, c, blend); }
inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColor(x, RGBW32(c.r,c.g,c.b,0), blend); } inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColor(x, RGBW32(c.r,c.g,c.b,0), blend); }
@ -653,8 +655,8 @@ typedef struct Segment {
inline void addPixelColorXY(int x, int y, CRGB c, bool fast = false) { addPixelColor(x, RGBW32(c.r,c.g,c.b,0), fast); } inline void addPixelColorXY(int x, int y, CRGB c, bool fast = false) { addPixelColor(x, RGBW32(c.r,c.g,c.b,0), fast); }
inline void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { fadePixelColor(x, fade); } inline void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { fadePixelColor(x, fade); }
inline void box_blur(uint16_t i, bool vertical, fract8 blur_amount) {} inline void box_blur(uint16_t i, bool vertical, fract8 blur_amount) {}
inline void blurRow(uint16_t row, fract8 blur_amount) {} inline void blurRow(uint32_t row, fract8 blur_amount, bool smear = false) {}
inline void blurCol(uint16_t col, fract8 blur_amount) {} inline void blurCol(uint32_t col, fract8 blur_amount, bool smear = false) {}
inline void moveX(int8_t delta, bool wrap = false) {} inline void moveX(int8_t delta, bool wrap = false) {}
inline void moveY(int8_t delta, bool wrap = false) {} inline void moveY(int8_t delta, bool wrap = false) {}
inline void move(uint8_t dir, uint8_t delta, bool wrap = false) {} inline void move(uint8_t dir, uint8_t delta, bool wrap = false) {}
@ -810,7 +812,7 @@ class WS2812FX { // 96 bytes
inline uint8_t getSegmentsNum(void) { return _segments.size(); } // returns currently present segments inline uint8_t getSegmentsNum(void) { return _segments.size(); } // returns currently present segments
inline uint8_t getCurrSegmentId(void) { return _segment_index; } // returns current segment index (only valid while strip.isServicing()) inline uint8_t getCurrSegmentId(void) { return _segment_index; } // returns current segment index (only valid while strip.isServicing())
inline uint8_t getMainSegmentId(void) { return _mainSegment; } // returns main segment index inline uint8_t getMainSegmentId(void) { return _mainSegment; } // returns main segment index
inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT + customPalettes.size(); }
inline uint8_t getTargetFps() { return _targetFps; } // returns rough FPS value for las 2s interval inline uint8_t getTargetFps() { return _targetFps; } // returns rough FPS value for las 2s interval
inline uint8_t getModeCount() { return _modeCount; } // returns number of registered modes/effects inline uint8_t getModeCount() { return _modeCount; } // returns number of registered modes/effects

Wyświetl plik

@ -65,9 +65,10 @@ void WS2812FX::setUpMatrix() {
customMappingSize = 0; // prevent use of mapping if anything goes wrong customMappingSize = 0; // prevent use of mapping if anything goes wrong
if (customMappingTable == nullptr) customMappingTable = new uint16_t[getLengthTotal()]; if (customMappingTable) delete[] customMappingTable;
customMappingTable = new uint16_t[getLengthTotal()];
if (customMappingTable != nullptr) { if (customMappingTable) {
customMappingSize = getLengthTotal(); customMappingSize = getLengthTotal();
// fill with empty in case we don't fill the entire matrix // fill with empty in case we don't fill the entire matrix
@ -138,7 +139,7 @@ void WS2812FX::setUpMatrix() {
DEBUG_PRINTLN(); DEBUG_PRINTLN();
#endif #endif
} else { // memory allocation error } else { // memory allocation error
DEBUG_PRINTLN(F("Ledmap alloc error.")); DEBUG_PRINTLN(F("ERROR 2D LED map allocation error."));
isMatrix = false; isMatrix = false;
panels = 0; panels = 0;
panel.clear(); panel.clear();
@ -174,11 +175,7 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
uint8_t _bri_t = currentBri(); uint8_t _bri_t = currentBri();
if (_bri_t < 255) { if (_bri_t < 255) {
byte r = scale8(R(col), _bri_t); col = color_fade(col, _bri_t);
byte g = scale8(G(col), _bri_t);
byte b = scale8(B(col), _bri_t);
byte w = scale8(W(col), _bri_t);
col = RGBW32(r, g, b, w);
} }
if (reverse ) x = virtualWidth() - x - 1; if (reverse ) x = virtualWidth() - x - 1;
@ -217,6 +214,7 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
} }
} }
#ifdef WLED_USE_AA_PIXELS
// anti-aliased version of setPixelColorXY() // anti-aliased version of setPixelColorXY()
void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa) void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
{ {
@ -260,9 +258,10 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
setPixelColorXY(uint16_t(roundf(fX)), uint16_t(roundf(fY)), col); setPixelColorXY(uint16_t(roundf(fX)), uint16_t(roundf(fY)), col);
} }
} }
#endif
// returns RGBW values of pixel // returns RGBW values of pixel
uint32_t IRAM_ATTR Segment::getPixelColorXY(uint16_t x, uint16_t y) { uint32_t IRAM_ATTR Segment::getPixelColorXY(int x, int y) {
if (!isActive()) return 0; // not active if (!isActive()) return 0; // not active
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit
if (reverse ) x = virtualWidth() - x - 1; if (reverse ) x = virtualWidth() - x - 1;
@ -275,59 +274,71 @@ uint32_t IRAM_ATTR Segment::getPixelColorXY(uint16_t x, uint16_t y) {
} }
// blurRow: perform a blur on a row of a rectangular matrix // blurRow: perform a blur on a row of a rectangular matrix
void Segment::blurRow(uint16_t row, fract8 blur_amount) { void Segment::blurRow(uint32_t row, fract8 blur_amount, bool smear){
if (!isActive() || blur_amount == 0) return; // not active if (!isActive() || blur_amount == 0) return; // not active
const uint_fast16_t cols = virtualWidth(); const uint_fast16_t cols = virtualWidth();
const uint_fast16_t rows = virtualHeight(); const uint_fast16_t rows = virtualHeight();
if (row >= rows) return; if (row >= rows) return;
// blur one row // blur one row
uint8_t keep = 255 - blur_amount; uint8_t keep = smear ? 255 : 255 - blur_amount;
uint8_t seep = blur_amount >> 1; uint8_t seep = blur_amount >> 1;
CRGB carryover = CRGB::Black; uint32_t carryover = BLACK;
uint32_t lastnew;
uint32_t last;
uint32_t curnew;
for (unsigned x = 0; x < cols; x++) { for (unsigned x = 0; x < cols; x++) {
CRGB cur = getPixelColorXY(x, row); uint32_t cur = getPixelColorXY(x, row);
CRGB before = cur; // remember color before blur uint32_t part = color_fade(cur, seep);
CRGB part = cur; curnew = color_fade(cur, keep);
part.nscale8(seep); if (x > 0) {
cur.nscale8(keep); if (carryover)
cur += carryover; curnew = color_add(curnew, carryover, true);
if (x>0) { uint32_t prev = color_add(lastnew, part, true);
CRGB prev = CRGB(getPixelColorXY(x-1, row)) + part; if (last != prev) // optimization: only set pixel if color has changed
setPixelColorXY(x-1, row, prev); setPixelColorXY(x - 1, row, prev);
} }
if (before != cur) // optimization: only set pixel if color has changed else // first pixel
setPixelColorXY(x, row, cur); setPixelColorXY(x, row, curnew);
lastnew = curnew;
last = cur; // save original value for comparison on next iteration
carryover = part; carryover = part;
} }
setPixelColorXY(cols-1, row, curnew); // set last pixel
} }
// blurCol: perform a blur on a column of a rectangular matrix // blurCol: perform a blur on a column of a rectangular matrix
void Segment::blurCol(uint16_t col, fract8 blur_amount) { void Segment::blurCol(uint32_t col, fract8 blur_amount, bool smear) {
if (!isActive() || blur_amount == 0) return; // not active if (!isActive() || blur_amount == 0) return; // not active
const uint_fast16_t cols = virtualWidth(); const uint_fast16_t cols = virtualWidth();
const uint_fast16_t rows = virtualHeight(); const uint_fast16_t rows = virtualHeight();
if (col >= cols) return; if (col >= cols) return;
// blur one column // blur one column
uint8_t keep = 255 - blur_amount; uint8_t keep = smear ? 255 : 255 - blur_amount;
uint8_t seep = blur_amount >> 1; uint8_t seep = blur_amount >> 1;
CRGB carryover = CRGB::Black; uint32_t carryover = BLACK;
uint32_t lastnew;
uint32_t last;
uint32_t curnew;
for (unsigned y = 0; y < rows; y++) { for (unsigned y = 0; y < rows; y++) {
CRGB cur = getPixelColorXY(col, y); uint32_t cur = getPixelColorXY(col, y);
CRGB part = cur; uint32_t part = color_fade(cur, seep);
CRGB before = cur; // remember color before blur curnew = color_fade(cur, keep);
part.nscale8(seep); if (y > 0) {
cur.nscale8(keep); if (carryover)
cur += carryover; curnew = color_add(curnew, carryover, true);
if (y>0) { uint32_t prev = color_add(lastnew, part, true);
CRGB prev = CRGB(getPixelColorXY(col, y-1)) + part; if (last != prev) // optimization: only set pixel if color has changed
setPixelColorXY(col, y-1, prev); setPixelColorXY(col, y - 1, prev);
} }
if (before != cur) // optimization: only set pixel if color has changed else // first pixel
setPixelColorXY(col, y, cur); setPixelColorXY(col, y, curnew);
carryover = part; lastnew = curnew;
last = cur; //save original value for comparison on next iteration
carryover = part;
} }
setPixelColorXY(col, rows - 1, curnew);
} }
// 1D Box blur (with added weight - blur_amount: [0=no blur, 255=max blur]) // 1D Box blur (with added weight - blur_amount: [0=no blur, 255=max blur])

Wyświetl plik

@ -455,18 +455,18 @@ CRGBPalette16 IRAM_ATTR &Segment::currentPalette(CRGBPalette16 &targetPalette, u
// relies on WS2812FX::service() to call it for each frame // relies on WS2812FX::service() to call it for each frame
void Segment::handleRandomPalette() { void Segment::handleRandomPalette() {
// is it time to generate a new palette? // is it time to generate a new palette?
if ((millis()/1000U) - _lastPaletteChange > randomPaletteChangeTime) { if ((uint16_t)((uint16_t)(millis() / 1000U) - _lastPaletteChange) > randomPaletteChangeTime){
_newRandomPalette = useHarmonicRandomPalette ? generateHarmonicRandomPalette(_randomPalette) : generateRandomPalette(); _newRandomPalette = useHarmonicRandomPalette ? generateHarmonicRandomPalette(_randomPalette) : generateRandomPalette();
_lastPaletteChange = millis()/1000U; _lastPaletteChange = (uint16_t)(millis() / 1000U);
_lastPaletteBlend = (uint16_t)(millis() & 0xFFFF)-512; // starts blending immediately _lastPaletteBlend = (uint16_t)((uint16_t)millis() - 512); // starts blending immediately
} }
// if palette transitions is enabled, blend it according to Transition Time (if longer than minimum given by service calls) // if palette transitions is enabled, blend it according to Transition Time (if longer than minimum given by service calls)
if (strip.paletteFade) { if (strip.paletteFade) {
// assumes that 128 updates are sufficient to blend a palette, so shift by 7 (can be more, can be less) // assumes that 128 updates are sufficient to blend a palette, so shift by 7 (can be more, can be less)
// in reality there need to be 255 blends to fully blend two entirely different palettes // in reality there need to be 255 blends to fully blend two entirely different palettes
if ((millis() & 0xFFFF) - _lastPaletteBlend < strip.getTransition() >> 7) return; // not yet time to fade, delay the update if ((uint16_t)((uint16_t)millis() - _lastPaletteBlend) < strip.getTransition() >> 7) return; // not yet time to fade, delay the update
_lastPaletteBlend = millis(); _lastPaletteBlend = (uint16_t)millis();
} }
nblendPaletteTowardPalette(_randomPalette, _newRandomPalette, 48); nblendPaletteTowardPalette(_randomPalette, _newRandomPalette, 48);
} }
@ -735,11 +735,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
uint16_t len = length(); uint16_t len = length();
uint8_t _bri_t = currentBri(); uint8_t _bri_t = currentBri();
if (_bri_t < 255) { if (_bri_t < 255) {
byte r = scale8(R(col), _bri_t); col = color_fade(col, _bri_t);
byte g = scale8(G(col), _bri_t);
byte b = scale8(B(col), _bri_t);
byte w = scale8(W(col), _bri_t);
col = RGBW32(r, g, b, w);
} }
// expand pixel (taking into account start, grouping, spacing [and offset]) // expand pixel (taking into account start, grouping, spacing [and offset])
@ -777,6 +773,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
} }
} }
#ifdef WLED_USE_AA_PIXELS
// anti-aliased normalized version of setPixelColor() // anti-aliased normalized version of setPixelColor()
void Segment::setPixelColor(float i, uint32_t col, bool aa) void Segment::setPixelColor(float i, uint32_t col, bool aa)
{ {
@ -809,6 +806,7 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa)
setPixelColor(uint16_t(roundf(fC)) | (vStrip<<16), col); setPixelColor(uint16_t(roundf(fC)) | (vStrip<<16), col);
} }
} }
#endif
uint32_t IRAM_ATTR Segment::getPixelColor(int i) uint32_t IRAM_ATTR Segment::getPixelColor(int i)
{ {
@ -993,33 +991,43 @@ 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) { void 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()) {
// compatibility with 2D // compatibility with 2D
const unsigned cols = virtualWidth(); const unsigned cols = virtualWidth();
const unsigned rows = virtualHeight(); const unsigned rows = virtualHeight();
for (unsigned i = 0; i < rows; i++) blurRow(i, blur_amount); // blur all rows for (unsigned i = 0; i < rows; i++) blurRow(i, blur_amount, smear); // blur all rows
for (unsigned k = 0; k < cols; k++) blurCol(k, blur_amount); // blur all columns for (unsigned k = 0; k < cols; k++) blurCol(k, blur_amount, smear); // blur all columns
return; return;
} }
#endif #endif
uint8_t keep = 255 - blur_amount; uint8_t keep = smear ? 255 : 255 - blur_amount;
uint8_t seep = blur_amount >> 1; uint8_t seep = blur_amount >> 1;
uint32_t carryover = BLACK;
unsigned vlength = virtualLength(); unsigned vlength = virtualLength();
uint32_t carryover = BLACK;
uint32_t lastnew;
uint32_t last;
uint32_t curnew;
for (unsigned i = 0; i < vlength; i++) { for (unsigned i = 0; i < vlength; i++) {
uint32_t cur = getPixelColor(i); uint32_t cur = getPixelColor(i);
uint32_t part = color_fade(cur, seep); uint32_t part = color_fade(cur, seep);
cur = color_add(color_fade(cur, keep), carryover, true); curnew = color_fade(cur, keep);
if (i > 0) { if (i > 0) {
uint32_t c = getPixelColor(i-1); if (carryover)
setPixelColor(i-1, color_add(c, part, true)); curnew = color_add(curnew, carryover, true);
uint32_t prev = color_add(lastnew, part, true);
if (last != prev) // optimization: only set pixel if color has changed
setPixelColor(i - 1, prev);
} }
setPixelColor(i, cur); else // first pixel
setPixelColor(i, curnew);
lastnew = curnew;
last = cur; // save original value for comparison on next iteration
carryover = part; carryover = part;
} }
setPixelColor(vlength - 1, curnew);
} }
/* /*
@ -1098,6 +1106,12 @@ void WS2812FX::finalizeInit(void) {
uint16_t prevLen = 0; uint16_t prevLen = 0;
for (int i = 0; i < defNumBusses && i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) { for (int i = 0; i < defNumBusses && i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) {
uint8_t defPin[] = {defDataPins[i]}; uint8_t defPin[] = {defDataPins[i]};
// when booting without config (1st boot) we need to make sure GPIOs defined for LED output don't clash with hardware
// i.e. DEBUG (GPIO1), DMX (2), SPI RAM/FLASH (16&17 on ESP32-WROVER/PICO), etc
if (pinManager.isPinAllocated(defPin[0])) {
defPin[0] = 1; // start with GPIO1 and work upwards
while (pinManager.isPinAllocated(defPin[0]) && defPin[0] < WLED_NUM_PINS) defPin[0]++;
}
uint16_t start = prevLen; uint16_t start = prevLen;
uint16_t count = defCounts[(i < defNumCounts) ? i : defNumCounts -1]; uint16_t count = defCounts[(i < defNumCounts) ? i : defNumCounts -1];
prevLen += count; prevLen += count;
@ -1162,12 +1176,16 @@ void WS2812FX::service() {
uint16_t delay = FRAMETIME; uint16_t delay = FRAMETIME;
if (!seg.freeze) { //only run effect function if not frozen if (!seg.freeze) { //only run effect function if not frozen
int16_t oldCCT = BusManager::getSegmentCCT(); // store original CCT value (actually it is not Segment based)
_virtualSegmentLength = seg.virtualLength(); //SEGLEN _virtualSegmentLength = seg.virtualLength(); //SEGLEN
_colors_t[0] = gamma32(seg.currentColor(0)); _colors_t[0] = gamma32(seg.currentColor(0));
_colors_t[1] = gamma32(seg.currentColor(1)); _colors_t[1] = gamma32(seg.currentColor(1));
_colors_t[2] = gamma32(seg.currentColor(2)); _colors_t[2] = gamma32(seg.currentColor(2));
seg.currentPalette(_currentPalette, seg.palette); // we need to pass reference seg.currentPalette(_currentPalette, seg.palette); // we need to pass reference
if (!cctFromRgb || correctWB) BusManager::setSegmentCCT(seg.currentBri(true), correctWB); // when correctWB is true we need to correct/adjust RGB value according to desired CCT value, but it will also affect actual WW/CW ratio
// when cctFromRgb is true we implicitly calculate WW and CW from RGB values
if (cctFromRgb) BusManager::setSegmentCCT(-1);
else BusManager::setSegmentCCT(seg.currentBri(true), correctWB);
// Effect blending // Effect blending
// When two effects are being blended, each may have different segment data, this // When two effects are being blended, each may have different segment data, this
// data needs to be saved first and then restored before running previous mode. // data needs to be saved first and then restored before running previous mode.
@ -1190,20 +1208,19 @@ void WS2812FX::service() {
#endif #endif
seg.call++; seg.call++;
if (seg.isInTransition() && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition if (seg.isInTransition() && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition
BusManager::setSegmentCCT(oldCCT); // restore old CCT for ABL adjustments
} }
seg.next_time = nowUp + delay; seg.next_time = nowUp + delay;
} }
// if (_segment_index == _queuedChangesSegId) setUpSegmentFromQueuedChanges();
_segment_index++; _segment_index++;
} }
_virtualSegmentLength = 0; _virtualSegmentLength = 0;
BusManager::setSegmentCCT(-1);
_isServicing = false; _isServicing = false;
_triggered = false; _triggered = false;
#ifdef WLED_DEBUG #ifdef WLED_DEBUG
if (millis() - nowUp > _frametime) DEBUG_PRINTLN(F("Slow effects.")); if (millis() - nowUp > _frametime) DEBUG_PRINTF_P(PSTR("Slow effects %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime);
#endif #endif
if (doShow) { if (doShow) {
yield(); yield();
@ -1211,7 +1228,7 @@ void WS2812FX::service() {
show(); show();
} }
#ifdef WLED_DEBUG #ifdef WLED_DEBUG
if (millis() - nowUp > _frametime) DEBUG_PRINTLN(F("Slow strip.")); if (millis() - nowUp > _frametime) DEBUG_PRINTF_P(PSTR("Slow strip %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime);
#endif #endif
} }
@ -1390,11 +1407,7 @@ bool WS2812FX::hasCCTBus(void) {
for (size_t b = 0; b < BusManager::getNumBusses(); b++) { for (size_t b = 0; b < BusManager::getNumBusses(); b++) {
Bus *bus = BusManager::getBus(b); Bus *bus = BusManager::getBus(b);
if (bus == nullptr || bus->getLength()==0) break; if (bus == nullptr || bus->getLength()==0) break;
switch (bus->getType()) { if (bus->hasCCT()) return true;
case TYPE_ANALOG_5CH:
case TYPE_ANALOG_2CH:
return true;
}
} }
return false; return false;
} }
@ -1425,31 +1438,12 @@ void WS2812FX::setSegment(uint8_t segId, uint16_t i1, uint16_t i2, uint8_t group
appendSegment(Segment(0, strip.getLengthTotal())); appendSegment(Segment(0, strip.getLengthTotal()));
segId = getSegmentsNum()-1; // segments are added at the end of list segId = getSegmentsNum()-1; // segments are added at the end of list
} }
/*
if (_queuedChangesSegId == segId) _queuedChangesSegId = 255; // cancel queued change if already queued for this segment
if (segId < getMaxSegments() && segId == getCurrSegmentId() && isServicing()) { // queue change to prevent concurrent access
// queuing a change for a second segment will lead to the loss of the first change if not yet applied
// however this is not a problem as the queued change is applied immediately after the effect function in that segment returns
_qStart = i1; _qStop = i2; _qStartY = startY; _qStopY = stopY;
_qGrouping = grouping; _qSpacing = spacing; _qOffset = offset;
_queuedChangesSegId = segId;
DEBUG_PRINT(F("Segment queued: ")); DEBUG_PRINTLN(segId);
return; // queued changes are applied immediately after effect function returns
}
*/
suspend(); suspend();
_segments[segId].setUp(i1, i2, grouping, spacing, offset, startY, stopY); _segments[segId].setUp(i1, i2, grouping, spacing, offset, startY, stopY);
resume(); resume();
if (segId > 0 && segId == getSegmentsNum()-1 && i2 <= i1) _segments.pop_back(); // if last segment was deleted remove it from vector if (segId > 0 && segId == getSegmentsNum()-1 && i2 <= i1) _segments.pop_back(); // if last segment was deleted remove it from vector
} }
/*
void WS2812FX::setUpSegmentFromQueuedChanges() {
if (_queuedChangesSegId >= getSegmentsNum()) return;
_segments[_queuedChangesSegId].setUp(_qStart, _qStop, _qGrouping, _qSpacing, _qOffset, _qStartY, _qStopY);
_queuedChangesSegId = 255;
}
*/
void WS2812FX::resetSegments() { void WS2812FX::resetSegments() {
_segments.clear(); // destructs all Segment as part of clearing _segments.clear(); // destructs all Segment as part of clearing
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
@ -1670,19 +1664,23 @@ bool WS2812FX::deserializeMap(uint8_t n) {
return false; // if file does not load properly then exit return false; // if file does not load properly then exit
} }
DEBUG_PRINT(F("Reading LED map from ")); DEBUG_PRINTLN(fileName); if (customMappingTable) delete[] customMappingTable;
customMappingTable = new uint16_t[getLengthTotal()];
if (customMappingTable == nullptr) customMappingTable = new uint16_t[getLengthTotal()]; if (customMappingTable) {
DEBUG_PRINT(F("Reading LED map from ")); DEBUG_PRINTLN(fileName);
JsonObject root = pDoc->as<JsonObject>(); JsonObject root = pDoc->as<JsonObject>();
JsonArray map = root[F("map")]; JsonArray map = root[F("map")];
if (!map.isNull() && map.size()) { // not an empty map if (!map.isNull() && map.size()) { // not an empty map
customMappingSize = min((unsigned)map.size(), (unsigned)getLengthTotal()); customMappingSize = min((unsigned)map.size(), (unsigned)getLengthTotal());
for (unsigned i=0; i<customMappingSize; i++) customMappingTable[i] = (uint16_t) (map[i]<0 ? 0xFFFFU : map[i]); for (unsigned i=0; i<customMappingSize; i++) customMappingTable[i] = (uint16_t) (map[i]<0 ? 0xFFFFU : map[i]);
}
} else {
DEBUG_PRINTLN(F("ERROR LED map allocation error."));
} }
releaseJSONBufferLock(); releaseJSONBufferLock();
return true; return (customMappingSize > 0);
} }
uint16_t IRAM_ATTR WS2812FX::getMappedPixelIndex(uint16_t index) { uint16_t IRAM_ATTR WS2812FX::getMappedPixelIndex(uint16_t index) {

Wyświetl plik

@ -9,9 +9,10 @@
#include "bus_wrapper.h" #include "bus_wrapper.h"
#include "bus_manager.h" #include "bus_manager.h"
extern bool cctICused;
//colors.cpp //colors.cpp
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb); uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
uint16_t approximateKelvinFromRGB(uint32_t rgb);
//udp.cpp //udp.cpp
uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte *buffer, uint8_t bri=255, bool isRGBW=false); uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte *buffer, uint8_t bri=255, bool isRGBW=false);
@ -122,13 +123,13 @@ BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com)
} }
_iType = PolyBus::getI(bc.type, _pins, nr); _iType = PolyBus::getI(bc.type, _pins, nr);
if (_iType == I_NONE) return; if (_iType == I_NONE) return;
if (bc.doubleBuffer && !allocData(bc.count * (Bus::hasWhite(_type) + 3*Bus::hasRGB(_type)))) return; //warning: hardcoded channel count if (bc.doubleBuffer && !allocData(bc.count * Bus::getNumberOfChannels(bc.type))) return;
//_buffering = bc.doubleBuffer; //_buffering = bc.doubleBuffer;
uint16_t lenToCreate = bc.count; uint16_t lenToCreate = bc.count;
if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(bc.count); // only needs a third of "RGB" LEDs for NeoPixelBus if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(bc.count); // only needs a third of "RGB" LEDs for NeoPixelBus
_busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr, _frequencykHz); _busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr, _frequencykHz);
_valid = (_busPtr != nullptr); _valid = (_busPtr != nullptr);
DEBUG_PRINTF("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u). mA=%d/%d\n", _valid?"S":"Uns", nr, bc.count, bc.type, _pins[0], _pins[1], _iType, _milliAmpsPerLed, _milliAmpsMax); DEBUG_PRINTF_P(PSTR("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u). mA=%d/%d\n"), _valid?"S":"Uns", nr, bc.count, bc.type, _pins[0], IS_2PIN(bc.type)?_pins[1]:255, _iType, _milliAmpsPerLed, _milliAmpsMax);
} }
//fine tune power estimation constants for your setup //fine tune power estimation constants for your setup
@ -205,13 +206,15 @@ void BusDigital::show() {
_milliAmpsTotal = 0; _milliAmpsTotal = 0;
if (!_valid) return; if (!_valid) return;
uint8_t cctWW = 0, cctCW = 0;
uint8_t newBri = estimateCurrentAndLimitBri(); // will fill _milliAmpsTotal uint8_t newBri = estimateCurrentAndLimitBri(); // will fill _milliAmpsTotal
if (newBri < _bri) PolyBus::setBrightness(_busPtr, _iType, newBri); // limit brightness to stay within current limits if (newBri < _bri) PolyBus::setBrightness(_busPtr, _iType, newBri); // limit brightness to stay within current limits
if (_data) { // use _buffering this causes ~20% FPS drop if (_data) {
size_t channels = Bus::hasWhite(_type) + 3*Bus::hasRGB(_type); size_t channels = getNumberOfChannels();
int16_t oldCCT = Bus::_cct; // temporarily save bus CCT
for (size_t i=0; i<_len; i++) { for (size_t i=0; i<_len; i++) {
size_t offset = i*channels; size_t offset = i * channels;
uint8_t co = _colorOrderMap.getPixelColorOrder(i+_start, _colorOrder); uint8_t co = _colorOrderMap.getPixelColorOrder(i+_start, _colorOrder);
uint32_t c; uint32_t c;
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs (_len is always a multiple of 3) if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs (_len is always a multiple of 3)
@ -221,17 +224,26 @@ void BusDigital::show() {
case 2: c = RGBW32(_data[offset-2], _data[offset-1], _data[offset] , 0); break; case 2: c = RGBW32(_data[offset-2], _data[offset-1], _data[offset] , 0); break;
} }
} else { } else {
c = RGBW32(_data[offset],_data[offset+1],_data[offset+2],(Bus::hasWhite(_type)?_data[offset+3]:0)); if (hasRGB()) c = RGBW32(_data[offset], _data[offset+1], _data[offset+2], hasWhite() ? _data[offset+3] : 0);
else c = RGBW32(0, 0, 0, _data[offset]);
}
if (hasCCT()) {
// unfortunately as a segment may span multiple buses or a bus may contain multiple segments and each segment may have different CCT
// we need to extract and appy CCT value for each pixel individually even though all buses share the same _cct variable
// TODO: there is an issue if CCT is calculated from RGB value (_cct==-1), we cannot do that with double buffer
Bus::_cct = _data[offset+channels-1];
Bus::calculateCCT(c, cctWW, cctCW);
} }
uint16_t pix = i; uint16_t pix = i;
if (_reversed) pix = _len - pix -1; if (_reversed) pix = _len - pix -1;
pix += _skip; pix += _skip;
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co); PolyBus::setPixelColor(_busPtr, _iType, pix, c, co, (cctCW<<8) | cctWW);
} }
#if !defined(STATUSLED) || STATUSLED>=0 #if !defined(STATUSLED) || STATUSLED>=0
if (_skip) PolyBus::setPixelColor(_busPtr, _iType, 0, 0, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); // paint skipped pixels black if (_skip) PolyBus::setPixelColor(_busPtr, _iType, 0, 0, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); // paint skipped pixels black
#endif #endif
for (int i=1; i<_skip; i++) PolyBus::setPixelColor(_busPtr, _iType, i, 0, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); // paint skipped pixels black for (int i=1; i<_skip; i++) PolyBus::setPixelColor(_busPtr, _iType, i, 0, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); // paint skipped pixels black
Bus::_cct = oldCCT;
} else { } else {
if (newBri < _bri) { if (newBri < _bri) {
uint16_t hwLen = _len; uint16_t hwLen = _len;
@ -239,7 +251,8 @@ void BusDigital::show() {
for (unsigned i = 0; i < hwLen; i++) { for (unsigned i = 0; i < hwLen; i++) {
// use 0 as color order, actual order does not matter here as we just update the channel values as-is // use 0 as color order, actual order does not matter here as we just update the channel values as-is
uint32_t c = restoreColorLossy(PolyBus::getPixelColor(_busPtr, _iType, i, 0), _bri); uint32_t c = restoreColorLossy(PolyBus::getPixelColor(_busPtr, _iType, i, 0), _bri);
PolyBus::setPixelColor(_busPtr, _iType, i, c, 0); // repaint all pixels with new brightness if (hasCCT()) Bus::calculateCCT(c, cctWW, cctCW); // this will unfortunately corrupt (segment) CCT data on every bus
PolyBus::setPixelColor(_busPtr, _iType, i, c, 0, (cctCW<<8) | cctWW); // repaint all pixels with new brightness
} }
} }
} }
@ -278,17 +291,20 @@ void BusDigital::setStatusPixel(uint32_t c) {
void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) { void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) {
if (!_valid) return; if (!_valid) return;
if (Bus::hasWhite(_type)) c = autoWhiteCalc(c); uint8_t cctWW = 0, cctCW = 0;
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT if (hasWhite()) c = autoWhiteCalc(c);
if (_data) { // use _buffering this causes ~20% FPS drop if (Bus::_cct >= 1900) c = colorBalanceFromKelvin(Bus::_cct, c); //color correction from CCT
size_t channels = Bus::hasWhite(_type) + 3*Bus::hasRGB(_type); if (_data) {
size_t offset = pix*channels; size_t offset = pix * getNumberOfChannels();
if (Bus::hasRGB(_type)) { if (hasRGB()) {
_data[offset++] = R(c); _data[offset++] = R(c);
_data[offset++] = G(c); _data[offset++] = G(c);
_data[offset++] = B(c); _data[offset++] = B(c);
} }
if (Bus::hasWhite(_type)) _data[offset] = W(c); if (hasWhite()) _data[offset++] = W(c);
// unfortunately as a segment may span multiple buses or a bus may contain multiple segments and each segment may have different CCT
// we need to store CCT value for each pixel (if there is a color correction in play, convert K in CCT ratio)
if (hasCCT()) _data[offset] = Bus::_cct >= 1900 ? (Bus::_cct - 1900) >> 5 : (Bus::_cct < 0 ? 127 : Bus::_cct); // TODO: if _cct == -1 we simply ignore it
} else { } else {
if (_reversed) pix = _len - pix -1; if (_reversed) pix = _len - pix -1;
pix += _skip; pix += _skip;
@ -303,21 +319,21 @@ void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) {
case 2: c = RGBW32(R(cOld), G(cOld), W(c) , 0); break; case 2: c = RGBW32(R(cOld), G(cOld), W(c) , 0); break;
} }
} }
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co); if (hasCCT()) Bus::calculateCCT(c, cctWW, cctCW);
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co, (cctCW<<8) | cctWW);
} }
} }
// returns original color if global buffering is enabled, else returns lossly restored color from bus // returns original color if global buffering is enabled, else returns lossly restored color from bus
uint32_t IRAM_ATTR BusDigital::getPixelColor(uint16_t pix) { uint32_t IRAM_ATTR BusDigital::getPixelColor(uint16_t pix) {
if (!_valid) return 0; if (!_valid) return 0;
if (_data) { // use _buffering this causes ~20% FPS drop if (_data) {
size_t channels = Bus::hasWhite(_type) + 3*Bus::hasRGB(_type); size_t offset = pix * getNumberOfChannels();
size_t offset = pix*channels;
uint32_t c; uint32_t c;
if (!Bus::hasRGB(_type)) { if (!hasRGB()) {
c = RGBW32(_data[offset], _data[offset], _data[offset], _data[offset]); c = RGBW32(_data[offset], _data[offset], _data[offset], _data[offset]);
} else { } else {
c = RGBW32(_data[offset], _data[offset+1], _data[offset+2], Bus::hasWhite(_type) ? _data[offset+3] : 0); c = RGBW32(_data[offset], _data[offset+1], _data[offset+2], hasWhite() ? _data[offset+3] : 0);
} }
return c; return c;
} else { } else {
@ -414,48 +430,31 @@ BusPwm::BusPwm(BusConfig &bc)
void BusPwm::setPixelColor(uint16_t pix, uint32_t c) { void BusPwm::setPixelColor(uint16_t pix, uint32_t c) {
if (pix != 0 || !_valid) return; //only react to first pixel if (pix != 0 || !_valid) return; //only react to first pixel
if (_type != TYPE_ANALOG_3CH) c = autoWhiteCalc(c); if (_type != TYPE_ANALOG_3CH) c = autoWhiteCalc(c);
if (_cct >= 1900 && (_type == TYPE_ANALOG_3CH || _type == TYPE_ANALOG_4CH)) { if (Bus::_cct >= 1900 && (_type == TYPE_ANALOG_3CH || _type == TYPE_ANALOG_4CH)) {
c = colorBalanceFromKelvin(_cct, c); //color correction from CCT c = colorBalanceFromKelvin(Bus::_cct, c); //color correction from CCT
} }
uint8_t r = R(c); uint8_t r = R(c);
uint8_t g = G(c); uint8_t g = G(c);
uint8_t b = B(c); uint8_t b = B(c);
uint8_t w = W(c); uint8_t w = W(c);
uint8_t cct = 0; //0 - full warm white, 255 - full cold white
if (_cct > -1) {
if (_cct >= 1900) cct = (_cct - 1900) >> 5;
else if (_cct < 256) cct = _cct;
} else {
cct = (approximateKelvinFromRGB(c) - 1900) >> 5;
}
uint8_t ww, cw;
#ifdef WLED_USE_IC_CCT
ww = w;
cw = cct;
#else
//0 - linear (CCT 127 = 50% warm, 50% cold), 127 - additive CCT blending (CCT 127 = 100% warm, 100% cold)
if (cct < _cctBlend) ww = 255;
else ww = ((255-cct) * 255) / (255 - _cctBlend);
if ((255-cct) < _cctBlend) cw = 255;
else cw = (cct * 255) / (255 - _cctBlend);
ww = (w * ww) / 255; //brightness scaling
cw = (w * cw) / 255;
#endif
switch (_type) { switch (_type) {
case TYPE_ANALOG_1CH: //one channel (white), relies on auto white calculation case TYPE_ANALOG_1CH: //one channel (white), relies on auto white calculation
_data[0] = w; _data[0] = w;
break; break;
case TYPE_ANALOG_2CH: //warm white + cold white case TYPE_ANALOG_2CH: //warm white + cold white
_data[1] = cw; if (cctICused) {
_data[0] = ww; _data[0] = w;
_data[1] = Bus::_cct < 0 || Bus::_cct > 255 ? 127 : Bus::_cct;
} else {
Bus::calculateCCT(c, _data[0], _data[1]);
}
break; break;
case TYPE_ANALOG_5CH: //RGB + warm white + cold white case TYPE_ANALOG_5CH: //RGB + warm white + cold white
_data[4] = cw; if (cctICused)
w = ww; _data[4] = Bus::_cct < 0 || Bus::_cct > 255 ? 127 : Bus::_cct;
else
Bus::calculateCCT(c, w, _data[4]);
case TYPE_ANALOG_4CH: //RGBW case TYPE_ANALOG_4CH: //RGBW
_data[3] = w; _data[3] = w;
case TYPE_ANALOG_3CH: //standard dumb RGB case TYPE_ANALOG_3CH: //standard dumb RGB
@ -506,7 +505,7 @@ void BusPwm::show() {
uint8_t numPins = NUM_PWM_PINS(_type); uint8_t numPins = NUM_PWM_PINS(_type);
unsigned maxBri = (1<<_depth) - 1; unsigned maxBri = (1<<_depth) - 1;
#ifdef ESP8266 #ifdef ESP8266
unsigned pwmBri = (unsigned)(roundf(powf((float)_bri / 255.0f, 1.7f) * (float)maxBri + 0.5f)); // using gamma 1.7 to extrapolate PWM duty cycle unsigned pwmBri = (unsigned)(roundf(powf((float)_bri / 255.0f, 1.7f) * (float)maxBri)); // using gamma 1.7 to extrapolate PWM duty cycle
#else #else
unsigned pwmBri = cieLUT[_bri] >> (12 - _depth); // use CIE LUT unsigned pwmBri = cieLUT[_bri] >> (12 - _depth); // use CIE LUT
#endif #endif
@ -620,7 +619,7 @@ BusNetwork::BusNetwork(BusConfig &bc)
void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) { void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
if (!_valid || pix >= _len) return; if (!_valid || pix >= _len) return;
if (_rgbw) c = autoWhiteCalc(c); if (_rgbw) c = autoWhiteCalc(c);
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT if (Bus::_cct >= 1900) c = colorBalanceFromKelvin(Bus::_cct, c); //color correction from CCT
uint16_t offset = pix * _UDPchannels; uint16_t offset = pix * _UDPchannels;
_data[offset] = R(c); _data[offset] = R(c);
_data[offset+1] = G(c); _data[offset+1] = G(c);
@ -660,25 +659,18 @@ uint32_t BusManager::memUsage(BusConfig &bc) {
if (bc.type == TYPE_ONOFF || IS_PWM(bc.type)) return 5; if (bc.type == TYPE_ONOFF || IS_PWM(bc.type)) return 5;
uint16_t len = bc.count + bc.skipAmount; uint16_t len = bc.count + bc.skipAmount;
uint16_t channels = 3; uint16_t channels = Bus::getNumberOfChannels(bc.type);
uint16_t multiplier = 1; uint16_t multiplier = 1;
if (IS_DIGITAL(bc.type)) { // digital types if (IS_DIGITAL(bc.type)) { // digital types
if (IS_16BIT(bc.type)) len *= 2; // 16-bit LEDs if (IS_16BIT(bc.type)) len *= 2; // 16-bit LEDs
#ifdef ESP8266 #ifdef ESP8266
if (bc.type > 28) channels = 4; //RGBW
if (bc.pins[0] == 3) { //8266 DMA uses 5x the mem if (bc.pins[0] == 3) { //8266 DMA uses 5x the mem
multiplier = 5; multiplier = 5;
} }
#else //ESP32 RMT uses double buffer, I2S uses 5x buffer #else //ESP32 RMT uses double buffer, I2S uses 5x buffer
if (bc.type > 28) channels = 4; //RGBW
multiplier = 2; multiplier = 2;
#endif #endif
} }
if (IS_VIRTUAL(bc.type)) {
switch (bc.type) {
case TYPE_NET_DDP_RGBW: channels = 4; break;
}
}
return len * channels * multiplier; //RGB return len * channels * multiplier; //RGB
} }
@ -740,7 +732,7 @@ void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) {
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
if (allowWBCorrection) cct = 1900 + (cct << 5); if (allowWBCorrection) cct = 1900 + (cct << 5);
} else cct = -1; } else cct = -1; // will use kelvin approximation from RGB
Bus::setCCT(cct); Bus::setCCT(cct);
} }

Wyświetl plik

@ -7,6 +7,9 @@
#include "const.h" #include "const.h"
//colors.cpp
uint16_t approximateKelvinFromRGB(uint32_t rgb);
#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,7 +35,7 @@ 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] = {255, 255, 255, 255, 255};
uint16_t frequency; uint16_t frequency;
bool doubleBuffer; bool doubleBuffer;
uint8_t milliAmpsPerLed; uint8_t milliAmpsPerLed;
@ -53,9 +56,9 @@ struct BusConfig {
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)
size_t nPins = 1; size_t nPins = 1;
if (type >= TYPE_NET_DDP_RGB && type < 96) nPins = 4; //virtual network bus. 4 "pins" store IP address if (IS_VIRTUAL(type)) nPins = 4; //virtual network bus. 4 "pins" store IP address
else if (type > 47) nPins = 2; else if (IS_2PIN(type)) nPins = 2;
else if (type > 40 && type < 46) nPins = NUM_PWM_PINS(type); else if (IS_PWM(type)) nPins = NUM_PWM_PINS(type);
for (size_t i = 0; i < nPins; i++) pins[i] = ppins[i]; for (size_t i = 0; i < nPins; i++) pins[i] = ppins[i];
} }
@ -138,6 +141,8 @@ class Bus {
virtual uint16_t getLEDCurrent() { return 0; } virtual uint16_t getLEDCurrent() { return 0; }
virtual uint16_t getUsedCurrent() { return 0; } virtual uint16_t getUsedCurrent() { return 0; }
virtual uint16_t getMaxCurrent() { return 0; } virtual uint16_t getMaxCurrent() { return 0; }
virtual uint8_t getNumberOfChannels() { return hasWhite(_type) + 3*hasRGB(_type) + hasCCT(_type); }
static inline uint8_t getNumberOfChannels(uint8_t type) { return hasWhite(type) + 3*hasRGB(type) + hasCCT(type); }
inline void setReversed(bool reversed) { _reversed = reversed; } inline void setReversed(bool reversed) { _reversed = reversed; }
inline uint16_t getStart() { return _start; } inline uint16_t getStart() { return _start; }
inline void setStart(uint16_t start) { _start = start; } inline void setStart(uint16_t start) { _start = start; }
@ -154,18 +159,22 @@ class Bus {
} }
virtual bool hasWhite(void) { return Bus::hasWhite(_type); } virtual bool hasWhite(void) { 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 ||
type == TYPE_FW1906 || type == TYPE_WS2805) 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 || type == TYPE_NET_ARTNET_RGBW) return true; // network types with white channel
return false; return false;
} }
virtual bool hasCCT(void) { return Bus::hasCCT(_type); } virtual bool hasCCT(void) { return Bus::hasCCT(_type); }
static bool hasCCT(uint8_t type) { static bool hasCCT(uint8_t type) {
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 ||
type == TYPE_FW1906 || type == TYPE_WS2805 ) return true;
return false; return false;
} }
static void setCCT(uint16_t cct) { static int16_t getCCT() { return _cct; }
static void setCCT(int16_t cct) {
_cct = cct; _cct = cct;
} }
static void setCCTBlend(uint8_t b) { static void setCCTBlend(uint8_t b) {
@ -176,6 +185,26 @@ class Bus {
if (_cctBlend > WLED_MAX_CCT_BLEND) _cctBlend = WLED_MAX_CCT_BLEND; if (_cctBlend > WLED_MAX_CCT_BLEND) _cctBlend = WLED_MAX_CCT_BLEND;
#endif #endif
} }
static void calculateCCT(uint32_t c, uint8_t &ww, uint8_t &cw) {
uint8_t cct = 0; //0 - full warm white, 255 - full cold white
uint8_t w = byte(c >> 24);
if (_cct > -1) {
if (_cct >= 1900) cct = (_cct - 1900) >> 5;
else if (_cct < 256) cct = _cct;
} else {
cct = (approximateKelvinFromRGB(c) - 1900) >> 5;
}
//0 - linear (CCT 127 = 50% warm, 50% cold), 127 - additive CCT blending (CCT 127 = 100% warm, 100% cold)
if (cct < _cctBlend) ww = 255;
else ww = ((255-cct) * 255) / (255 - _cctBlend);
if ((255-cct) < _cctBlend) cw = 255;
else cw = (cct * 255) / (255 - _cctBlend);
ww = (w * ww) / 255; //brightness scaling
cw = (w * cw) / 255;
}
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() { 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; }
@ -191,8 +220,17 @@ class Bus {
bool _needsRefresh; bool _needsRefresh;
uint8_t _autoWhiteMode; uint8_t _autoWhiteMode;
uint8_t *_data; uint8_t *_data;
// global Auto White Calculation override
static uint8_t _gAWM; static uint8_t _gAWM;
// _cct has the following menaings (see calculateCCT() & BusManager::setSegmentCCT()):
// -1 means to extract approximate CCT value in K from RGB (in calcualteCCT())
// [0,255] is the exact CCT value where 0 means warm and 255 cold
// [1900,10060] only for color correction expressed in K (colorBalanceFromKelvin())
static int16_t _cct; static int16_t _cct;
// _cctBlend determines WW/CW blending:
// 0 - linear (CCT 127 => 50% warm, 50% cold)
// 63 - semi additive/nonlinear (CCT 127 => 66% warm, 66% cold)
// 127 - additive CCT blending (CCT 127 => 100% warm, 100% cold)
static uint8_t _cctBlend; static uint8_t _cctBlend;
uint32_t autoWhiteCalc(uint32_t c); uint32_t autoWhiteCalc(uint32_t c);
@ -334,9 +372,12 @@ class BusManager {
static void setStatusPixel(uint32_t c); static void setStatusPixel(uint32_t c);
static void setPixelColor(uint16_t pix, uint32_t c); static void setPixelColor(uint16_t pix, uint32_t c);
static void setBrightness(uint8_t b); static void setBrightness(uint8_t b);
// for setSegmentCCT(), cct can only be in [-1,255] range; allowWBCorrection will convert it to K
// WARNING: setSegmentCCT() is a misleading name!!! much better would be setGlobalCCT() or just setCCT()
static void setSegmentCCT(int16_t cct, bool allowWBCorrection = false); static void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
static void setMilliampsMax(uint16_t max) { _milliAmpsMax = max;} static void setMilliampsMax(uint16_t max) { _milliAmpsMax = max;}
static uint32_t getPixelColor(uint16_t pix); static uint32_t getPixelColor(uint16_t pix);
static inline int16_t getSegmentCCT() { return Bus::getCCT(); }
static Bus* getBus(uint8_t busNr); static Bus* getBus(uint8_t busNr);

Wyświetl plik

@ -2,6 +2,7 @@
#define BusWrapper_h #define BusWrapper_h
#include "NeoPixelBusLg.h" #include "NeoPixelBusLg.h"
#include "bus_manager.h"
// temporary - these defines should actually be set in platformio.ini // temporary - these defines should actually be set in platformio.ini
// C3: I2S0 and I2S1 methods not supported (has one I2S bus) // C3: I2S0 and I2S1 methods not supported (has one I2S bus)
@ -63,52 +64,64 @@
#define I_8266_U1_UCS_4 54 #define I_8266_U1_UCS_4 54
#define I_8266_DM_UCS_4 55 #define I_8266_DM_UCS_4 55
#define I_8266_BB_UCS_4 56 #define I_8266_BB_UCS_4 56
//FW1906 GRBCW
#define I_8266_U0_FW6_5 66
#define I_8266_U1_FW6_5 67
#define I_8266_DM_FW6_5 68
#define I_8266_BB_FW6_5 69
//ESP8266 APA106 //ESP8266 APA106
#define I_8266_U0_APA106_3 81 #define I_8266_U0_APA106_3 81
#define I_8266_U1_APA106_3 82 #define I_8266_U1_APA106_3 82
#define I_8266_DM_APA106_3 83 #define I_8266_DM_APA106_3 83
#define I_8266_BB_APA106_3 84 #define I_8266_BB_APA106_3 84
//WS2805
#define I_8266_U0_2805_5 89
#define I_8266_U1_2805_5 90
#define I_8266_DM_2805_5 91
#define I_8266_BB_2805_5 92
/*** ESP32 Neopixel methods ***/ /*** ESP32 Neopixel methods ***/
//RGB //RGB
#define I_32_RN_NEO_3 21 #define I_32_RN_NEO_3 21
#define I_32_I0_NEO_3 22 #define I_32_I0_NEO_3 22
#define I_32_I1_NEO_3 23 #define I_32_I1_NEO_3 23
#define I_32_BB_NEO_3 24 // bitbanging on ESP32 not recommended
//RGBW //RGBW
#define I_32_RN_NEO_4 25 #define I_32_RN_NEO_4 25
#define I_32_I0_NEO_4 26 #define I_32_I0_NEO_4 26
#define I_32_I1_NEO_4 27 #define I_32_I1_NEO_4 27
#define I_32_BB_NEO_4 28 // bitbanging on ESP32 not recommended
//400Kbps //400Kbps
#define I_32_RN_400_3 29 #define I_32_RN_400_3 29
#define I_32_I0_400_3 30 #define I_32_I0_400_3 30
#define I_32_I1_400_3 31 #define I_32_I1_400_3 31
#define I_32_BB_400_3 32 // bitbanging on ESP32 not recommended
//TM1814 (RGBW) //TM1814 (RGBW)
#define I_32_RN_TM1_4 33 #define I_32_RN_TM1_4 33
#define I_32_I0_TM1_4 34 #define I_32_I0_TM1_4 34
#define I_32_I1_TM1_4 35 #define I_32_I1_TM1_4 35
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
//TM1829 (RGB) //TM1829 (RGB)
#define I_32_RN_TM2_3 36 #define I_32_RN_TM2_3 36
#define I_32_I0_TM2_3 37 #define I_32_I0_TM2_3 37
#define I_32_I1_TM2_3 38 #define I_32_I1_TM2_3 38
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
//UCS8903 (RGB) //UCS8903 (RGB)
#define I_32_RN_UCS_3 57 #define I_32_RN_UCS_3 57
#define I_32_I0_UCS_3 58 #define I_32_I0_UCS_3 58
#define I_32_I1_UCS_3 59 #define I_32_I1_UCS_3 59
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
//UCS8904 (RGBW) //UCS8904 (RGBW)
#define I_32_RN_UCS_4 60 #define I_32_RN_UCS_4 60
#define I_32_I0_UCS_4 61 #define I_32_I0_UCS_4 61
#define I_32_I1_UCS_4 62 #define I_32_I1_UCS_4 62
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S) //FW1906 GRBCW
#define I_32_RN_FW6_5 63
#define I_32_I0_FW6_5 64
#define I_32_I1_FW6_5 65
//APA106
#define I_32_RN_APA106_3 85 #define I_32_RN_APA106_3 85
#define I_32_I0_APA106_3 86 #define I_32_I0_APA106_3 86
#define I_32_I1_APA106_3 87 #define I_32_I1_APA106_3 87
#define I_32_BB_APA106_3 88 // bitbangging on ESP32 not recommended //WS2805
#define I_32_RN_2805_5 93
#define I_32_I0_2805_5 94
#define I_32_I1_2805_5 95
//APA102 //APA102
#define I_HS_DOT_3 39 //hardware SPI #define I_HS_DOT_3 39 //hardware SPI
@ -176,6 +189,16 @@
#define B_8266_U1_APA106_3 NeoPixelBusLg<NeoRbgFeature, NeoEsp8266Uart1Apa106Method, NeoGammaNullMethod> //3 chan, esp8266, gpio2 #define B_8266_U1_APA106_3 NeoPixelBusLg<NeoRbgFeature, NeoEsp8266Uart1Apa106Method, NeoGammaNullMethod> //3 chan, esp8266, gpio2
#define B_8266_DM_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266DmaApa106Method, NeoGammaNullMethod> //3 chan, esp8266, gpio3 #define B_8266_DM_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266DmaApa106Method, NeoGammaNullMethod> //3 chan, esp8266, gpio3
#define B_8266_BB_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266BitBangApa106Method, NeoGammaNullMethod> //3 chan, esp8266, bb (any pin but 16) #define B_8266_BB_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266BitBangApa106Method, NeoGammaNullMethod> //3 chan, esp8266, bb (any pin but 16)
//FW1906 GRBCW
#define B_8266_U0_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp8266Uart0Ws2813Method, NeoGammaNullMethod> //esp8266, gpio1
#define B_8266_U1_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp8266Uart1Ws2813Method, NeoGammaNullMethod> //esp8266, gpio2
#define B_8266_DM_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp8266Dma800KbpsMethod, NeoGammaNullMethod> //esp8266, gpio3
#define B_8266_BB_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp8266BitBang800KbpsMethod, NeoGammaNullMethod> //esp8266, bb
//WS2805 GRBCW
#define B_8266_U0_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp8266Uart0Ws2805Method, NeoGammaNullMethod> //esp8266, gpio1
#define B_8266_U1_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp8266Uart1Ws2805Method, NeoGammaNullMethod> //esp8266, gpio2
#define B_8266_DM_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp8266DmaWs2805Method, NeoGammaNullMethod> //esp8266, gpio3
#define B_8266_BB_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp8266BitBangWs2805Method, NeoGammaNullMethod> //esp8266, bb
#endif #endif
/*** ESP32 Neopixel methods ***/ /*** ESP32 Neopixel methods ***/
@ -183,75 +206,102 @@
//RGB //RGB
#define B_32_RN_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod> #define B_32_RN_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod> #define B_32_I0_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0Ws2812xMethod, NeoGammaNullMethod>
//#define B_32_I0_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0X8Ws2812xMethod, NeoGammaNullMethod> // parallel I2S
#endif #endif
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod> #define B_32_I1_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1Ws2812xMethod, NeoGammaNullMethod>
//#define B_32_I1_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1X8Ws2812xMethod, NeoGammaNullMethod> // parallel I2S
#endif #endif
//#define B_32_BB_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32BitBang800KbpsMethod, NeoGammaNullMethod> // NeoEsp8266BitBang800KbpsMethod
//RGBW //RGBW
#define B_32_RN_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod> #define B_32_RN_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32RmtNSk6812Method, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod> #define B_32_I0_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s0Sk6812Method, NeoGammaNullMethod>
//#define B_32_I0_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s0X8Sk6812Method, NeoGammaNullMethod> // parallel I2S
#endif #endif
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod> #define B_32_I1_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s1Sk6812Method, NeoGammaNullMethod>
//#define B_32_I1_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s1X8Sk6812Method, NeoGammaNullMethod> // parallel I2S
#endif #endif
//#define B_32_BB_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32BitBang800KbpsMethod, NeoGammaNullMethod> // NeoEsp8266BitBang800KbpsMethod
//400Kbps //400Kbps
#define B_32_RN_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtN400KbpsMethod, NeoGammaNullMethod> #define B_32_RN_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtN400KbpsMethod, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0400KbpsMethod, NeoGammaNullMethod> #define B_32_I0_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0400KbpsMethod, NeoGammaNullMethod>
//#define B_32_I0_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0X8400KbpsMethod, NeoGammaNullMethod> // parallel I2S
#endif #endif
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1400KbpsMethod, NeoGammaNullMethod> #define B_32_I1_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1400KbpsMethod, NeoGammaNullMethod>
//#define B_32_I1_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1X8400KbpsMethod, NeoGammaNullMethod> // parallel I2S
#endif #endif
//#define B_32_BB_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32BitBang400KbpsMethod, NeoGammaNullMethod> // NeoEsp8266BitBang400KbpsMethod
//TM1814 (RGBW) //TM1814 (RGBW)
#define B_32_RN_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32RmtNTm1814Method, NeoGammaNullMethod> #define B_32_RN_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32RmtNTm1814Method, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s0Tm1814Method, NeoGammaNullMethod> #define B_32_I0_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s0Tm1814Method, NeoGammaNullMethod>
//#define B_32_I0_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s0X8Tm1814Method, NeoGammaNullMethod> // parallel I2S
#endif #endif
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s1Tm1814Method, NeoGammaNullMethod> #define B_32_I1_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s1Tm1814Method, NeoGammaNullMethod>
//#define B_32_I1_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s1X8Tm1814Method, NeoGammaNullMethod> // parallel I2S
#endif #endif
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
//TM1829 (RGB) //TM1829 (RGB)
#define B_32_RN_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32RmtNTm1829Method, NeoGammaNullMethod> #define B_32_RN_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32RmtNTm1829Method, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s0Tm1829Method, NeoGammaNullMethod> #define B_32_I0_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s0Tm1829Method, NeoGammaNullMethod>
//#define B_32_I0_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s0X8Tm1829Method, NeoGammaNullMethod> // parallel I2S
#endif #endif
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s1Tm1829Method, NeoGammaNullMethod> #define B_32_I1_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s1Tm1829Method, NeoGammaNullMethod>
//#define B_32_I1_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s1X8Tm1829Method, NeoGammaNullMethod> // parallel I2S
#endif #endif
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
//UCS8903 //UCS8903
#define B_32_RN_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod> #define B_32_RN_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod> #define B_32_I0_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod>
//#define B_32_I0_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s0X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
#endif #endif
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod> #define B_32_I1_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
//#define B_32_I1_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s1X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
#endif #endif
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
//UCS8904 //UCS8904
#define B_32_RN_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod> #define B_32_RN_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod> #define B_32_I0_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod>
//#define B_32_I0_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s0X8800KbpsMethod, NeoGammaNullMethod>// parallel I2S
#endif #endif
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod> #define B_32_I1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
//#define B_32_I1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s1X8800KbpsMethod, NeoGammaNullMethod>// parallel I2S
#endif #endif
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
#define B_32_RN_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtNApa106Method, NeoGammaNullMethod> #define B_32_RN_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtNApa106Method, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0Apa106Method, NeoGammaNullMethod> #define B_32_I0_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0Apa106Method, NeoGammaNullMethod>
//#define B_32_I0_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0X8Apa106Method, NeoGammaNullMethod> // parallel I2S
#endif #endif
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1Apa106Method, NeoGammaNullMethod> #define B_32_I1_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1Apa106Method, NeoGammaNullMethod>
//#define B_32_I1_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1X8Apa106Method, NeoGammaNullMethod> // parallel I2S
#endif
//FW1906 GRBCW
#define B_32_RN_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod>
//#define B_32_I0_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32I2s0X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
//#define B_32_I1_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32I2s1X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
#endif
//WS2805 RGBWC
#define B_32_RN_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32RmtNWs2805Method, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32I2s0Ws2805Method, NeoGammaNullMethod>
//#define B_32_I0_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32I2s0X8Ws2805Method, NeoGammaNullMethod> // parallel I2S
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32I2s1Ws2805Method, NeoGammaNullMethod>
//#define B_32_I1_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32I2s1X8Ws2805Method, NeoGammaNullMethod> // parallel I2S
#endif #endif
//#define B_32_BB_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266BitBangApa106Method, NeoGammaNullMethod> // NeoEsp8266BitBang800KbpsMethod
#endif #endif
//APA102 //APA102
@ -290,6 +340,7 @@
//handles pointer type conversion for all possible bus types //handles pointer type conversion for all possible bus types
class PolyBus { class PolyBus {
public: public:
// initialize SPI bus speed for DotStar methods // initialize SPI bus speed for DotStar methods
template <class T> template <class T>
static void beginDotStar(void* busPtr, int8_t sck, int8_t miso, int8_t mosi, int8_t ss, uint16_t clock_kHz = 0U) { static void beginDotStar(void* busPtr, int8_t sck, int8_t miso, int8_t mosi, int8_t ss, uint16_t clock_kHz = 0U) {
@ -353,6 +404,14 @@ class PolyBus {
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->Begin(); break; case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->Begin(); break;
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->Begin(); break; case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->Begin(); break;
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->Begin(); break; case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->Begin(); break;
case I_8266_U0_FW6_5: (static_cast<B_8266_U0_FW6_5*>(busPtr))->Begin(); break;
case I_8266_U1_FW6_5: (static_cast<B_8266_U1_FW6_5*>(busPtr))->Begin(); break;
case I_8266_DM_FW6_5: (static_cast<B_8266_DM_FW6_5*>(busPtr))->Begin(); break;
case I_8266_BB_FW6_5: (static_cast<B_8266_BB_FW6_5*>(busPtr))->Begin(); break;
case I_8266_U0_2805_5: (static_cast<B_8266_U0_2805_5*>(busPtr))->Begin(); break;
case I_8266_U1_2805_5: (static_cast<B_8266_U1_2805_5*>(busPtr))->Begin(); break;
case I_8266_DM_2805_5: (static_cast<B_8266_DM_2805_5*>(busPtr))->Begin(); break;
case I_8266_BB_2805_5: (static_cast<B_8266_BB_2805_5*>(busPtr))->Begin(); break;
#endif #endif
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Begin(); break; case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Begin(); break;
@ -362,7 +421,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->Begin(); break; case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->Begin(); break;
#endif #endif
// case I_32_BB_NEO_3: (static_cast<B_32_BB_NEO_3*>(busPtr))->Begin(); break;
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->Begin(); break; case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->Begin(); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->Begin(); break; case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->Begin(); break;
@ -370,7 +428,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->Begin(); break; case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->Begin(); break;
#endif #endif
// case I_32_BB_NEO_4: (static_cast<B_32_BB_NEO_4*>(busPtr))->Begin(); break;
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->Begin(); break; case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->Begin(); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->Begin(); break; case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->Begin(); break;
@ -378,7 +435,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Begin(); break; case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Begin(); break;
#endif #endif
// case I_32_BB_400_3: (static_cast<B_32_BB_400_3*>(busPtr))->Begin(); break;
case I_32_RN_TM1_4: beginTM1814<B_32_RN_TM1_4*>(busPtr); break; case I_32_RN_TM1_4: beginTM1814<B_32_RN_TM1_4*>(busPtr); break;
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->Begin(); break; case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->Begin(); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
@ -396,7 +452,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->Begin(); break; case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->Begin(); break;
#endif #endif
// case I_32_BB_UCS_3: (static_cast<B_32_BB_UCS_3*>(busPtr))->Begin(); break;
case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->Begin(); break; case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->Begin(); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->Begin(); break; case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->Begin(); break;
@ -404,7 +459,13 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Begin(); break; case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Begin(); break;
#endif #endif
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->Begin(); break; case I_32_RN_FW6_5: (static_cast<B_32_RN_FW6_5*>(busPtr))->Begin(); break;
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_FW6_5: (static_cast<B_32_I0_FW6_5*>(busPtr))->Begin(); break;
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_FW6_5: (static_cast<B_32_I1_FW6_5*>(busPtr))->Begin(); break;
#endif
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->Begin(); break; case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->Begin(); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->Begin(); break; case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->Begin(); break;
@ -412,7 +473,13 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->Begin(); break; case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->Begin(); break;
#endif #endif
// case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->Begin(); break; case I_32_RN_2805_5: (static_cast<B_32_RN_2805_5*>(busPtr))->Begin(); break;
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_2805_5: (static_cast<B_32_I0_2805_5*>(busPtr))->Begin(); break;
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_2805_5: (static_cast<B_32_I1_2805_5*>(busPtr))->Begin(); break;
#endif
// ESP32 can (and should, to avoid inadvertantly driving the chip select signal) specify the pins used for SPI, but only in begin() // ESP32 can (and should, to avoid inadvertantly driving the chip select signal) specify the pins used for SPI, but only in begin()
case I_HS_DOT_3: beginDotStar<B_HS_DOT_3*>(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break; case I_HS_DOT_3: beginDotStar<B_HS_DOT_3*>(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break;
case I_HS_LPD_3: beginDotStar<B_HS_LPD_3*>(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break; case I_HS_LPD_3: beginDotStar<B_HS_LPD_3*>(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break;
@ -465,6 +532,14 @@ class PolyBus {
case I_8266_U1_APA106_3: busPtr = new B_8266_U1_APA106_3(len, pins[0]); break; case I_8266_U1_APA106_3: busPtr = new B_8266_U1_APA106_3(len, pins[0]); break;
case I_8266_DM_APA106_3: busPtr = new B_8266_DM_APA106_3(len, pins[0]); break; case I_8266_DM_APA106_3: busPtr = new B_8266_DM_APA106_3(len, pins[0]); break;
case I_8266_BB_APA106_3: busPtr = new B_8266_BB_APA106_3(len, pins[0]); break; case I_8266_BB_APA106_3: busPtr = new B_8266_BB_APA106_3(len, pins[0]); break;
case I_8266_U0_FW6_5: busPtr = new B_8266_U0_FW6_5(len, pins[0]); break;
case I_8266_U1_FW6_5: busPtr = new B_8266_U1_FW6_5(len, pins[0]); break;
case I_8266_DM_FW6_5: busPtr = new B_8266_DM_FW6_5(len, pins[0]); break;
case I_8266_BB_FW6_5: busPtr = new B_8266_BB_FW6_5(len, pins[0]); break;
case I_8266_U0_2805_5: busPtr = new B_8266_U0_2805_5(len, pins[0]); break;
case I_8266_U1_2805_5: busPtr = new B_8266_U1_2805_5(len, pins[0]); break;
case I_8266_DM_2805_5: busPtr = new B_8266_DM_2805_5(len, pins[0]); break;
case I_8266_BB_2805_5: busPtr = new B_8266_BB_2805_5(len, pins[0]); break;
#endif #endif
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
case I_32_RN_NEO_3: busPtr = new B_32_RN_NEO_3(len, pins[0], (NeoBusChannel)channel); break; case I_32_RN_NEO_3: busPtr = new B_32_RN_NEO_3(len, pins[0], (NeoBusChannel)channel); break;
@ -474,7 +549,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_3: busPtr = new B_32_I1_NEO_3(len, pins[0]); break; case I_32_I1_NEO_3: busPtr = new B_32_I1_NEO_3(len, pins[0]); break;
#endif #endif
// case I_32_BB_NEO_3: busPtr = new B_32_BB_NEO_3(len, pins[0], (NeoBusChannel)channel); break;
case I_32_RN_NEO_4: busPtr = new B_32_RN_NEO_4(len, pins[0], (NeoBusChannel)channel); break; case I_32_RN_NEO_4: busPtr = new B_32_RN_NEO_4(len, pins[0], (NeoBusChannel)channel); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_NEO_4: busPtr = new B_32_I0_NEO_4(len, pins[0]); break; case I_32_I0_NEO_4: busPtr = new B_32_I0_NEO_4(len, pins[0]); break;
@ -482,7 +556,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_4: busPtr = new B_32_I1_NEO_4(len, pins[0]); break; case I_32_I1_NEO_4: busPtr = new B_32_I1_NEO_4(len, pins[0]); break;
#endif #endif
// case I_32_BB_NEO_4: busPtr = new B_32_BB_NEO_4(len, pins[0], (NeoBusChannel)channel); break;
case I_32_RN_400_3: busPtr = new B_32_RN_400_3(len, pins[0], (NeoBusChannel)channel); break; case I_32_RN_400_3: busPtr = new B_32_RN_400_3(len, pins[0], (NeoBusChannel)channel); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_400_3: busPtr = new B_32_I0_400_3(len, pins[0]); break; case I_32_I0_400_3: busPtr = new B_32_I0_400_3(len, pins[0]); break;
@ -490,7 +563,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_400_3: busPtr = new B_32_I1_400_3(len, pins[0]); break; case I_32_I1_400_3: busPtr = new B_32_I1_400_3(len, pins[0]); break;
#endif #endif
// case I_32_BB_400_3: busPtr = new B_32_BB_400_3(len, pins[0], (NeoBusChannel)channel); break;
case I_32_RN_TM1_4: busPtr = new B_32_RN_TM1_4(len, pins[0], (NeoBusChannel)channel); break; case I_32_RN_TM1_4: busPtr = new B_32_RN_TM1_4(len, pins[0], (NeoBusChannel)channel); break;
case I_32_RN_TM2_3: busPtr = new B_32_RN_TM2_3(len, pins[0], (NeoBusChannel)channel); break; case I_32_RN_TM2_3: busPtr = new B_32_RN_TM2_3(len, pins[0], (NeoBusChannel)channel); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
@ -508,7 +580,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_3: busPtr = new B_32_I1_UCS_3(len, pins[0]); break; case I_32_I1_UCS_3: busPtr = new B_32_I1_UCS_3(len, pins[0]); break;
#endif #endif
// case I_32_BB_UCS_3: busPtr = new B_32_BB_UCS_3(len, pins[0], (NeoBusChannel)channel); break;
case I_32_RN_UCS_4: busPtr = new B_32_RN_UCS_4(len, pins[0], (NeoBusChannel)channel); break; case I_32_RN_UCS_4: busPtr = new B_32_RN_UCS_4(len, pins[0], (NeoBusChannel)channel); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_UCS_4: busPtr = new B_32_I0_UCS_4(len, pins[0]); break; case I_32_I0_UCS_4: busPtr = new B_32_I0_UCS_4(len, pins[0]); break;
@ -516,7 +587,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_4: busPtr = new B_32_I1_UCS_4(len, pins[0]); break; case I_32_I1_UCS_4: busPtr = new B_32_I1_UCS_4(len, pins[0]); break;
#endif #endif
// case I_32_BB_UCS_4: busPtr = new B_32_BB_UCS_4(len, pins[0], (NeoBusChannel)channel); break;
case I_32_RN_APA106_3: busPtr = new B_32_RN_APA106_3(len, pins[0], (NeoBusChannel)channel); break; case I_32_RN_APA106_3: busPtr = new B_32_RN_APA106_3(len, pins[0], (NeoBusChannel)channel); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_APA106_3: busPtr = new B_32_I0_APA106_3(len, pins[0]); break; case I_32_I0_APA106_3: busPtr = new B_32_I0_APA106_3(len, pins[0]); break;
@ -524,7 +594,20 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_APA106_3: busPtr = new B_32_I1_APA106_3(len, pins[0]); break; case I_32_I1_APA106_3: busPtr = new B_32_I1_APA106_3(len, pins[0]); break;
#endif #endif
// case I_32_BB_APA106_3: busPtr = new B_32_BB_APA106_3(len, pins[0], (NeoBusChannel)channel); break; case I_32_RN_FW6_5: busPtr = new B_32_RN_FW6_5(len, pins[0], (NeoBusChannel)channel); break;
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_FW6_5: busPtr = new B_32_I0_FW6_5(len, pins[0]); break;
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_FW6_5: busPtr = new B_32_I1_FW6_5(len, pins[0]); break;
#endif
case I_32_RN_2805_5: busPtr = new B_32_RN_2805_5(len, pins[0], (NeoBusChannel)channel); break;
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_2805_5: busPtr = new B_32_I0_2805_5(len, pins[0]); break;
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_2805_5: busPtr = new B_32_I1_2805_5(len, pins[0]); break;
#endif
#endif #endif
// for 2-wire: pins[1] is clk, pins[0] is dat. begin expects (len, clk, dat) // for 2-wire: pins[1] is clk, pins[0] is dat. begin expects (len, clk, dat)
case I_HS_DOT_3: busPtr = new B_HS_DOT_3(len, pins[1], pins[0]); break; case I_HS_DOT_3: busPtr = new B_HS_DOT_3(len, pins[1], pins[0]); break;
@ -578,6 +661,14 @@ class PolyBus {
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->Show(consistent); break; case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->Show(consistent); break;
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->Show(consistent); break; case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->Show(consistent); break;
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->Show(consistent); break; case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->Show(consistent); break;
case I_8266_U0_FW6_5: (static_cast<B_8266_U0_FW6_5*>(busPtr))->Show(consistent); break;
case I_8266_U1_FW6_5: (static_cast<B_8266_U1_FW6_5*>(busPtr))->Show(consistent); break;
case I_8266_DM_FW6_5: (static_cast<B_8266_DM_FW6_5*>(busPtr))->Show(consistent); break;
case I_8266_BB_FW6_5: (static_cast<B_8266_BB_FW6_5*>(busPtr))->Show(consistent); break;
case I_8266_U0_2805_5: (static_cast<B_8266_U0_2805_5*>(busPtr))->Show(consistent); break;
case I_8266_U1_2805_5: (static_cast<B_8266_U1_2805_5*>(busPtr))->Show(consistent); break;
case I_8266_DM_2805_5: (static_cast<B_8266_DM_2805_5*>(busPtr))->Show(consistent); break;
case I_8266_BB_2805_5: (static_cast<B_8266_BB_2805_5*>(busPtr))->Show(consistent); break;
#endif #endif
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Show(consistent); break; case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Show(consistent); break;
@ -587,7 +678,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->Show(consistent); break; case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->Show(consistent); break;
#endif #endif
// case I_32_BB_NEO_3: (static_cast<B_32_BB_NEO_3*>(busPtr))->Show(consistent); break;
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->Show(consistent); break; case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->Show(consistent); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->Show(consistent); break; case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->Show(consistent); break;
@ -595,7 +685,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->Show(consistent); break; case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->Show(consistent); break;
#endif #endif
// case I_32_BB_NEO_4: (static_cast<B_32_BB_NEO_4*>(busPtr))->Show(consistent); break;
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->Show(consistent); break; case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->Show(consistent); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->Show(consistent); break; case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->Show(consistent); break;
@ -603,7 +692,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Show(consistent); break; case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Show(consistent); break;
#endif #endif
// case I_32_BB_400_3: (static_cast<B_32_BB_400_3*>(busPtr))->Show(consistent); break;
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->Show(consistent); break; case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->Show(consistent); break;
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->Show(consistent); break; case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->Show(consistent); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
@ -621,7 +709,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->Show(consistent); break; case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->Show(consistent); break;
#endif #endif
// case I_32_BB_UCS_3: (static_cast<B_32_BB_NEO_3*>(busPtr))->Show(consistent); break;
case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->Show(consistent); break; case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->Show(consistent); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->Show(consistent); break; case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->Show(consistent); break;
@ -629,7 +716,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Show(consistent); break; case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Show(consistent); break;
#endif #endif
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->Show(consistent); break;
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->Show(consistent); break; case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->Show(consistent); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->Show(consistent); break; case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->Show(consistent); break;
@ -637,7 +723,20 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->Show(consistent); break; case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->Show(consistent); break;
#endif #endif
// case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->Show(consistent); break; case I_32_RN_FW6_5: (static_cast<B_32_RN_FW6_5*>(busPtr))->Show(consistent); break;
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_FW6_5: (static_cast<B_32_I0_FW6_5*>(busPtr))->Show(consistent); break;
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_FW6_5: (static_cast<B_32_I1_FW6_5*>(busPtr))->Show(consistent); break;
#endif
case I_32_RN_2805_5: (static_cast<B_32_RN_2805_5*>(busPtr))->Show(consistent); break;
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_2805_5: (static_cast<B_32_I0_2805_5*>(busPtr))->Show(consistent); break;
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_2805_5: (static_cast<B_32_I1_2805_5*>(busPtr))->Show(consistent); break;
#endif
#endif #endif
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->Show(consistent); break; case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->Show(consistent); break;
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->Show(consistent); break; case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->Show(consistent); break;
@ -687,6 +786,14 @@ class PolyBus {
case I_8266_U1_APA106_3: return (static_cast<B_8266_U1_APA106_3*>(busPtr))->CanShow(); break; case I_8266_U1_APA106_3: return (static_cast<B_8266_U1_APA106_3*>(busPtr))->CanShow(); break;
case I_8266_DM_APA106_3: return (static_cast<B_8266_DM_APA106_3*>(busPtr))->CanShow(); break; case I_8266_DM_APA106_3: return (static_cast<B_8266_DM_APA106_3*>(busPtr))->CanShow(); break;
case I_8266_BB_APA106_3: return (static_cast<B_8266_BB_APA106_3*>(busPtr))->CanShow(); break; case I_8266_BB_APA106_3: return (static_cast<B_8266_BB_APA106_3*>(busPtr))->CanShow(); break;
case I_8266_U0_FW6_5: return (static_cast<B_8266_U0_FW6_5*>(busPtr))->CanShow(); break;
case I_8266_U1_FW6_5: return (static_cast<B_8266_U1_FW6_5*>(busPtr))->CanShow(); break;
case I_8266_DM_FW6_5: return (static_cast<B_8266_DM_FW6_5*>(busPtr))->CanShow(); break;
case I_8266_BB_FW6_5: return (static_cast<B_8266_BB_FW6_5*>(busPtr))->CanShow(); break;
case I_8266_U0_2805_5: return (static_cast<B_8266_U0_2805_5*>(busPtr))->CanShow(); break;
case I_8266_U1_2805_5: return (static_cast<B_8266_U1_2805_5*>(busPtr))->CanShow(); break;
case I_8266_DM_2805_5: return (static_cast<B_8266_DM_2805_5*>(busPtr))->CanShow(); break;
case I_8266_BB_2805_5: return (static_cast<B_8266_BB_2805_5*>(busPtr))->CanShow(); break;
#endif #endif
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
case I_32_RN_NEO_3: return (static_cast<B_32_RN_NEO_3*>(busPtr))->CanShow(); break; case I_32_RN_NEO_3: return (static_cast<B_32_RN_NEO_3*>(busPtr))->CanShow(); break;
@ -696,7 +803,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_3: return (static_cast<B_32_I1_NEO_3*>(busPtr))->CanShow(); break; case I_32_I1_NEO_3: return (static_cast<B_32_I1_NEO_3*>(busPtr))->CanShow(); break;
#endif #endif
// case I_32_BB_NEO_3: return (static_cast<B_32_BB_NEO_3*>(busPtr))->CanShow(); break;
case I_32_RN_NEO_4: return (static_cast<B_32_RN_NEO_4*>(busPtr))->CanShow(); break; case I_32_RN_NEO_4: return (static_cast<B_32_RN_NEO_4*>(busPtr))->CanShow(); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_NEO_4: return (static_cast<B_32_I0_NEO_4*>(busPtr))->CanShow(); break; case I_32_I0_NEO_4: return (static_cast<B_32_I0_NEO_4*>(busPtr))->CanShow(); break;
@ -704,7 +810,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_4: return (static_cast<B_32_I1_NEO_4*>(busPtr))->CanShow(); break; case I_32_I1_NEO_4: return (static_cast<B_32_I1_NEO_4*>(busPtr))->CanShow(); break;
#endif #endif
// case I_32_BB_NEO_4: return (static_cast<B_32_BB_NEO_4*>(busPtr))->CanShow(); break;
case I_32_RN_400_3: return (static_cast<B_32_RN_400_3*>(busPtr))->CanShow(); break; case I_32_RN_400_3: return (static_cast<B_32_RN_400_3*>(busPtr))->CanShow(); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_400_3: return (static_cast<B_32_I0_400_3*>(busPtr))->CanShow(); break; case I_32_I0_400_3: return (static_cast<B_32_I0_400_3*>(busPtr))->CanShow(); break;
@ -712,7 +817,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_400_3: return (static_cast<B_32_I1_400_3*>(busPtr))->CanShow(); break; case I_32_I1_400_3: return (static_cast<B_32_I1_400_3*>(busPtr))->CanShow(); break;
#endif #endif
// case I_32_BB_400_3: return (static_cast<B_32_BB_400_3*>(busPtr))->CanShow(); break;
case I_32_RN_TM1_4: return (static_cast<B_32_RN_TM1_4*>(busPtr))->CanShow(); break; case I_32_RN_TM1_4: return (static_cast<B_32_RN_TM1_4*>(busPtr))->CanShow(); break;
case I_32_RN_TM2_3: return (static_cast<B_32_RN_TM2_3*>(busPtr))->CanShow(); break; case I_32_RN_TM2_3: return (static_cast<B_32_RN_TM2_3*>(busPtr))->CanShow(); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
@ -730,7 +834,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_3: return (static_cast<B_32_I1_UCS_3*>(busPtr))->CanShow(); break; case I_32_I1_UCS_3: return (static_cast<B_32_I1_UCS_3*>(busPtr))->CanShow(); break;
#endif #endif
// case I_32_BB_UCS_3: return (static_cast<B_32_BB_UCS_3*>(busPtr))->CanShow(); break;
case I_32_RN_UCS_4: return (static_cast<B_32_RN_UCS_4*>(busPtr))->CanShow(); break; case I_32_RN_UCS_4: return (static_cast<B_32_RN_UCS_4*>(busPtr))->CanShow(); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_UCS_4: return (static_cast<B_32_I0_UCS_4*>(busPtr))->CanShow(); break; case I_32_I0_UCS_4: return (static_cast<B_32_I0_UCS_4*>(busPtr))->CanShow(); break;
@ -738,7 +841,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_4: return (static_cast<B_32_I1_UCS_4*>(busPtr))->CanShow(); break; case I_32_I1_UCS_4: return (static_cast<B_32_I1_UCS_4*>(busPtr))->CanShow(); break;
#endif #endif
// case I_32_BB_UCS_4: return (static_cast<B_32_BB_UCS_4*>(busPtr))->CanShow(); break;
case I_32_RN_APA106_3: return (static_cast<B_32_RN_APA106_3*>(busPtr))->CanShow(); break; case I_32_RN_APA106_3: return (static_cast<B_32_RN_APA106_3*>(busPtr))->CanShow(); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_APA106_3: return (static_cast<B_32_I0_APA106_3*>(busPtr))->CanShow(); break; case I_32_I0_APA106_3: return (static_cast<B_32_I0_APA106_3*>(busPtr))->CanShow(); break;
@ -746,7 +848,20 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_APA106_3: return (static_cast<B_32_I1_APA106_3*>(busPtr))->CanShow(); break; case I_32_I1_APA106_3: return (static_cast<B_32_I1_APA106_3*>(busPtr))->CanShow(); break;
#endif #endif
// case I_32_BB_APA106_3: return (static_cast<B_32_BB_APA106_3*>(busPtr))->CanShow(); break; case I_32_RN_FW6_5: return (static_cast<B_32_RN_FW6_5*>(busPtr))->CanShow(); break;
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_FW6_5: return (static_cast<B_32_I0_FW6_5*>(busPtr))->CanShow(); break;
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_FW6_5: return (static_cast<B_32_I1_FW6_5*>(busPtr))->CanShow(); break;
#endif
case I_32_RN_2805_5: return (static_cast<B_32_RN_2805_5*>(busPtr))->CanShow(); break;
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_2805_5: return (static_cast<B_32_I0_2805_5*>(busPtr))->CanShow(); break;
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_2805_5: return (static_cast<B_32_I1_2805_5*>(busPtr))->CanShow(); break;
#endif
#endif #endif
case I_HS_DOT_3: return (static_cast<B_HS_DOT_3*>(busPtr))->CanShow(); break; case I_HS_DOT_3: return (static_cast<B_HS_DOT_3*>(busPtr))->CanShow(); break;
case I_SS_DOT_3: return (static_cast<B_SS_DOT_3*>(busPtr))->CanShow(); break; case I_SS_DOT_3: return (static_cast<B_SS_DOT_3*>(busPtr))->CanShow(); break;
@ -762,12 +877,13 @@ class PolyBus {
return true; return true;
} }
static void setPixelColor(void* busPtr, uint8_t busType, uint16_t pix, uint32_t c, uint8_t co) { static void setPixelColor(void* busPtr, uint8_t busType, uint16_t pix, uint32_t c, uint8_t co, uint16_t wwcw = 0) {
uint8_t r = c >> 16; uint8_t r = c >> 16;
uint8_t g = c >> 8; uint8_t g = c >> 8;
uint8_t b = c >> 0; uint8_t b = c >> 0;
uint8_t w = c >> 24; uint8_t w = c >> 24;
RgbwColor col; RgbwColor col;
uint8_t cctWW = wwcw & 0xFF, cctCW = (wwcw>>8) & 0xFF;
// reorder channels to selected order // reorder channels to selected order
switch (co & 0x0F) { switch (co & 0x0F) {
@ -821,6 +937,14 @@ class PolyBus {
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
case I_8266_U0_FW6_5: (static_cast<B_8266_U0_FW6_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
case I_8266_U1_FW6_5: (static_cast<B_8266_U1_FW6_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
case I_8266_DM_FW6_5: (static_cast<B_8266_DM_FW6_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
case I_8266_BB_FW6_5: (static_cast<B_8266_BB_FW6_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
case I_8266_U0_2805_5: (static_cast<B_8266_U0_2805_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
case I_8266_U1_2805_5: (static_cast<B_8266_U1_2805_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
case I_8266_DM_2805_5: (static_cast<B_8266_DM_2805_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
case I_8266_BB_2805_5: (static_cast<B_8266_BB_2805_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
#endif #endif
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
@ -830,7 +954,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
#endif #endif
// case I_32_BB_NEO_3: (static_cast<B_32_BB_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->SetPixelColor(pix, col); break; case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->SetPixelColor(pix, col); break; case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
@ -838,7 +961,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->SetPixelColor(pix, col); break; case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
#endif #endif
// case I_32_BB_NEO_4: (static_cast<B_32_BB_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
@ -846,7 +968,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
#endif #endif
// case I_32_BB_400_3: (static_cast<B_32_BB_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(colB)); break;
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->SetPixelColor(pix, col); break; case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
@ -864,7 +985,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->SetPixelColor(pix, Rgb48Color(RgbColor(col))); break; case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->SetPixelColor(pix, Rgb48Color(RgbColor(col))); break;
#endif #endif
// case I_32_BB_UCS_3: (static_cast<B_32_BB_UCS_3*>(busPtr))->SetPixelColor(pix, Rgb48Color(RgbColor(col))); break;
case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break; case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break; case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
@ -872,7 +992,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break; case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
#endif #endif
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
@ -880,7 +999,20 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
#endif #endif
// case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_32_RN_FW6_5: (static_cast<B_32_RN_FW6_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_FW6_5: (static_cast<B_32_I0_FW6_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_FW6_5: (static_cast<B_32_I1_FW6_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
#endif
case I_32_RN_2805_5: (static_cast<B_32_RN_2805_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_2805_5: (static_cast<B_32_I0_2805_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_2805_5: (static_cast<B_32_I1_2805_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
#endif
#endif #endif
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break; case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
@ -931,6 +1063,14 @@ class PolyBus {
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->SetLuminance(b); break; case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->SetLuminance(b); break;
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->SetLuminance(b); break; case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->SetLuminance(b); break;
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->SetLuminance(b); break; case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->SetLuminance(b); break;
case I_8266_U0_FW6_5: (static_cast<B_8266_U0_FW6_5*>(busPtr))->SetLuminance(b); break;
case I_8266_U1_FW6_5: (static_cast<B_8266_U1_FW6_5*>(busPtr))->SetLuminance(b); break;
case I_8266_DM_FW6_5: (static_cast<B_8266_DM_FW6_5*>(busPtr))->SetLuminance(b); break;
case I_8266_BB_FW6_5: (static_cast<B_8266_BB_FW6_5*>(busPtr))->SetLuminance(b); break;
case I_8266_U0_2805_5: (static_cast<B_8266_U0_2805_5*>(busPtr))->SetLuminance(b); break;
case I_8266_U1_2805_5: (static_cast<B_8266_U1_2805_5*>(busPtr))->SetLuminance(b); break;
case I_8266_DM_2805_5: (static_cast<B_8266_DM_2805_5*>(busPtr))->SetLuminance(b); break;
case I_8266_BB_2805_5: (static_cast<B_8266_BB_2805_5*>(busPtr))->SetLuminance(b); break;
#endif #endif
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetLuminance(b); break; case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetLuminance(b); break;
@ -940,7 +1080,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->SetLuminance(b); break; case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->SetLuminance(b); break;
#endif #endif
// case I_32_BB_NEO_3: (static_cast<B_32_BB_NEO_3*>(busPtr))->SetLuminance(b); break;
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->SetLuminance(b); break; case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->SetLuminance(b); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->SetLuminance(b); break; case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->SetLuminance(b); break;
@ -948,7 +1087,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->SetLuminance(b); break; case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->SetLuminance(b); break;
#endif #endif
// case I_32_BB_NEO_4: (static_cast<B_32_BB_NEO_4*>(busPtr))->SetLuminance(b); break;
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->SetLuminance(b); break; case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->SetLuminance(b); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->SetLuminance(b); break; case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->SetLuminance(b); break;
@ -956,7 +1094,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetLuminance(b); break; case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetLuminance(b); break;
#endif #endif
// case I_32_BB_400_3: (static_cast<B_32_BB_400_3*>(busPtr))->SetLuminance(b); break;
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->SetLuminance(b); break; case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->SetLuminance(b); break;
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->SetLuminance(b); break; case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->SetLuminance(b); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
@ -974,7 +1111,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->SetLuminance(b); break; case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->SetLuminance(b); break;
#endif #endif
// case I_32_BB_UCS_3: (static_cast<B_32_BB_UCS_3*>(busPtr))->SetLuminance(b); break;
case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->SetLuminance(b); break; case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->SetLuminance(b); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->SetLuminance(b); break; case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->SetLuminance(b); break;
@ -982,7 +1118,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetLuminance(b); break; case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetLuminance(b); break;
#endif #endif
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->SetLuminance(b); break;
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->SetLuminance(b); break; case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->SetLuminance(b); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->SetLuminance(b); break; case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->SetLuminance(b); break;
@ -990,7 +1125,20 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->SetLuminance(b); break; case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->SetLuminance(b); break;
#endif #endif
// case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->SetLuminance(b); break; case I_32_RN_FW6_5: (static_cast<B_32_RN_FW6_5*>(busPtr))->SetLuminance(b); break;
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_FW6_5: (static_cast<B_32_I0_FW6_5*>(busPtr))->SetLuminance(b); break;
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_FW6_5: (static_cast<B_32_I1_FW6_5*>(busPtr))->SetLuminance(b); break;
#endif
case I_32_RN_2805_5: (static_cast<B_32_RN_2805_5*>(busPtr))->SetLuminance(b); break;
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_2805_5: (static_cast<B_32_I0_2805_5*>(busPtr))->SetLuminance(b); break;
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_2805_5: (static_cast<B_32_I1_2805_5*>(busPtr))->SetLuminance(b); break;
#endif
#endif #endif
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetLuminance(b); break; case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetLuminance(b); break;
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetLuminance(b); break; case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetLuminance(b); break;
@ -1042,6 +1190,14 @@ class PolyBus {
case I_8266_U1_APA106_3: col = (static_cast<B_8266_U1_APA106_3*>(busPtr))->GetPixelColor(pix); break; case I_8266_U1_APA106_3: col = (static_cast<B_8266_U1_APA106_3*>(busPtr))->GetPixelColor(pix); break;
case I_8266_DM_APA106_3: col = (static_cast<B_8266_DM_APA106_3*>(busPtr))->GetPixelColor(pix); break; case I_8266_DM_APA106_3: col = (static_cast<B_8266_DM_APA106_3*>(busPtr))->GetPixelColor(pix); break;
case I_8266_BB_APA106_3: col = (static_cast<B_8266_BB_APA106_3*>(busPtr))->GetPixelColor(pix); break; case I_8266_BB_APA106_3: col = (static_cast<B_8266_BB_APA106_3*>(busPtr))->GetPixelColor(pix); break;
case I_8266_U0_FW6_5: { RgbwwColor c = (static_cast<B_8266_U0_FW6_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
case I_8266_U1_FW6_5: { RgbwwColor c = (static_cast<B_8266_U1_FW6_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
case I_8266_DM_FW6_5: { RgbwwColor c = (static_cast<B_8266_DM_FW6_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
case I_8266_BB_FW6_5: { RgbwwColor c = (static_cast<B_8266_BB_FW6_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
case I_8266_U0_2805_5: { RgbwwColor c = (static_cast<B_8266_U0_2805_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
case I_8266_U1_2805_5: { RgbwwColor c = (static_cast<B_8266_U1_2805_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
case I_8266_DM_2805_5: { RgbwwColor c = (static_cast<B_8266_DM_2805_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
case I_8266_BB_2805_5: { RgbwwColor c = (static_cast<B_8266_BB_2805_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
#endif #endif
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
case I_32_RN_NEO_3: col = (static_cast<B_32_RN_NEO_3*>(busPtr))->GetPixelColor(pix); break; case I_32_RN_NEO_3: col = (static_cast<B_32_RN_NEO_3*>(busPtr))->GetPixelColor(pix); break;
@ -1051,7 +1207,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_3: col = (static_cast<B_32_I1_NEO_3*>(busPtr))->GetPixelColor(pix); break; case I_32_I1_NEO_3: col = (static_cast<B_32_I1_NEO_3*>(busPtr))->GetPixelColor(pix); break;
#endif #endif
// case I_32_BB_NEO_3: col = (static_cast<B_32_BB_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_RN_NEO_4: col = (static_cast<B_32_RN_NEO_4*>(busPtr))->GetPixelColor(pix); break; case I_32_RN_NEO_4: col = (static_cast<B_32_RN_NEO_4*>(busPtr))->GetPixelColor(pix); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_NEO_4: col = (static_cast<B_32_I0_NEO_4*>(busPtr))->GetPixelColor(pix); break; case I_32_I0_NEO_4: col = (static_cast<B_32_I0_NEO_4*>(busPtr))->GetPixelColor(pix); break;
@ -1059,7 +1214,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_4: col = (static_cast<B_32_I1_NEO_4*>(busPtr))->GetPixelColor(pix); break; case I_32_I1_NEO_4: col = (static_cast<B_32_I1_NEO_4*>(busPtr))->GetPixelColor(pix); break;
#endif #endif
// case I_32_BB_NEO_4: col = (static_cast<B_32_BB_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_RN_400_3: col = (static_cast<B_32_RN_400_3*>(busPtr))->GetPixelColor(pix); break; case I_32_RN_400_3: col = (static_cast<B_32_RN_400_3*>(busPtr))->GetPixelColor(pix); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_400_3: col = (static_cast<B_32_I0_400_3*>(busPtr))->GetPixelColor(pix); break; case I_32_I0_400_3: col = (static_cast<B_32_I0_400_3*>(busPtr))->GetPixelColor(pix); break;
@ -1067,7 +1221,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_400_3: col = (static_cast<B_32_I1_400_3*>(busPtr))->GetPixelColor(pix); break; case I_32_I1_400_3: col = (static_cast<B_32_I1_400_3*>(busPtr))->GetPixelColor(pix); break;
#endif #endif
// case I_32_BB_400_3: col = (static_cast<B_32_BB_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_RN_TM1_4: col = (static_cast<B_32_RN_TM1_4*>(busPtr))->GetPixelColor(pix); break; case I_32_RN_TM1_4: col = (static_cast<B_32_RN_TM1_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_RN_TM2_3: col = (static_cast<B_32_RN_TM2_3*>(busPtr))->GetPixelColor(pix); break; case I_32_RN_TM2_3: col = (static_cast<B_32_RN_TM2_3*>(busPtr))->GetPixelColor(pix); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
@ -1085,7 +1238,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_3: { Rgb48Color c = (static_cast<B_32_I1_UCS_3*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,0); } break; case I_32_I1_UCS_3: { Rgb48Color c = (static_cast<B_32_I1_UCS_3*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,0); } break;
#endif #endif
// case I_32_BB_UCS_3: col = (static_cast<B_32_BB_UCS_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_RN_UCS_4: { Rgbw64Color c = (static_cast<B_32_RN_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break; case I_32_RN_UCS_4: { Rgbw64Color c = (static_cast<B_32_RN_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_UCS_4: { Rgbw64Color c = (static_cast<B_32_I0_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break; case I_32_I0_UCS_4: { Rgbw64Color c = (static_cast<B_32_I0_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
@ -1093,7 +1245,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_4: { Rgbw64Color c = (static_cast<B_32_I1_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break; case I_32_I1_UCS_4: { Rgbw64Color c = (static_cast<B_32_I1_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
#endif #endif
// case I_32_BB_UCS_4: col = (static_cast<B_32_BB_UCS_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_RN_APA106_3: col = (static_cast<B_32_RN_APA106_3*>(busPtr))->GetPixelColor(pix); break; case I_32_RN_APA106_3: col = (static_cast<B_32_RN_APA106_3*>(busPtr))->GetPixelColor(pix); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_APA106_3: col = (static_cast<B_32_I0_APA106_3*>(busPtr))->GetPixelColor(pix); break; case I_32_I0_APA106_3: col = (static_cast<B_32_I0_APA106_3*>(busPtr))->GetPixelColor(pix); break;
@ -1101,7 +1252,20 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_APA106_3: col = (static_cast<B_32_I1_APA106_3*>(busPtr))->GetPixelColor(pix); break; case I_32_I1_APA106_3: col = (static_cast<B_32_I1_APA106_3*>(busPtr))->GetPixelColor(pix); break;
#endif #endif
// case I_32_BB_APA106_3: col = (static_cast<B_32_BB_APA106_3*>(busPtr))->GetPixelColor(pix); break; case I_32_RN_FW6_5: { RgbwwColor c = (static_cast<B_32_RN_FW6_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_FW6_5: { RgbwwColor c = (static_cast<B_32_I0_FW6_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_FW6_5: { RgbwwColor c = (static_cast<B_32_I1_FW6_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
#endif
case I_32_RN_2805_5: { RgbwwColor c = (static_cast<B_32_RN_2805_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_2805_5: { RgbwwColor c = (static_cast<B_32_I0_2805_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_2805_5: { RgbwwColor c = (static_cast<B_32_I1_2805_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
#endif
#endif #endif
case I_HS_DOT_3: col = (static_cast<B_HS_DOT_3*>(busPtr))->GetPixelColor(pix); break; case I_HS_DOT_3: col = (static_cast<B_HS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
case I_SS_DOT_3: col = (static_cast<B_SS_DOT_3*>(busPtr))->GetPixelColor(pix); break; case I_SS_DOT_3: col = (static_cast<B_SS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
@ -1171,6 +1335,14 @@ class PolyBus {
case I_8266_U1_APA106_3: delete (static_cast<B_8266_U1_APA106_3*>(busPtr)); break; case I_8266_U1_APA106_3: delete (static_cast<B_8266_U1_APA106_3*>(busPtr)); break;
case I_8266_DM_APA106_3: delete (static_cast<B_8266_DM_APA106_3*>(busPtr)); break; case I_8266_DM_APA106_3: delete (static_cast<B_8266_DM_APA106_3*>(busPtr)); break;
case I_8266_BB_APA106_3: delete (static_cast<B_8266_BB_APA106_3*>(busPtr)); break; case I_8266_BB_APA106_3: delete (static_cast<B_8266_BB_APA106_3*>(busPtr)); break;
case I_8266_U0_FW6_5: delete (static_cast<B_8266_U0_FW6_5*>(busPtr)); break;
case I_8266_U1_FW6_5: delete (static_cast<B_8266_U1_FW6_5*>(busPtr)); break;
case I_8266_DM_FW6_5: delete (static_cast<B_8266_DM_FW6_5*>(busPtr)); break;
case I_8266_BB_FW6_5: delete (static_cast<B_8266_BB_FW6_5*>(busPtr)); break;
case I_8266_U0_2805_5: delete (static_cast<B_8266_U0_2805_5*>(busPtr)); break;
case I_8266_U1_2805_5: delete (static_cast<B_8266_U1_2805_5*>(busPtr)); break;
case I_8266_DM_2805_5: delete (static_cast<B_8266_DM_2805_5*>(busPtr)); break;
case I_8266_BB_2805_5: delete (static_cast<B_8266_BB_2805_5*>(busPtr)); break;
#endif #endif
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
case I_32_RN_NEO_3: delete (static_cast<B_32_RN_NEO_3*>(busPtr)); break; case I_32_RN_NEO_3: delete (static_cast<B_32_RN_NEO_3*>(busPtr)); break;
@ -1180,7 +1352,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_3: delete (static_cast<B_32_I1_NEO_3*>(busPtr)); break; case I_32_I1_NEO_3: delete (static_cast<B_32_I1_NEO_3*>(busPtr)); break;
#endif #endif
// case I_32_BB_NEO_3: delete (static_cast<B_32_BB_NEO_3*>(busPtr)); break;
case I_32_RN_NEO_4: delete (static_cast<B_32_RN_NEO_4*>(busPtr)); break; case I_32_RN_NEO_4: delete (static_cast<B_32_RN_NEO_4*>(busPtr)); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_NEO_4: delete (static_cast<B_32_I0_NEO_4*>(busPtr)); break; case I_32_I0_NEO_4: delete (static_cast<B_32_I0_NEO_4*>(busPtr)); break;
@ -1188,7 +1359,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_NEO_4: delete (static_cast<B_32_I1_NEO_4*>(busPtr)); break; case I_32_I1_NEO_4: delete (static_cast<B_32_I1_NEO_4*>(busPtr)); break;
#endif #endif
// case I_32_BB_NEO_4: delete (static_cast<B_32_BB_NEO_4*>(busPtr)); break;
case I_32_RN_400_3: delete (static_cast<B_32_RN_400_3*>(busPtr)); break; case I_32_RN_400_3: delete (static_cast<B_32_RN_400_3*>(busPtr)); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_400_3: delete (static_cast<B_32_I0_400_3*>(busPtr)); break; case I_32_I0_400_3: delete (static_cast<B_32_I0_400_3*>(busPtr)); break;
@ -1196,7 +1366,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_400_3: delete (static_cast<B_32_I1_400_3*>(busPtr)); break; case I_32_I1_400_3: delete (static_cast<B_32_I1_400_3*>(busPtr)); break;
#endif #endif
// case I_32_BB_400_3: delete (static_cast<B_32_BB_400_3*>(busPtr)); break;
case I_32_RN_TM1_4: delete (static_cast<B_32_RN_TM1_4*>(busPtr)); break; case I_32_RN_TM1_4: delete (static_cast<B_32_RN_TM1_4*>(busPtr)); break;
case I_32_RN_TM2_3: delete (static_cast<B_32_RN_TM2_3*>(busPtr)); break; case I_32_RN_TM2_3: delete (static_cast<B_32_RN_TM2_3*>(busPtr)); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
@ -1214,7 +1383,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_3: delete (static_cast<B_32_I1_UCS_3*>(busPtr)); break; case I_32_I1_UCS_3: delete (static_cast<B_32_I1_UCS_3*>(busPtr)); break;
#endif #endif
// case I_32_BB_UCS_3: delete (static_cast<B_32_BB_UCS_3*>(busPtr)); break;
case I_32_RN_UCS_4: delete (static_cast<B_32_RN_UCS_4*>(busPtr)); break; case I_32_RN_UCS_4: delete (static_cast<B_32_RN_UCS_4*>(busPtr)); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_UCS_4: delete (static_cast<B_32_I0_UCS_4*>(busPtr)); break; case I_32_I0_UCS_4: delete (static_cast<B_32_I0_UCS_4*>(busPtr)); break;
@ -1222,7 +1390,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_4: delete (static_cast<B_32_I1_UCS_4*>(busPtr)); break; case I_32_I1_UCS_4: delete (static_cast<B_32_I1_UCS_4*>(busPtr)); break;
#endif #endif
// case I_32_BB_UCS_4: delete (static_cast<B_32_BB_UCS_4*>(busPtr)); break;
case I_32_RN_APA106_3: delete (static_cast<B_32_RN_APA106_3*>(busPtr)); break; case I_32_RN_APA106_3: delete (static_cast<B_32_RN_APA106_3*>(busPtr)); break;
#ifndef WLED_NO_I2S0_PIXELBUS #ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_APA106_3: delete (static_cast<B_32_I0_APA106_3*>(busPtr)); break; case I_32_I0_APA106_3: delete (static_cast<B_32_I0_APA106_3*>(busPtr)); break;
@ -1230,7 +1397,20 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS #ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_APA106_3: delete (static_cast<B_32_I1_APA106_3*>(busPtr)); break; case I_32_I1_APA106_3: delete (static_cast<B_32_I1_APA106_3*>(busPtr)); break;
#endif #endif
// case I_32_BB_APA106_3: delete (static_cast<B_32_BB_APA106_3*>(busPtr)); break; case I_32_RN_FW6_5: delete (static_cast<B_32_RN_FW6_5*>(busPtr)); break;
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_FW6_5: delete (static_cast<B_32_I0_FW6_5*>(busPtr)); break;
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_FW6_5: delete (static_cast<B_32_I1_FW6_5*>(busPtr)); break;
#endif
case I_32_RN_2805_5: delete (static_cast<B_32_RN_2805_5*>(busPtr)); break;
#ifndef WLED_NO_I2S0_PIXELBUS
case I_32_I0_2805_5: delete (static_cast<B_32_I0_2805_5*>(busPtr)); break;
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_2805_5: delete (static_cast<B_32_I1_2805_5*>(busPtr)); break;
#endif
#endif #endif
case I_HS_DOT_3: delete (static_cast<B_HS_DOT_3*>(busPtr)); break; case I_HS_DOT_3: delete (static_cast<B_HS_DOT_3*>(busPtr)); break;
case I_SS_DOT_3: delete (static_cast<B_SS_DOT_3*>(busPtr)); break; case I_SS_DOT_3: delete (static_cast<B_SS_DOT_3*>(busPtr)); break;
@ -1292,13 +1472,17 @@ class PolyBus {
return I_8266_U0_UCS_4 + offset; return I_8266_U0_UCS_4 + offset;
case TYPE_APA106: case TYPE_APA106:
return I_8266_U0_APA106_3 + offset; return I_8266_U0_APA106_3 + offset;
case TYPE_FW1906:
return I_8266_U0_FW6_5 + offset;
case TYPE_WS2805:
return I_8266_U0_2805_5 + offset;
} }
#else //ESP32 #else //ESP32
uint8_t offset = 0; //0 = RMT (num 0-7) 8 = I2S0 9 = I2S1 uint8_t offset = 0; // 0 = RMT (num 1-8), 1 = I2S0 (used by Audioreactive), 2 = I2S1
#if defined(CONFIG_IDF_TARGET_ESP32S2) #if defined(CONFIG_IDF_TARGET_ESP32S2)
// ESP32-S2 only has 4 RMT channels // ESP32-S2 only has 4 RMT channels
if (num > 4) return I_NONE; if (num > 4) return I_NONE;
if (num > 3) offset = 1; // only one I2S if (num > 3) offset = 1; // only one I2S (use last to allow Audioreactive)
#elif defined(CONFIG_IDF_TARGET_ESP32C3) #elif defined(CONFIG_IDF_TARGET_ESP32C3)
// On ESP32-C3 only the first 2 RMT channels are usable for transmitting // On ESP32-C3 only the first 2 RMT channels are usable for transmitting
if (num > 1) return I_NONE; if (num > 1) return I_NONE;
@ -1310,7 +1494,8 @@ class PolyBus {
#else #else
// standard ESP32 has 8 RMT and 2 I2S channels // standard ESP32 has 8 RMT and 2 I2S channels
if (num > 9) return I_NONE; if (num > 9) return I_NONE;
if (num > 7) offset = num -7; if (num > 8) offset = 1;
if (num == 0) offset = 2; // prefer I2S1 for 1st bus (less flickering but more RAM needed)
#endif #endif
switch (busType) { switch (busType) {
case TYPE_WS2812_1CH_X3: case TYPE_WS2812_1CH_X3:
@ -1332,11 +1517,14 @@ class PolyBus {
return I_32_RN_UCS_4 + offset; return I_32_RN_UCS_4 + offset;
case TYPE_APA106: case TYPE_APA106:
return I_32_RN_APA106_3 + offset; return I_32_RN_APA106_3 + offset;
case TYPE_FW1906:
return I_32_RN_FW6_5 + offset;
case TYPE_WS2805:
return I_32_RN_2805_5 + offset;
} }
#endif #endif
} }
return I_NONE; return I_NONE;
} }
}; };
#endif
#endif

Wyświetl plik

@ -96,9 +96,13 @@ bool isButtonPressed(uint8_t i)
case BTN_TYPE_TOUCH: case BTN_TYPE_TOUCH:
case BTN_TYPE_TOUCH_SWITCH: case BTN_TYPE_TOUCH_SWITCH:
#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
if (digitalPinToTouchChannel(btnPin[i]) >= 0 && touchRead(pin) <= touchThreshold) return true; #ifdef SOC_TOUCH_VERSION_2 //ESP32 S2 and S3 provide a function to check touch state (state is updated in interrupt)
if (touchInterruptGetLastStatus(pin)) return true;
#else
if (digitalPinToTouchChannel(btnPin[i]) >= 0 && touchRead(pin) <= touchThreshold) return true;
#endif
#endif #endif
break; break;
} }
return false; return false;
} }
@ -403,3 +407,8 @@ void handleIO()
offMode = true; offMode = true;
} }
} }
void IRAM_ATTR touchButtonISR()
{
// used for ESP32 S2 and S3: nothing to do, ISR is just used to update registers of HAL driver
}

Wyświetl plik

@ -110,6 +110,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
Bus::setGlobalAWMode(hw_led[F("rgbwm")] | AW_GLOBAL_DISABLED); Bus::setGlobalAWMode(hw_led[F("rgbwm")] | AW_GLOBAL_DISABLED);
CJSON(correctWB, hw_led["cct"]); CJSON(correctWB, hw_led["cct"]);
CJSON(cctFromRgb, hw_led[F("cr")]); CJSON(cctFromRgb, hw_led[F("cr")]);
CJSON(cctICused, hw_led[F("ic")]);
CJSON(strip.cctBlending, hw_led[F("cb")]); CJSON(strip.cctBlending, hw_led[F("cb")]);
Bus::setCCTBlend(strip.cctBlending); Bus::setCCTBlend(strip.cctBlending);
strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS
@ -185,7 +186,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
uint8_t maPerLed = elm[F("ledma")] | 55; uint8_t maPerLed = elm[F("ledma")] | 55;
uint16_t maMax = elm[F("maxpwr")] | (ablMilliampsMax * length) / total; // rough (incorrect?) per strip ABL calculation when no config exists uint16_t maMax = elm[F("maxpwr")] | (ablMilliampsMax * length) / total; // rough (incorrect?) per strip ABL calculation when no config exists
// To disable brightness limiter we either set output max current to 0 or single LED current to 0 (we choose output max current) // To disable brightness limiter we either set output max current to 0 or single LED current to 0 (we choose output max current)
if ((ledType > TYPE_TM1814 && ledType < TYPE_WS2801) || ledType >= TYPE_NET_DDP_RGB) { // analog and virtual if (IS_PWM(ledType) || IS_ONOFF(ledType) || IS_VIRTUAL(ledType)) { // analog and virtual
maPerLed = 0; maPerLed = 0;
maMax = 0; maMax = 0;
} }
@ -228,6 +229,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
// read multiple button configuration // read multiple button configuration
JsonObject btn_obj = hw["btn"]; JsonObject btn_obj = hw["btn"];
CJSON(touchThreshold, btn_obj[F("tt")]);
bool pull = btn_obj[F("pull")] | (!disablePullUp); // if true, pullup is enabled bool pull = btn_obj[F("pull")] | (!disablePullUp); // if true, pullup is enabled
disablePullUp = !pull; disablePullUp = !pull;
JsonArray hw_btn_ins = btn_obj["ins"]; JsonArray hw_btn_ins = btn_obj["ins"];
@ -252,6 +254,13 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
btnPin[s] = -1; btnPin[s] = -1;
pinManager.deallocatePin(pin,PinOwner::Button); pinManager.deallocatePin(pin,PinOwner::Button);
} }
//if touch pin, enable the touch interrupt on ESP32 S2 & S3
#ifdef SOC_TOUCH_VERSION_2 // ESP32 S2 and S3 have a fucntion to check touch state but need to attach an interrupt to do so
if ((buttonType[s] == BTN_TYPE_TOUCH || buttonType[s] == BTN_TYPE_TOUCH_SWITCH))
{
touchAttachInterrupt(btnPin[s], touchButtonISR, 256 + (touchThreshold << 4)); // threshold on Touch V2 is much higher (1500 is a value given by Espressif example, I measured changes of over 5000)
}
#endif
else else
#endif #endif
{ {
@ -308,7 +317,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
} }
} }
} }
CJSON(touchThreshold,btn_obj[F("tt")]);
CJSON(buttonPublishMqtt,btn_obj["mqtt"]); CJSON(buttonPublishMqtt,btn_obj["mqtt"]);
#ifndef WLED_DISABLE_INFRARED #ifndef WLED_DISABLE_INFRARED
@ -632,12 +641,12 @@ static const char s_cfg_json[] PROGMEM = "/cfg.json";
void deserializeConfigFromFS() { void deserializeConfigFromFS() {
bool success = deserializeConfigSec(); bool success = deserializeConfigSec();
#ifdef WLED_ADD_EEPROM_SUPPORT
if (!success) { //if file does not exist, try reading from EEPROM if (!success) { //if file does not exist, try reading from EEPROM
#ifdef WLED_ADD_EEPROM_SUPPORT
deEEPSettings(); deEEPSettings();
return; return;
#endif
} }
#endif
if (!requestJSONBufferLock(1)) return; if (!requestJSONBufferLock(1)) return;
@ -767,6 +776,7 @@ void serializeConfig() {
hw_led[F("ledma")] = 0; // no longer used hw_led[F("ledma")] = 0; // no longer used
hw_led["cct"] = correctWB; hw_led["cct"] = correctWB;
hw_led[F("cr")] = cctFromRgb; hw_led[F("cr")] = cctFromRgb;
hw_led[F("ic")] = cctICused;
hw_led[F("cb")] = strip.cctBlending; hw_led[F("cb")] = strip.cctBlending;
hw_led["fps"] = strip.getTargetFps(); hw_led["fps"] = strip.getTargetFps();
hw_led[F("rgbwm")] = Bus::getGlobalAWMode(); // global auto white mode override hw_led[F("rgbwm")] = Bus::getGlobalAWMode(); // global auto white mode override

Wyświetl plik

@ -65,24 +65,30 @@ uint32_t color_add(uint32_t c1, uint32_t c2, bool fast)
* fades color toward black * fades color toward black
* 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
*/ */
uint32_t color_fade(uint32_t c1, uint8_t amount, bool video) uint32_t color_fade(uint32_t c1, uint8_t amount, bool video)
{ {
uint8_t r = R(c1); uint32_t scaledcolor; // color order is: W R G B from MSB to LSB
uint8_t g = G(c1); uint32_t r = R(c1);
uint8_t b = B(c1); uint32_t g = G(c1);
uint8_t w = W(c1); uint32_t b = B(c1);
if (video) { uint32_t w = W(c1);
r = scale8_video(r, amount); if (video) {
g = scale8_video(g, amount); uint32_t scale = amount; // 32bit for faster calculation
b = scale8_video(b, amount); scaledcolor = (((r * scale) >> 8) << 16) + ((r && scale) ? 1 : 0);
w = scale8_video(w, amount); scaledcolor |= (((g * scale) >> 8) << 8) + ((g && scale) ? 1 : 0);
} else { scaledcolor |= ((b * scale) >> 8) + ((b && scale) ? 1 : 0);
r = scale8(r, amount); scaledcolor |= (((w * scale) >> 8) << 24) + ((w && scale) ? 1 : 0);
g = scale8(g, amount); return scaledcolor;
b = scale8(b, amount); }
w = scale8(w, amount); else {
uint32_t scale = 1 + amount;
scaledcolor = ((r * scale) >> 8) << 16;
scaledcolor |= ((g * scale) >> 8) << 8;
scaledcolor |= (b * scale) >> 8;
scaledcolor |= ((w * scale) >> 8) << 24;
return scaledcolor;
} }
return RGBW32(r, g, b, w);
} }
void setRandomColor(byte* rgb) void setRandomColor(byte* rgb)

Wyświetl plik

@ -21,7 +21,7 @@
#define WLED_BRAND "WLED" #define WLED_BRAND "WLED"
#endif #endif
#ifndef WLED_PRODUCT_NAME #ifndef WLED_PRODUCT_NAME
#define WLED_PRODUCT_NAME "FOSS" #define WLED_PRODUCT_NAME "DIY"
#endif #endif
//Defaults //Defaults
@ -53,24 +53,16 @@
#define WLED_MAX_BUSSES 3 // will allow 2 digital & 1 analog (or the other way around) #define WLED_MAX_BUSSES 3 // will allow 2 digital & 1 analog (or the other way around)
#define WLED_MIN_VIRTUAL_BUSSES 3 #define WLED_MIN_VIRTUAL_BUSSES 3
#elif defined(CONFIG_IDF_TARGET_ESP32S2) // 4 RMT, 8 LEDC, only has 1 I2S bus, supported in NPB #elif defined(CONFIG_IDF_TARGET_ESP32S2) // 4 RMT, 8 LEDC, only has 1 I2S bus, supported in NPB
#if defined(USERMOD_AUDIOREACTIVE) // requested by @softhack007 https://github.com/blazoncek/WLED/issues/33 // the 5th bus (I2S) will prevent Audioreactive usermod from functioning (it is last used though)
#define WLED_MAX_BUSSES 6 // will allow 4 digital & 2 analog #define WLED_MAX_BUSSES 7 // will allow 5 digital & 2 analog
#define WLED_MIN_VIRTUAL_BUSSES 4 #define WLED_MIN_VIRTUAL_BUSSES 3
#else
#define WLED_MAX_BUSSES 7 // will allow 5 digital & 2 analog
#define WLED_MIN_VIRTUAL_BUSSES 3
#endif
#elif defined(CONFIG_IDF_TARGET_ESP32S3) // 4 RMT, 8 LEDC, has 2 I2S but NPB does not support them ATM #elif defined(CONFIG_IDF_TARGET_ESP32S3) // 4 RMT, 8 LEDC, has 2 I2S but NPB does not support them ATM
#define WLED_MAX_BUSSES 6 // will allow 4 digital & 2 analog #define WLED_MAX_BUSSES 6 // will allow 4 digital & 2 analog
#define WLED_MIN_VIRTUAL_BUSSES 4 #define WLED_MIN_VIRTUAL_BUSSES 4
#else #else
#if defined(USERMOD_AUDIOREACTIVE) // requested by @softhack007 https://github.com/blazoncek/WLED/issues/33 // the 10th digital bus (I2S0) will prevent Audioreactive usermod from functioning (it is last used though)
#define WLED_MAX_BUSSES 8 #define WLED_MAX_BUSSES 10
#define WLED_MIN_VIRTUAL_BUSSES 2 #define WLED_MIN_VIRTUAL_BUSSES 0
#else
#define WLED_MAX_BUSSES 10
#define WLED_MIN_VIRTUAL_BUSSES 0
#endif
#endif #endif
#endif #endif
#else #else
@ -181,6 +173,7 @@
#define USERMOD_ID_ANIMARTRIX 45 //Usermod "usermod_v2_animartrix.h" #define USERMOD_ID_ANIMARTRIX 45 //Usermod "usermod_v2_animartrix.h"
#define USERMOD_ID_HTTP_PULL_LIGHT_CONTROL 46 //usermod "usermod_v2_HttpPullLightControl.h" #define USERMOD_ID_HTTP_PULL_LIGHT_CONTROL 46 //usermod "usermod_v2_HttpPullLightControl.h"
#define USERMOD_ID_TETRISAI 47 //Usermod "usermod_v2_tetris.h" #define USERMOD_ID_TETRISAI 47 //Usermod "usermod_v2_tetris.h"
#define USERMOD_ID_MAX17048 48 //Usermod "usermod_max17048.h"
//Access point behavior //Access point behavior
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot #define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
@ -270,9 +263,11 @@
#define TYPE_TM1829 25 #define TYPE_TM1829 25
#define TYPE_UCS8903 26 #define TYPE_UCS8903 26
#define TYPE_APA106 27 #define TYPE_APA106 27
#define TYPE_FW1906 28 //RGB + CW + WW + unused channel (6 channels per IC)
#define TYPE_UCS8904 29 //first RGBW digital type (hardcoded in busmanager.cpp, memUsage()) #define TYPE_UCS8904 29 //first RGBW digital type (hardcoded in busmanager.cpp, memUsage())
#define TYPE_SK6812_RGBW 30 #define TYPE_SK6812_RGBW 30
#define TYPE_TM1814 31 #define TYPE_TM1814 31
#define TYPE_WS2805 32 //RGB + WW + CW
//"Analog" types (40-47) //"Analog" types (40-47)
#define TYPE_ONOFF 40 //binary output (relays etc.; NOT PWM) #define TYPE_ONOFF 40 //binary output (relays etc.; NOT PWM)
#define TYPE_ANALOG_1CH 41 //single channel PWM. Uses value of brightest RGBW channel #define TYPE_ANALOG_1CH 41 //single channel PWM. Uses value of brightest RGBW channel
@ -297,6 +292,7 @@
#define IS_DIGITAL(t) (((t) > 15 && (t) < 40) || ((t) > 47 && (t) < 64)) //digital are 16-39 and 48-63 #define IS_DIGITAL(t) (((t) > 15 && (t) < 40) || ((t) > 47 && (t) < 64)) //digital are 16-39 and 48-63
#define IS_2PIN(t) ((t) > 47 && (t) < 64) #define IS_2PIN(t) ((t) > 47 && (t) < 64)
#define IS_16BIT(t) ((t) == TYPE_UCS8903 || (t) == TYPE_UCS8904) #define IS_16BIT(t) ((t) == TYPE_UCS8903 || (t) == TYPE_UCS8904)
#define IS_ONOFF(t) ((t) == 40)
#define IS_PWM(t) ((t) > 40 && (t) < 46) //does not include on/Off type #define IS_PWM(t) ((t) > 40 && (t) < 46) //does not include on/Off type
#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_VIRTUAL(t) ((t) >= 80 && (t) < 96) //this was a poor choice a better would be 96-111 #define IS_VIRTUAL(t) ((t) >= 80 && (t) < 96) //this was a poor choice a better would be 96-111
@ -374,6 +370,7 @@
//Playlist option byte //Playlist option byte
#define PL_OPTION_SHUFFLE 0x01 #define PL_OPTION_SHUFFLE 0x01
#define PL_OPTION_RESTORE 0x02
// Segment capability byte // Segment capability byte
#define SEG_CAPABILITY_RGB 0x01 #define SEG_CAPABILITY_RGB 0x01
@ -511,10 +508,10 @@
//this is merely a default now and can be changed at runtime //this is merely a default now and can be changed at runtime
#ifndef LEDPIN #ifndef LEDPIN
#if defined(ESP8266) || (defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32_PICO) #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) //|| (defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)) || defined(ARDUINO_ESP32_PICO)
#define LEDPIN 2 // GPIO2 (D4) on Wemos D1 mini compatible boards, and on boards where GPIO16 is not available #define LEDPIN 2 // GPIO2 (D4) on Wemos D1 mini compatible boards, safe to use on any board
#else #else
#define LEDPIN 16 // aligns with GPIO2 (D4) on Wemos D1 mini32 compatible boards #define LEDPIN 16 // aligns with GPIO2 (D4) on Wemos D1 mini32 compatible boards (if it is unusable it will be reassigned in WS2812FX::finalizeInit())
#endif #endif
#endif #endif

Wyświetl plik

@ -358,7 +358,7 @@ button {
#putil, #segutil, #segutil2 { #putil, #segutil, #segutil2 {
min-height: 42px; min-height: 42px;
margin: 13px auto 0; margin: 0 auto;
} }
#segutil .segin { #segutil .segin {

Wyświetl plik

@ -694,8 +694,6 @@ function parseInfo(i) {
function populateInfo(i) function populateInfo(i)
{ {
var cn=""; var cn="";
var heap = i.freeheap/1024;
heap = heap.toFixed(1);
var pwr = i.leds.pwr; var pwr = i.leds.pwr;
var pwru = "Not calculated"; var pwru = "Not calculated";
if (pwr > 1000) {pwr /= 1000; pwr = pwr.toFixed((pwr > 10) ? 0 : 1); pwru = pwr + " A";} if (pwr > 1000) {pwr /= 1000; pwr = pwr.toFixed((pwr > 10) ? 0 : 1); pwru = pwr + " A";}
@ -720,11 +718,13 @@ ${inforow("Build",i.vid)}
${inforow("Signal strength",i.wifi.signal +"% ("+ i.wifi.rssi, " dBm)")} ${inforow("Signal strength",i.wifi.signal +"% ("+ i.wifi.rssi, " dBm)")}
${inforow("Uptime",getRuntimeStr(i.uptime))} ${inforow("Uptime",getRuntimeStr(i.uptime))}
${inforow("Time",i.time)} ${inforow("Time",i.time)}
${inforow("Free heap",heap," kB")} ${inforow("Free heap",(i.freeheap/1024).toFixed(1)," kB")}
${i.psram?inforow("Free PSRAM",(i.psram/1024).toFixed(1)," kB"):""} ${i.psram?inforow("Free PSRAM",(i.psram/1024).toFixed(1)," kB"):""}
${inforow("Estimated current",pwru)} ${inforow("Estimated current",pwru)}
${inforow("Average FPS",i.leds.fps)} ${inforow("Average FPS",i.leds.fps)}
${inforow("MAC address",i.mac)} ${inforow("MAC address",i.mac)}
${inforow("CPU clock",i.clock," MHz")}
${inforow("Flash size",i.flash," MB")}
${inforow("Filesystem",i.fs.u + "/" + i.fs.t + " kB (" +Math.round(i.fs.u*100/i.fs.t) + "%)")} ${inforow("Filesystem",i.fs.u + "/" + i.fs.t + " kB (" +Math.round(i.fs.u*100/i.fs.t) + "%)")}
${inforow("Environment",i.arch + " " + i.core + " (" + i.lwip + ")")} ${inforow("Environment",i.arch + " " + i.core + " (" + i.lwip + ")")}
</table>`; </table>`;
@ -863,14 +863,11 @@ function populateSegments(s)
gId("segcont").classList.remove("hide"); gId("segcont").classList.remove("hide");
let noNewSegs = (lowestUnused >= maxSeg); let noNewSegs = (lowestUnused >= maxSeg);
resetUtil(noNewSegs); resetUtil(noNewSegs);
if (gId('selall')) gId('selall').checked = true;
for (var i = 0; i <= lSeg; i++) { for (var i = 0; i <= lSeg; i++) {
if (!gId(`seg${i}`)) continue; if (!gId(`seg${i}`)) continue;
updateLen(i); updateLen(i);
updateTrail(gId(`seg${i}bri`)); updateTrail(gId(`seg${i}bri`));
gId(`segr${i}`).classList.add("hide"); gId(`segr${i}`).classList.add("hide");
//if (i<lSeg) gId(`segd${i}`).classList.add("hide"); // hide delete button for all but last
if (!gId(`seg${i}sel`).checked && gId('selall')) gId('selall').checked = false; // uncheck if at least one is unselected.
} }
if (segCount < 2) { if (segCount < 2) {
gId(`segd${lSeg}`).classList.add("hide"); // hide delete if only one segment gId(`segd${lSeg}`).classList.add("hide"); // hide delete if only one segment
@ -1462,8 +1459,6 @@ function readState(s,command=false)
return true; return true;
} }
if (s.seg.length>2) d.querySelectorAll(".pop").forEach((e)=>{e.classList.remove("hide");});
var cd = gId('csl').querySelectorAll("button"); var cd = gId('csl').querySelectorAll("button");
for (let e = cd.length-1; e >= 0; e--) { for (let e = cd.length-1; e >= 0; e--) {
cd[e].dataset.r = i.col[e][0]; cd[e].dataset.r = i.col[e][0];
@ -1838,7 +1833,7 @@ function makeSeg()
}); });
var cn = `<div class="seg lstI expanded">`+ var cn = `<div class="seg lstI expanded">`+
`<div class="segin">`+ `<div class="segin">`+
`<input type="text" id="seg${lu}t" autocomplete="off" maxlength=32 value="" placeholder="New segment ${lu}"/>`+ `<input class="ptxt show" type="text" id="seg${lu}t" autocomplete="off" maxlength=32 value="" placeholder="New segment ${lu}"/>`+
`<table class="segt">`+ `<table class="segt">`+
`<tr>`+ `<tr>`+
`<td width="38%">${isM?'Start X':'Start LED'}</td>`+ `<td width="38%">${isM?'Start X':'Start LED'}</td>`+
@ -1864,13 +1859,19 @@ function makeSeg()
function resetUtil(off=false) function resetUtil(off=false)
{ {
gId('segutil').innerHTML = `<div class="seg btn btn-s${off?' off':''}" style="padding:0;">` gId('segutil').innerHTML = `<div class="seg btn btn-s${off?' off':''}" style="padding:0;margin-bottom:12px;">`
+ '<label class="check schkl"><input type="checkbox" id="selall" onchange="selSegAll(this)"><span class="checkmark"></span></label>' + '<label class="check schkl"><input type="checkbox" id="selall" onchange="selSegAll(this)"><span class="checkmark"></span></label>'
+ `<div class="segname" ${off?'':'onclick="makeSeg()"'}><i class="icons btn-icon">&#xe18a;</i>Add segment</div>` + `<div class="segname" ${off?'':'onclick="makeSeg()"'}><i class="icons btn-icon">&#xe18a;</i>Add segment</div>`
+ '<div class="pop hide" onclick="event.stopPropagation();">' + '<div class="pop hide" onclick="event.stopPropagation();">'
+ `<i class="icons g-icon" title="Select group" onclick="this.nextElementSibling.classList.toggle('hide');">&#xE34B;</i>` + `<i class="icons g-icon" title="Select group" onclick="this.nextElementSibling.classList.toggle('hide');">&#xE34B;</i>`
+ '<div class="pop-c hide"><span style="color:var(--c-f);" onclick="selGrp(0);">&#x278A;</span><span style="color:var(--c-r);" onclick="selGrp(1);">&#x278B;</span><span style="color:var(--c-g);" onclick="selGrp(2);">&#x278C;</span><span style="color:var(--c-l);" onclick="selGrp(3);">&#x278D;</span></div>' + '<div class="pop-c hide"><span style="color:var(--c-f);" onclick="selGrp(0);">&#x278A;</span><span style="color:var(--c-r);" onclick="selGrp(1);">&#x278B;</span><span style="color:var(--c-g);" onclick="selGrp(2);">&#x278C;</span><span style="color:var(--c-l);" onclick="selGrp(3);">&#x278D;</span></div>'
+ '</div></div>'; + '</div></div>';
gId('selall').checked = true;
for (var i = 0; i <= lSeg; i++) {
if (!gId(`seg${i}`)) continue;
if (!gId(`seg${i}sel`).checked) gId('selall').checked = false; // uncheck if at least one is unselected.
}
if (lSeg>2) d.querySelectorAll("#Segments .pop").forEach((e)=>{e.classList.remove("hide");});
} }
function makePlSel(el, incPl=false) function makePlSel(el, incPl=false)
@ -1984,7 +1985,7 @@ function makeP(i,pl)
<div class="sel">End preset:<br> <div class="sel">End preset:<br>
<div class="sel-p"><select class="sel-ple" id="pl${i}selEnd" onchange="plR(${i})" data-val=${plJson[i].end?plJson[i].end:0}> <div class="sel-p"><select class="sel-ple" id="pl${i}selEnd" onchange="plR(${i})" data-val=${plJson[i].end?plJson[i].end:0}>
<option value="0">None</option> <option value="0">None</option>
<option value="255">Restore preset</option> <option value="255" ${plJson[i].end && plJson[i].end==255?"selected":""}>Restore preset</option>
${makePlSel(plJson[i].end?plJson[i].end:0, true)} ${makePlSel(plJson[i].end?plJson[i].end:0, true)}
</select></div></div> </select></div></div>
</div> </div>

Wyświetl plik

@ -23,6 +23,8 @@
function isD2P(t) { return t > 47 && t < 64; } // is digital 2 pin type function isD2P(t) { return t > 47 && t < 64; } // is digital 2 pin type
function is16b(t) { return t == 26 || t == 29 } // is digital 16 bit type function is16b(t) { return t == 26 || t == 29 } // is digital 16 bit type
function isVir(t) { return t >= 80 && t < 96; } // is virtual type function isVir(t) { return t >= 80 && t < 96; } // is virtual type
function hasW(t) { return (t >= 18 && t <= 21) || (t >= 28 && t <= 32) || (t >= 44 && t <= 45) || (t >= 88 && t <= 89); }
function hasCCT(t) { return t == 20 || t == 21 || t == 42 || t == 45 || t == 28 || t == 32; }
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript // https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) { function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script"); let scE = d.createElement("script");
@ -151,7 +153,7 @@
{ {
const t = parseInt(d.Sf["LT"+n].value); // LED type SELECT const t = parseInt(d.Sf["LT"+n].value); // LED type SELECT
gId('LAdis'+n).style.display = s.selectedIndex==5 ? "inline" : "none"; gId('LAdis'+n).style.display = s.selectedIndex==5 ? "inline" : "none";
d.Sf["LA"+n].value = s.value==="0" ? 55 : s.value; if (s.value!=="0") d.Sf["LA"+n].value = s.value;
d.Sf["LA"+n].min = (isVir(t) || isAna(t)) ? 0 : 1; d.Sf["LA"+n].min = (isVir(t) || isAna(t)) ? 0 : 1;
} }
function setABL() function setABL()
@ -188,6 +190,7 @@
if (isDig(t)) { if (isDig(t)) {
if (is16b(t)) len *= 2; // 16 bit LEDs if (is16b(t)) len *= 2; // 16 bit LEDs
if (t > 28 && t < 40) ch = 4; //RGBW if (t > 28 && t < 40) ch = 4; //RGBW
if (t == 28) ch = 5; //GRBCW
if (maxM < 10000 && d.getElementsByName("L0"+n)[0].value == 3) { //8266 DMA uses 5x the mem if (maxM < 10000 && d.getElementsByName("L0"+n)[0].value == 3) { //8266 DMA uses 5x the mem
mul = 5; mul = 5;
} }
@ -202,7 +205,7 @@
function UI(change=false) function UI(change=false)
{ {
let isRGBW = false, gRGBW = false, memu = 0; let gRGBW = false, memu = 0;
let busMA = 0; let busMA = 0;
let sLC = 0, sPC = 0, sDI = 0, maxLC = 0; let sLC = 0, sPC = 0, sDI = 0, maxLC = 0;
const ablEN = d.Sf.ABL.checked; const ablEN = d.Sf.ABL.checked;
@ -242,15 +245,15 @@
d.Sf["MA"+n].min = (isVir(t) || isAna(t)) ? 0 : 250; d.Sf["MA"+n].min = (isVir(t) || isAna(t)) ? 0 : 250;
} }
gId("rf"+n).onclick = (t == 31) ? (()=>{return false}) : (()=>{}); // prevent change for TM1814 gId("rf"+n).onclick = (t == 31) ? (()=>{return false}) : (()=>{}); // prevent change for TM1814
gRGBW |= isRGBW = ((t > 17 && t < 22) || (t > 28 && t < 32) || (t > 40 && t < 46 && t != 43) || t == 88); // RGBW checkbox, TYPE_xxxx values from const.h gRGBW |= hasW(t); // RGBW checkbox, TYPE_xxxx values from const.h
gId("co"+n).style.display = (isVir(t) || isAna(t)) ? "none":"inline"; // hide color order for PWM gId("co"+n).style.display = (isVir(t) || isAna(t)) ? "none":"inline"; // hide color order for PWM
gId("dig"+n+"w").style.display = (isDig(t) && isRGBW) ? "inline":"none"; // show swap channels dropdown gId("dig"+n+"w").style.display = (isDig(t) && hasW(t)) ? "inline":"none"; // show swap channels dropdown
if (!(isDig(t) && isRGBW)) d.Sf["WO"+n].value = 0; // reset swapping if (!(isDig(t) && hasW(t))) d.Sf["WO"+n].value = 0; // reset swapping
gId("dig"+n+"c").style.display = (isAna(t)) ? "none":"inline"; // hide count for analog gId("dig"+n+"c").style.display = (isAna(t)) ? "none":"inline"; // hide count for analog
gId("dig"+n+"r").style.display = (isVir(t)) ? "none":"inline"; // hide reversed for virtual gId("dig"+n+"r").style.display = (isVir(t)) ? "none":"inline"; // hide reversed for virtual
gId("dig"+n+"s").style.display = (isVir(t) || isAna(t)) ? "none":"inline"; // hide skip 1st for virtual & analog gId("dig"+n+"s").style.display = (isVir(t) || isAna(t)) ? "none":"inline"; // hide skip 1st for virtual & analog
gId("dig"+n+"f").style.display = (isDig(t)) ? "inline":"none"; // hide refresh gId("dig"+n+"f").style.display = (isDig(t)) ? "inline":"none"; // hide refresh
gId("dig"+n+"a").style.display = (isRGBW) ? "inline":"none"; // auto calculate white gId("dig"+n+"a").style.display = (hasW(t)) ? "inline":"none"; // auto calculate white
gId("dig"+n+"l").style.display = (isD2P(t) || isPWM(t)) ? "inline":"none"; // bus clock speed / PWM speed (relative) (not On/Off) gId("dig"+n+"l").style.display = (isD2P(t) || isPWM(t)) ? "inline":"none"; // bus clock speed / PWM speed (relative) (not On/Off)
gId("rev"+n).innerHTML = isAna(t) ? "Inverted output":"Reversed (rotated 180°)"; // change reverse text for analog gId("rev"+n).innerHTML = isAna(t) ? "Inverted output":"Reversed (rotated 180°)"; // change reverse text for analog
//gId("psd"+n).innerHTML = isAna(t) ? "Index:":"Start:"; // change analog start description //gId("psd"+n).innerHTML = isAna(t) ? "Index:":"Start:"; // change analog start description
@ -383,7 +386,9 @@ ${i+1}:
<option value="25">TM1829</option>\ <option value="25">TM1829</option>\
<option value="26">UCS8903</option>\ <option value="26">UCS8903</option>\
<option value="27">APA106/PL9823</option>\ <option value="27">APA106/PL9823</option>\
<option value="28">FW1906 GRBCW</option>\
<option value="29">UCS8904 RGBW</option>\ <option value="29">UCS8904 RGBW</option>\
<option value="32">WS2805 RGBCW</option>\
<option value="50">WS2801</option>\ <option value="50">WS2801</option>\
<option value="51">APA102</option>\ <option value="51">APA102</option>\
<option value="52">LPD8806</option>\ <option value="52">LPD8806</option>\
@ -412,7 +417,7 @@ mA/LED: <select name="LAsel${i}" onchange="enLA(this,${i});UI();">
<option value="15">15mA (seed/fairy pixels)</option> <option value="15">15mA (seed/fairy pixels)</option>
<option value="0">Custom</option> <option value="0">Custom</option>
</select><br> </select><br>
<div id="LAdis${i}" style="display: none;">max. mA/LED: <input name="LA${i}" type="number" min="1" max="254" oninput="UI()"> mA<br></div> <div id="LAdis${i}" style="display: none;">max. mA/LED: <input name="LA${i}" type="number" min="1" max="255" oninput="UI()"> mA<br></div>
<div id="PSU${i}">PSU: <input name="MA${i}" type="number" class="xl" min="250" max="65000" oninput="UI()" value="250"> mA<br></div> <div id="PSU${i}">PSU: <input name="MA${i}" type="number" class="xl" min="250" max="65000" oninput="UI()" value="250"> mA<br></div>
</div> </div>
<div id="co${i}" style="display:inline">Color Order: <div id="co${i}" style="display:inline">Color Order:
@ -861,6 +866,7 @@ Swap: <select id="xw${i}" name="XW${i}">
</select> </select>
<br> <br>
Calculate CCT from RGB: <input type="checkbox" name="CR"><br> Calculate CCT from RGB: <input type="checkbox" name="CR"><br>
CCT IC used (Athom 15W): <input type="checkbox" name="IC"><br>
CCT additive blending: <input type="number" class="s" min="0" max="100" name="CB" required> % CCT additive blending: <input type="number" class="s" min="0" max="100" name="CB" required> %
</div> </div>
<h3>Advanced</h3> <h3>Advanced</h3>

Wyświetl plik

@ -84,7 +84,7 @@
option.textContent = "Other network..."; option.textContent = "Other network...";
select.appendChild(option); select.appendChild(option);
if (input.value === "" || found) input.replaceWith(select); if (input.value === "" || input.value === "Your_Network" || found) input.replaceWith(select);
else select.remove(); else select.remove();
} }

Wyświetl plik

@ -20,6 +20,7 @@ void doublePressAction(uint8_t b=0);
bool isButtonPressed(uint8_t b=0); bool isButtonPressed(uint8_t b=0);
void handleButton(); void handleButton();
void handleIO(); void handleIO();
void IRAM_ATTR touchButtonISR();
//cfg.cpp //cfg.cpp
bool deserializeConfig(JsonObject doc, bool fromFS = false); bool deserializeConfig(JsonObject doc, bool fromFS = false);
@ -233,6 +234,7 @@ const char *getPresetsFileName(bool persistent = true);
void initPresetsFile(); void initPresetsFile();
void handlePresets(); void handlePresets();
bool applyPreset(byte index, byte callMode = CALL_MODE_DIRECT_CHANGE); bool applyPreset(byte index, byte callMode = CALL_MODE_DIRECT_CHANGE);
bool applyPresetFromPlaylist(byte index);
void applyPresetWithFallback(uint8_t presetID, uint8_t callMode, uint8_t effectID = 0, uint8_t paletteID = 0); void applyPresetWithFallback(uint8_t presetID, uint8_t callMode, uint8_t effectID = 0, uint8_t paletteID = 0);
inline bool applyTemporaryPreset() {return applyPreset(255);}; inline bool applyTemporaryPreset() {return applyPreset(255);};
void savePreset(byte index, const char* pname = nullptr, JsonObject saveobj = JsonObject()); void savePreset(byte index, const char* pname = nullptr, JsonObject saveobj = JsonObject());
@ -434,7 +436,6 @@ void handleSerial();
void updateBaudRate(uint32_t rate); void updateBaudRate(uint32_t rate);
//wled_server.cpp //wled_server.cpp
String getFileContentType(String &filename);
void createEditHandler(bool enable); void createEditHandler(bool enable);
void initServer(); void initServer();
void serveMessage(AsyncWebServerRequest* request, uint16_t code, const String& headl, const String& subl="", byte optionT=255); void serveMessage(AsyncWebServerRequest* request, uint16_t code, const String& headl, const String& subl="", byte optionT=255);

Wyświetl plik

@ -375,20 +375,16 @@ void updateFSInfo() {
#endif #endif
} }
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
#ifdef ARDUINO_ARCH_ESP32
// caching presets in PSRAM may prevent occasional flashes seen when HomeAssitant polls WLED // caching presets in PSRAM may prevent occasional flashes seen when HomeAssitant polls WLED
// original idea by @akaricchi (https://github.com/Akaricchi) // original idea by @akaricchi (https://github.com/Akaricchi)
// returns a pointer to the PSRAM buffer updates size parameter // returns a pointer to the PSRAM buffer, updates size parameter
static const uint8_t *getPresetCache(size_t &size) { static const uint8_t *getPresetCache(size_t &size) {
static unsigned long presetsCachedTime; static unsigned long presetsCachedTime;
static uint8_t *presetsCached; static uint8_t *presetsCached;
static size_t presetsCachedSize; static size_t presetsCachedSize;
if (!psramFound()) {
size = 0;
return nullptr;
}
if (presetsModifiedTime != presetsCachedTime) { if (presetsModifiedTime != presetsCachedTime) {
if (presetsCached) { if (presetsCached) {
free(presetsCached); free(presetsCached);
@ -420,26 +416,19 @@ bool handleFileRead(AsyncWebServerRequest* request, String path){
DEBUG_PRINT(F("WS FileRead: ")); DEBUG_PRINTLN(path); DEBUG_PRINT(F("WS FileRead: ")); DEBUG_PRINTLN(path);
if(path.endsWith("/")) path += "index.htm"; if(path.endsWith("/")) path += "index.htm";
if(path.indexOf(F("sec")) > -1) return false; if(path.indexOf(F("sec")) > -1) return false;
String contentType = getFileContentType(path); #ifdef ARDUINO_ARCH_ESP32
if(request->hasArg(F("download"))) contentType = F("application/octet-stream"); if (psramSafe && psramFound() && path.endsWith(FPSTR(getPresetsFileName()))) {
/*String pathWithGz = path + ".gz";
if(WLED_FS.exists(pathWithGz)){
request->send(WLED_FS, pathWithGz, contentType);
return true;
}*/
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
if (path.endsWith(FPSTR(getPresetsFileName()))) {
size_t psize; size_t psize;
const uint8_t *presets = getPresetCache(psize); const uint8_t *presets = getPresetCache(psize);
if (presets) { if (presets) {
AsyncWebServerResponse *response = request->beginResponse_P(200, contentType, presets, psize); AsyncWebServerResponse *response = request->beginResponse_P(200, FPSTR(CONTENT_TYPE_JSON), presets, psize);
request->send(response); request->send(response);
return true; return true;
} }
} }
#endif #endif
if(WLED_FS.exists(path)) { if(WLED_FS.exists(path) || WLED_FS.exists(path + ".gz")) {
request->send(WLED_FS, path, contentType); request->send(WLED_FS, path, String(), request->hasArg(F("download")));
return true; return true;
} }
return false; return false;

Wyświetl plik

@ -210,7 +210,7 @@ void sendImprovInfoResponse() {
//Use serverDescription if it has been changed from the default "WLED", else mDNS name //Use serverDescription if it has been changed from the default "WLED", else mDNS name
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0); bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
char vString[20]; char vString[20];
sprintf_P(vString, PSTR("0.15.0-b1/%i"), VERSION); sprintf_P(vString, PSTR("0.15.0-b3/%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);

Wyświetl plik

@ -142,28 +142,42 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
{ {
if (seg.getLightCapabilities() & 3) { if (seg.getLightCapabilities() & 3) {
// segment has RGB or White // segment has RGB or White
for (size_t i = 0; i < 3; i++) for (size_t i = 0; i < NUM_COLORS; i++) {
{ // JSON "col" array can contain the following values for each of segment's colors (primary, background, custom):
// "col":[int|string|object|array, int|string|object|array, int|string|object|array]
// int = Kelvin temperature or 0 for black
// string = hex representation of [WW]RRGGBB
// object = individual channel control {"r":0,"g":127,"b":255,"w":255}, each being optional (valid to send {})
// array = direct channel values [r,g,b,w] (w element being optional)
int rgbw[] = {0,0,0,0}; int rgbw[] = {0,0,0,0};
bool colValid = false; bool colValid = false;
JsonArray colX = colarr[i]; JsonArray colX = colarr[i];
if (colX.isNull()) { if (colX.isNull()) {
byte brgbw[] = {0,0,0,0}; JsonObject oCol = colarr[i];
const char* hexCol = colarr[i]; if (!oCol.isNull()) {
if (hexCol == nullptr) { //Kelvin color temperature (or invalid), e.g 2400 // we have a JSON object for color {"w":123,"r":123,...}; allows individual channel control
int kelvin = colarr[i] | -1; rgbw[0] = oCol["r"] | R(seg.colors[i]);
if (kelvin < 0) continue; rgbw[1] = oCol["g"] | G(seg.colors[i]);
if (kelvin == 0) seg.setColor(i, 0); rgbw[2] = oCol["b"] | B(seg.colors[i]);
if (kelvin > 0) colorKtoRGB(kelvin, brgbw); rgbw[3] = oCol["w"] | W(seg.colors[i]);
colValid = true; colValid = true;
} else { //HEX string, e.g. "FFAA00" } else {
colValid = colorFromHexString(brgbw, hexCol); byte brgbw[] = {0,0,0,0};
const char* hexCol = colarr[i];
if (hexCol == nullptr) { //Kelvin color temperature (or invalid), e.g 2400
int kelvin = colarr[i] | -1;
if (kelvin < 0) continue;
if (kelvin == 0) seg.setColor(i, 0);
if (kelvin > 0) colorKtoRGB(kelvin, brgbw);
colValid = true;
} else { //HEX string, e.g. "FFAA00"
colValid = colorFromHexString(brgbw, hexCol);
}
for (size_t c = 0; c < 4; c++) rgbw[c] = brgbw[c];
} }
for (size_t c = 0; c < 4; c++) rgbw[c] = brgbw[c];
} else { //Array of ints (RGB or RGBW color), e.g. [255,160,0] } else { //Array of ints (RGB or RGBW color), e.g. [255,160,0]
byte sz = colX.size(); byte sz = colX.size();
if (sz == 0) continue; //do nothing on empty array if (sz == 0) continue; //do nothing on empty array
copyArray(colX, rgbw, 4); copyArray(colX, rgbw, 4);
colValid = true; colValid = true;
} }
@ -226,14 +240,19 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
getVal(elem["ix"], &seg.intensity); getVal(elem["ix"], &seg.intensity);
uint8_t pal = seg.palette; uint8_t pal = seg.palette;
last = strip.getPaletteCount();
if (!elem["pal"].isNull() && elem["pal"].is<const char*>()) {
const char *tmp = elem["pal"].as<const char *>();
if (strlen(tmp) > 3 && (strchr(tmp,'r') || strchr(tmp,'~') != strrchr(tmp,'~'))) last = 0; // we have "X~Y(r|[w]~[-])" form
}
if (seg.getLightCapabilities() & 1) { // ignore palette for White and On/Off segments if (seg.getLightCapabilities() & 1) { // ignore palette for White and On/Off segments
if (getVal(elem["pal"], &pal)) seg.setPalette(pal); if (getVal(elem["pal"], &pal, 0, last)) seg.setPalette(pal);
} }
getVal(elem["c1"], &seg.custom1); getVal(elem["c1"], &seg.custom1);
getVal(elem["c2"], &seg.custom2); getVal(elem["c2"], &seg.custom2);
uint8_t cust3 = seg.custom3; uint8_t cust3 = seg.custom3;
getVal(elem["c3"], &cust3); // we can't pass reference to bitfield getVal(elem["c3"], &cust3, 0, 31); // we can't pass reference to bitfield
seg.custom3 = constrain(cust3, 0, 31); seg.custom3 = constrain(cust3, 0, 31);
seg.check1 = getBoolVal(elem["o1"], seg.check1); seg.check1 = getBoolVal(elem["o1"], seg.check1);
@ -257,8 +276,8 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
seg.fill(BLACK); seg.fill(BLACK);
} }
uint16_t start = 0, stop = 0; start = 0, stop = 0;
byte set = 0; //0 nothing set, 1 start set, 2 range set set = 0; //0 nothing set, 1 start set, 2 range set
for (size_t i = 0; i < iarr.size(); i++) { for (size_t i = 0; i < iarr.size(); i++) {
if(iarr[i].is<JsonInteger>()) { if(iarr[i].is<JsonInteger>()) {
@ -298,7 +317,7 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
return true; return true;
} }
// deserializes WLED state (fileDoc points to doc object if called from web server) // deserializes WLED state
// presetId is non-0 if called from handlePreset() // presetId is non-0 if called from handlePreset()
bool deserializeState(JsonObject root, byte callMode, byte presetId) bool deserializeState(JsonObject root, byte callMode, byte presetId)
{ {
@ -730,6 +749,8 @@ void serializeInfo(JsonObject root)
root[F("arch")] = ESP.getChipModel(); root[F("arch")] = ESP.getChipModel();
#endif #endif
root[F("core")] = ESP.getSdkVersion(); root[F("core")] = ESP.getSdkVersion();
root[F("clock")] = ESP.getCpuFreqMHz();
root[F("flash")] = (ESP.getFlashChipSize()/1024)/1024;
#ifdef WLED_DEBUG #ifdef WLED_DEBUG
root[F("maxalloc")] = ESP.getMaxAllocHeap(); root[F("maxalloc")] = ESP.getMaxAllocHeap();
root[F("resetReason0")] = (int)rtc_get_reset_reason(0); root[F("resetReason0")] = (int)rtc_get_reset_reason(0);
@ -739,6 +760,8 @@ void serializeInfo(JsonObject root)
#else #else
root[F("arch")] = "esp8266"; root[F("arch")] = "esp8266";
root[F("core")] = ESP.getCoreVersion(); root[F("core")] = ESP.getCoreVersion();
root[F("clock")] = ESP.getCpuFreqMHz();
root[F("flash")] = (ESP.getFlashChipSize()/1024)/1024;
#ifdef WLED_DEBUG #ifdef WLED_DEBUG
root[F("maxalloc")] = ESP.getMaxFreeBlockSize(); root[F("maxalloc")] = ESP.getMaxFreeBlockSize();
root[F("resetReason")] = (int)ESP.getResetInfoPtr()->reason; root[F("resetReason")] = (int)ESP.getResetInfoPtr()->reason;
@ -747,8 +770,8 @@ void serializeInfo(JsonObject root)
#endif #endif
root[F("freeheap")] = ESP.getFreeHeap(); root[F("freeheap")] = ESP.getFreeHeap();
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) #if defined(ARDUINO_ARCH_ESP32)
if (psramFound()) root[F("psram")] = ESP.getFreePsram(); if (psramSafe && psramFound()) root[F("psram")] = ESP.getFreePsram();
#endif #endif
root[F("uptime")] = millis()/1000 + rolloverMillis*4294967; root[F("uptime")] = millis()/1000 + rolloverMillis*4294967;
@ -850,8 +873,8 @@ void serializePalettes(JsonObject root, int page)
int itemPerPage = 8; int itemPerPage = 8;
#endif #endif
int palettesCount = strip.getPaletteCount();
int customPalettes = strip.customPalettes.size(); int customPalettes = strip.customPalettes.size();
int palettesCount = strip.getPaletteCount() - customPalettes;
int maxPage = (palettesCount + customPalettes -1) / itemPerPage; int maxPage = (palettesCount + customPalettes -1) / itemPerPage;
if (page > maxPage) page = maxPage; if (page > maxPage) page = maxPage;
@ -1063,7 +1086,7 @@ void serveJson(AsyncWebServerRequest* request)
} }
#endif #endif
else if (url.indexOf("pal") > 0) { else if (url.indexOf("pal") > 0) {
request->send_P(200, "application/json", JSON_palette_names); // contentType defined in AsyncJson-v6.h request->send_P(200, FPSTR(CONTENT_TYPE_JSON), JSON_palette_names);
return; return;
} }
else if (url.indexOf(F("cfg")) > 0 && handleFileRead(request, F("/cfg.json"))) { else if (url.indexOf(F("cfg")) > 0 && handleFileRead(request, F("/cfg.json"))) {
@ -1150,10 +1173,10 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
} }
#endif #endif
char buffer[2048]; // shoud be enough for 256 LEDs [RRGGBB] + all other text (9+25) DynamicBuffer buffer(9 + (9*(1+(used/n))) + 7 + 5 + 6 + 5 + 6 + 5 + 2);
strcpy_P(buffer, PSTR("{\"leds\":[")); char* buf = buffer.data(); // assign buffer for oappnd() functions
obuf = buffer; // assign buffer for oappnd() functions strncpy_P(buffer.data(), PSTR("{\"leds\":["), buffer.size());
olen = 9; buf += 9; // sizeof(PSTR()) from last line
for (size_t i = 0; i < used; i += n) for (size_t i = 0; i < used; i += n)
{ {
@ -1168,29 +1191,27 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
r = scale8(qadd8(w, r), strip.getBrightness()); //R, add white channel to RGB channels as a simple RGBW -> RGB map r = scale8(qadd8(w, r), strip.getBrightness()); //R, add white channel to RGB channels as a simple RGBW -> RGB map
g = scale8(qadd8(w, g), strip.getBrightness()); //G g = scale8(qadd8(w, g), strip.getBrightness()); //G
b = scale8(qadd8(w, b), strip.getBrightness()); //B b = scale8(qadd8(w, b), strip.getBrightness()); //B
olen += sprintf_P(obuf + olen, PSTR("\"%06X\","), RGBW32(r,g,b,0)); buf += sprintf_P(buf, PSTR("\"%06X\","), RGBW32(r,g,b,0));
} }
olen -= 1; buf--; // remove last comma
oappend((const char*)F("],\"n\":")); buf += sprintf_P(buf, PSTR("],\"n\":%d"), n);
oappendi(n);
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
if (strip.isMatrix) { if (strip.isMatrix) {
oappend((const char*)F(",\"w\":")); buf += sprintf_P(buf, PSTR(",\"w\":%d"), Segment::maxWidth/n);
oappendi(Segment::maxWidth/n); buf += sprintf_P(buf, PSTR(",\"h\":%d"), Segment::maxHeight/n);
oappend((const char*)F(",\"h\":"));
oappendi(Segment::maxHeight/n);
} }
#endif #endif
oappend("}"); (*buf++) = '}';
(*buf++) = 0;
if (request) { if (request) {
request->send(200, "application/json", buffer); // contentType defined in AsyncJson-v6.h request->send(200, FPSTR(CONTENT_TYPE_JSON), toString(std::move(buffer)));
} }
#ifdef WLED_ENABLE_WEBSOCKETS #ifdef WLED_ENABLE_WEBSOCKETS
else { else {
wsc->text(obuf, olen); wsc->text(toString(std::move(buffer)));
} }
#endif #endif
obuf = nullptr;
return true; return true;
} }
#endif #endif

Wyświetl plik

@ -209,11 +209,10 @@ bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag)
// if tag is set to PinOwner::None, checks for ANY owner of the pin. // if tag is set to PinOwner::None, checks for ANY owner of the pin.
// if tag is set to any other value, checks if that tag is the current owner of the pin. // if tag is set to any other value, checks if that tag is the current owner of the pin.
bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag) bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag) const
{ {
if (!isPinOk(gpio, false)) return true; if (!isPinOk(gpio, false)) return true;
if ((tag != PinOwner::None) && (ownerTag[gpio] != tag)) return false; if ((tag != PinOwner::None) && (ownerTag[gpio] != tag)) return false;
if (gpio >= WLED_NUM_PINS) return false; // catch error case, to avoid array out-of-bounds access
byte by = gpio >> 3; byte by = gpio >> 3;
byte bi = gpio - (by<<3); byte bi = gpio - (by<<3);
return bitRead(pinAlloc[by], bi); return bitRead(pinAlloc[by], bi);
@ -236,8 +235,9 @@ bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag)
*/ */
// 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
{ {
if (gpio >= WLED_NUM_PINS) return false; // catch error case, to avoid array out-of-bounds access
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
if (digitalPinIsValid(gpio)) { if (digitalPinIsValid(gpio)) {
#if defined(CONFIG_IDF_TARGET_ESP32C3) #if defined(CONFIG_IDF_TARGET_ESP32C3)
@ -248,7 +248,7 @@ bool PinManagerClass::isPinOk(byte gpio, bool output)
// 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 (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.
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 (gpio > 32 && gpio < 38) return !psramFound(); // 33 to 37: not available if using _octal_ SPI Flash or _octal_ PSRAM
// 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
@ -257,9 +257,8 @@ bool PinManagerClass::isPinOk(byte gpio, bool output)
// GPIO46 is input only and pulled down // GPIO46 is input only and pulled down
#else #else
if (gpio > 5 && gpio < 12) return false; //SPI flash pins if (gpio > 5 && gpio < 12) return false; //SPI flash pins
#ifdef BOARD_HAS_PSRAM if (strncmp_P(PSTR("ESP32-PICO"), ESP.getChipModel(), 10) == 0 && (gpio == 16 || gpio == 17)) return false; // PICO-D4: gpio16+17 are in use for onboard SPI FLASH
if (gpio == 16 || gpio == 17) return false; //PSRAM pins if (gpio == 16 || gpio == 17) return !psramFound(); //PSRAM pins on ESP32 (these are IO)
#endif
#endif #endif
if (output) return digitalPinCanOutput(gpio); if (output) return digitalPinCanOutput(gpio);
else return true; else return true;
@ -272,8 +271,8 @@ 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 (!isPinOk(gpio, false)) return PinOwner::None; if (!isPinOk(gpio, false)) return PinOwner::None;
return ownerTag[gpio]; return ownerTag[gpio];
} }

Wyświetl plik

@ -61,7 +61,8 @@ enum struct PinOwner : uint8_t {
UM_Audioreactive = USERMOD_ID_AUDIOREACTIVE, // 0x20 // Usermod "audio_reactive.h" UM_Audioreactive = USERMOD_ID_AUDIOREACTIVE, // 0x20 // Usermod "audio_reactive.h"
UM_SdCard = USERMOD_ID_SD_CARD, // 0x25 // Usermod "usermod_sd_card.h" UM_SdCard = USERMOD_ID_SD_CARD, // 0x25 // Usermod "usermod_sd_card.h"
UM_PWM_OUTPUTS = USERMOD_ID_PWM_OUTPUTS, // 0x26 // Usermod "usermod_pwm_outputs.h" UM_PWM_OUTPUTS = USERMOD_ID_PWM_OUTPUTS, // 0x26 // Usermod "usermod_pwm_outputs.h"
UM_LDR_DUSK_DAWN = USERMOD_ID_LDR_DUSK_DAWN // 0x2B // Usermod "usermod_LDR_Dusk_Dawn_v2.h" UM_LDR_DUSK_DAWN = USERMOD_ID_LDR_DUSK_DAWN, // 0x2B // Usermod "usermod_LDR_Dusk_Dawn_v2.h"
UM_MAX17048 = USERMOD_ID_MAX17048 // 0x2F // Usermod "usermod_max17048.h"
}; };
static_assert(0u == static_cast<uint8_t>(PinOwner::None), "PinOwner::None must be zero, so default array initialization works as expected"); static_assert(0u == static_cast<uint8_t>(PinOwner::None), "PinOwner::None must be zero, so default array initialization works as expected");
@ -108,11 +109,11 @@ class PinManagerClass {
inline void deallocatePin(byte gpio) { deallocatePin(gpio, PinOwner::None); } inline void deallocatePin(byte gpio) { deallocatePin(gpio, PinOwner::None); }
// 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) const;
// 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;
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
byte allocateLedc(byte channels); byte allocateLedc(byte channels);

Wyświetl plik

@ -109,7 +109,10 @@ int16_t loadPlaylist(JsonObject playlistObj, byte presetId) {
if (playlistRepeat > 0) playlistRepeat++; //add one extra repetition immediately since it will be deducted on first start if (playlistRepeat > 0) playlistRepeat++; //add one extra repetition immediately since it will be deducted on first start
playlistEndPreset = playlistObj["end"] | 0; playlistEndPreset = playlistObj["end"] | 0;
// if end preset is 255 restore original preset (if any running) upon playlist end // if end preset is 255 restore original preset (if any running) upon playlist end
if (playlistEndPreset == 255 && currentPreset > 0) playlistEndPreset = currentPreset; if (playlistEndPreset == 255 && currentPreset > 0) {
playlistEndPreset = currentPreset;
playlistOptions |= PL_OPTION_RESTORE; // for async save operation
}
if (playlistEndPreset > 250) playlistEndPreset = 0; if (playlistEndPreset > 250) playlistEndPreset = 0;
shuffle = shuffle || playlistObj["r"]; shuffle = shuffle || playlistObj["r"];
if (shuffle) playlistOptions |= PL_OPTION_SHUFFLE; if (shuffle) playlistOptions |= PL_OPTION_SHUFFLE;
@ -122,8 +125,7 @@ int16_t loadPlaylist(JsonObject playlistObj, byte presetId) {
void handlePlaylist() { void handlePlaylist() {
static unsigned long presetCycledTime = 0; static unsigned long presetCycledTime = 0;
// if fileDoc is not null JSON buffer is in use so just quit if (currentPlaylist < 0 || playlistEntries == nullptr) return;
if (currentPlaylist < 0 || playlistEntries == nullptr || fileDoc != nullptr) return;
if (millis() - presetCycledTime > (100*playlistEntryDur)) { if (millis() - presetCycledTime > (100*playlistEntryDur)) {
presetCycledTime = millis(); presetCycledTime = millis();
@ -135,7 +137,7 @@ void handlePlaylist() {
if (!playlistIndex) { if (!playlistIndex) {
if (playlistRepeat == 1) { //stop if all repetitions are done if (playlistRepeat == 1) { //stop if all repetitions are done
unloadPlaylist(); unloadPlaylist();
if (playlistEndPreset) applyPreset(playlistEndPreset); if (playlistEndPreset) applyPresetFromPlaylist(playlistEndPreset);
return; return;
} }
if (playlistRepeat > 1) playlistRepeat--; // decrease repeat count on each index reset if not an endless playlist if (playlistRepeat > 1) playlistRepeat--; // decrease repeat count on each index reset if not an endless playlist
@ -146,7 +148,7 @@ void handlePlaylist() {
jsonTransitionOnce = true; jsonTransitionOnce = true;
strip.setTransition(fadeTransition ? playlistEntries[playlistIndex].tr * 100 : 0); strip.setTransition(fadeTransition ? playlistEntries[playlistIndex].tr * 100 : 0);
playlistEntryDur = playlistEntries[playlistIndex].dur; playlistEntryDur = playlistEntries[playlistIndex].dur;
applyPreset(playlistEntries[playlistIndex].preset); applyPresetFromPlaylist(playlistEntries[playlistIndex].preset);
} }
} }
@ -157,7 +159,7 @@ void serializePlaylist(JsonObject sObj) {
JsonArray dur = playlist.createNestedArray("dur"); JsonArray dur = playlist.createNestedArray("dur");
JsonArray transition = playlist.createNestedArray(F("transition")); JsonArray transition = playlist.createNestedArray(F("transition"));
playlist[F("repeat")] = (playlistIndex < 0 && playlistRepeat > 0) ? playlistRepeat - 1 : playlistRepeat; // remove added repetition count (if not yet running) playlist[F("repeat")] = (playlistIndex < 0 && playlistRepeat > 0) ? playlistRepeat - 1 : playlistRepeat; // remove added repetition count (if not yet running)
playlist["end"] = playlistEndPreset; playlist["end"] = playlistOptions & PL_OPTION_RESTORE ? 255 : playlistEndPreset;
playlist["r"] = playlistOptions & PL_OPTION_SHUFFLE; playlist["r"] = playlistOptions & PL_OPTION_SHUFFLE;
for (int i=0; i<playlistLen; i++) { for (int i=0; i<playlistLen; i++) {
ps.add(playlistEntries[i].preset); ps.add(playlistEntries[i].preset);

Wyświetl plik

@ -27,7 +27,7 @@ static void doSaveState() {
unsigned long start = millis(); unsigned long start = millis();
while (strip.isUpdating() && millis()-start < (2*FRAMETIME_FIXED)+1) yield(); // wait 2 frames while (strip.isUpdating() && millis()-start < (2*FRAMETIME_FIXED)+1) yield(); // wait 2 frames
if (!requestJSONBufferLock(10)) return; // will set fileDoc if (!requestJSONBufferLock(10)) return;
initPresetsFile(); // just in case if someone deleted presets.json using /edit initPresetsFile(); // just in case if someone deleted presets.json using /edit
JsonObject sObj = pDoc->to<JsonObject>(); JsonObject sObj = pDoc->to<JsonObject>();
@ -53,23 +53,21 @@ static void doSaveState() {
#if defined(ARDUINO_ARCH_ESP32) #if defined(ARDUINO_ARCH_ESP32)
if (!persist) { if (!persist) {
if (tmpRAMbuffer!=nullptr) free(tmpRAMbuffer); if (tmpRAMbuffer!=nullptr) free(tmpRAMbuffer);
size_t len = measureJson(*fileDoc) + 1; size_t len = measureJson(*pDoc) + 1;
DEBUG_PRINTLN(len); DEBUG_PRINTLN(len);
// if possible use SPI RAM on ESP32 // if possible use SPI RAM on ESP32
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM) if (psramSafe && psramFound())
if (psramFound())
tmpRAMbuffer = (char*) ps_malloc(len); tmpRAMbuffer = (char*) ps_malloc(len);
else else
#endif
tmpRAMbuffer = (char*) malloc(len); tmpRAMbuffer = (char*) malloc(len);
if (tmpRAMbuffer!=nullptr) { if (tmpRAMbuffer!=nullptr) {
serializeJson(*fileDoc, tmpRAMbuffer, len); serializeJson(*pDoc, tmpRAMbuffer, len);
} else { } else {
writeObjectToFileUsingId(getPresetsFileName(persist), presetToSave, fileDoc); writeObjectToFileUsingId(getPresetsFileName(persist), presetToSave, pDoc);
} }
} else } else
#endif #endif
writeObjectToFileUsingId(getPresetsFileName(persist), presetToSave, fileDoc); writeObjectToFileUsingId(getPresetsFileName(persist), presetToSave, pDoc);
if (persist) presetsModifiedTime = toki.second(); //unix time if (persist) presetsModifiedTime = toki.second(); //unix time
releaseJSONBufferLock(); releaseJSONBufferLock();
@ -117,6 +115,15 @@ void initPresetsFile()
f.close(); f.close();
} }
bool applyPresetFromPlaylist(byte index)
{
DEBUG_PRINT(F("Request to apply preset: "));
DEBUG_PRINTLN(index);
presetToApply = index;
callModeToApply = CALL_MODE_DIRECT_CHANGE;
return true;
}
bool applyPreset(byte index, byte callMode) bool applyPreset(byte index, byte callMode)
{ {
unloadPlaylist(); // applying a preset unloads the playlist (#3827) unloadPlaylist(); // applying a preset unloads the playlist (#3827)
@ -145,7 +152,7 @@ void handlePresets()
return; return;
} }
if (presetToApply == 0 || fileDoc) return; // no preset waiting to apply, or JSON buffer is already allocated, return to loop until free if (presetToApply == 0 || !requestJSONBufferLock(9)) return; // no preset waiting to apply, or JSON buffer is already allocated, return to loop until free
bool changePreset = false; bool changePreset = false;
uint8_t tmpPreset = presetToApply; // store temporary since deserializeState() may call applyPreset() uint8_t tmpPreset = presetToApply; // store temporary since deserializeState() may call applyPreset()
@ -153,9 +160,6 @@ void handlePresets()
JsonObject fdo; JsonObject fdo;
// allocate buffer
if (!requestJSONBufferLock(9)) return; // will also assign fileDoc
presetToApply = 0; //clear request for preset presetToApply = 0; //clear request for preset
callModeToApply = 0; callModeToApply = 0;
@ -164,14 +168,14 @@ void handlePresets()
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
if (tmpPreset==255 && tmpRAMbuffer!=nullptr) { if (tmpPreset==255 && tmpRAMbuffer!=nullptr) {
deserializeJson(*fileDoc,tmpRAMbuffer); deserializeJson(*pDoc,tmpRAMbuffer);
errorFlag = ERR_NONE; errorFlag = ERR_NONE;
} else } else
#endif #endif
{ {
errorFlag = readObjectFromFileUsingId(getPresetsFileName(tmpPreset < 255), tmpPreset, fileDoc) ? ERR_NONE : ERR_FS_PLOAD; errorFlag = readObjectFromFileUsingId(getPresetsFileName(tmpPreset < 255), tmpPreset, pDoc) ? ERR_NONE : ERR_FS_PLOAD;
} }
fdo = fileDoc->as<JsonObject>(); fdo = pDoc->as<JsonObject>();
//HTTP API commands //HTTP API commands
const char* httpwin = fdo["win"]; const char* httpwin = fdo["win"];
@ -198,13 +202,13 @@ void handlePresets()
} }
#endif #endif
releaseJSONBufferLock(); // will also clear fileDoc releaseJSONBufferLock();
if (changePreset) notify(tmpMode); // force UDP notification if (changePreset) notify(tmpMode); // force UDP notification
stateUpdated(tmpMode); // was colorUpdated() if anything breaks stateUpdated(tmpMode); // was colorUpdated() if anything breaks
updateInterfaces(tmpMode); updateInterfaces(tmpMode);
} }
//called from handleSet(PS=) [network callback (fileDoc==nullptr), IR (irrational), deserializeState, UDP] and deserializeState() [network callback (filedoc!=nullptr)] //called from handleSet(PS=) [network callback (sObj is empty), IR (irrational), deserializeState, UDP] and deserializeState() [network callback (filedoc!=nullptr)]
void savePreset(byte index, const char* pname, JsonObject sObj) void savePreset(byte index, const char* pname, JsonObject sObj)
{ {
if (!saveName) saveName = new char[33]; if (!saveName) saveName = new char[33];
@ -242,7 +246,7 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
if (sObj[F("playlist")].isNull()) { if (sObj[F("playlist")].isNull()) {
// we will save API call immediately (often causes presets.json corruption) // we will save API call immediately (often causes presets.json corruption)
presetToSave = 0; presetToSave = 0;
if (index <= 250 && fileDoc) { // cannot save API calls to temporary preset (255) if (index <= 250) { // cannot save API calls to temporary preset (255)
sObj.remove("o"); sObj.remove("o");
sObj.remove("v"); sObj.remove("v");
sObj.remove("time"); sObj.remove("time");
@ -250,7 +254,7 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
sObj.remove(F("psave")); sObj.remove(F("psave"));
if (sObj["n"].isNull()) sObj["n"] = saveName; if (sObj["n"].isNull()) sObj["n"] = saveName;
initPresetsFile(); // just in case if someone deleted presets.json using /edit initPresetsFile(); // just in case if someone deleted presets.json using /edit
writeObjectToFileUsingId(getPresetsFileName(), index, fileDoc); writeObjectToFileUsingId(getPresetsFileName(), index, pDoc);
presetsModifiedTime = toki.second(); //unix time presetsModifiedTime = toki.second(); //unix time
updateFSInfo(); updateFSInfo();
} }

26
wled00/set.cpp 100755 → 100644
Wyświetl plik

@ -110,6 +110,10 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
for (uint8_t s=0; s<WLED_MAX_BUTTONS; s++) { for (uint8_t s=0; s<WLED_MAX_BUTTONS; s++) {
if (btnPin[s]>=0 && pinManager.isPinAllocated(btnPin[s], PinOwner::Button)) { if (btnPin[s]>=0 && pinManager.isPinAllocated(btnPin[s], PinOwner::Button)) {
pinManager.deallocatePin(btnPin[s], PinOwner::Button); pinManager.deallocatePin(btnPin[s], PinOwner::Button);
#ifdef SOC_TOUCH_VERSION_2 // ESP32 S2 and S3 have a function to check touch state, detach interrupt
if (digitalPinToTouchChannel(btnPin[s]) >= 0) // if touch capable pin
touchDetachInterrupt(btnPin[s]); // if not assigned previously, this will do nothing
#endif
} }
} }
@ -123,6 +127,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
autoSegments = request->hasArg(F("MS")); autoSegments = request->hasArg(F("MS"));
correctWB = request->hasArg(F("CCT")); correctWB = request->hasArg(F("CCT"));
cctFromRgb = request->hasArg(F("CR")); cctFromRgb = request->hasArg(F("CR"));
cctICused = request->hasArg(F("IC"));
strip.cctBlending = request->arg(F("CB")).toInt(); strip.cctBlending = request->arg(F("CB")).toInt();
Bus::setCCTBlend(strip.cctBlending); Bus::setCCTBlend(strip.cctBlending);
Bus::setGlobalAWMode(request->arg(F("AW")).toInt()); Bus::setGlobalAWMode(request->arg(F("AW")).toInt());
@ -240,6 +245,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
rlyMde = (bool)request->hasArg(F("RM")); rlyMde = (bool)request->hasArg(F("RM"));
disablePullUp = (bool)request->hasArg(F("IP")); disablePullUp = (bool)request->hasArg(F("IP"));
touchThreshold = request->arg(F("TT")).toInt();
for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) { for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
char bt[4] = "BT"; bt[2] = (i<10?48:55)+i; bt[3] = 0; // button pin (use A,B,C,... if WLED_MAX_BUTTONS>10) char bt[4] = "BT"; bt[2] = (i<10?48:55)+i; bt[3] = 0; // button pin (use A,B,C,... if WLED_MAX_BUTTONS>10)
char be[4] = "BE"; be[2] = (i<10?48:55)+i; be[3] = 0; // button type (use A,B,C,... if WLED_MAX_BUTTONS>10) char be[4] = "BE"; be[2] = (i<10?48:55)+i; be[3] = 0; // button type (use A,B,C,... if WLED_MAX_BUTTONS>10)
@ -256,12 +262,21 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
btnPin[i] = -1; btnPin[i] = -1;
pinManager.deallocatePin(hw_btn_pin,PinOwner::Button); pinManager.deallocatePin(hw_btn_pin,PinOwner::Button);
} }
else if ((buttonType[i] == BTN_TYPE_TOUCH || buttonType[i] == BTN_TYPE_TOUCH_SWITCH) && digitalPinToTouchChannel(btnPin[i]) < 0) else if ((buttonType[i] == BTN_TYPE_TOUCH || buttonType[i] == BTN_TYPE_TOUCH_SWITCH))
{ {
// not a touch pin if (digitalPinToTouchChannel(btnPin[i]) < 0)
DEBUG_PRINTF_P(PSTR("PIN ALLOC error: GPIO%d for touch button #%d is not an touch pin!\n"), btnPin[i], i); {
btnPin[i] = -1; // not a touch pin
pinManager.deallocatePin(hw_btn_pin,PinOwner::Button); DEBUG_PRINTF_P(PSTR("PIN ALLOC error: GPIO%d for touch button #%d is not an touch pin!\n"), btnPin[i], i);
btnPin[i] = -1;
pinManager.deallocatePin(hw_btn_pin,PinOwner::Button);
}
#ifdef SOC_TOUCH_VERSION_2 // ESP32 S2 and S3 have a fucntion to check touch state but need to attach an interrupt to do so
else
{
touchAttachInterrupt(btnPin[i], touchButtonISR, 256 + (touchThreshold << 4)); // threshold on Touch V2 is much higher (1500 is a value given by Espressif example, I measured changes of over 5000)
}
#endif
} }
else else
#endif #endif
@ -281,7 +296,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
buttonType[i] = BTN_TYPE_NONE; buttonType[i] = BTN_TYPE_NONE;
} }
} }
touchThreshold = request->arg(F("TT")).toInt();
briS = request->arg(F("CA")).toInt(); briS = request->arg(F("CA")).toInt();

Wyświetl plik

@ -21,8 +21,6 @@
#define DYNAMIC_JSON_DOCUMENT_SIZE 16384 #define DYNAMIC_JSON_DOCUMENT_SIZE 16384
#endif #endif
constexpr const char* JSON_MIMETYPE = "application/json";
/* /*
* Json Response * Json Response
* */ * */
@ -66,7 +64,7 @@ class AsyncJsonResponse: public AsyncAbstractResponse {
AsyncJsonResponse(JsonDocument *ref, bool isArray=false) : _jsonBuffer(1), _isValid{false} { AsyncJsonResponse(JsonDocument *ref, bool isArray=false) : _jsonBuffer(1), _isValid{false} {
_code = 200; _code = 200;
_contentType = JSON_MIMETYPE; _contentType = FPSTR(CONTENT_TYPE_JSON);
if(isArray) if(isArray)
_root = ref->to<JsonArray>(); _root = ref->to<JsonArray>();
else else
@ -75,7 +73,7 @@ class AsyncJsonResponse: public AsyncAbstractResponse {
AsyncJsonResponse(size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE, bool isArray=false) : _jsonBuffer(maxJsonBufferSize), _isValid{false} { AsyncJsonResponse(size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE, bool isArray=false) : _jsonBuffer(maxJsonBufferSize), _isValid{false} {
_code = 200; _code = 200;
_contentType = JSON_MIMETYPE; _contentType = FPSTR(CONTENT_TYPE_JSON);
if(isArray) if(isArray)
_root = _jsonBuffer.createNestedArray(); _root = _jsonBuffer.createNestedArray();
else else

Wyświetl plik

@ -209,8 +209,12 @@
#include "../usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h" #include "../usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h"
#endif #endif
#ifdef USERMOD_MAX17048
#include "../usermods/MAX17048_v2/usermod_max17048.h"
#endif
#ifdef USERMOD_TETRISAI #ifdef USERMOD_TETRISAI
#include "../usermods/TetrisAI_v2/usermod_v2_tetrisai.h" #include "../usermods/TetrisAI_v2/usermod_v2_tetrisai.h"
#endif #endif
void registerUsermods() void registerUsermods()
@ -410,6 +414,10 @@ void registerUsermods()
usermods.add(new StairwayWipeUsermod()); usermods.add(new StairwayWipeUsermod());
#endif #endif
#ifdef USERMOD_MAX17048
usermods.add(new Usermod_MAX17048());
#endif
#ifdef USERMOD_TETRISAI #ifdef USERMOD_TETRISAI
usermods.add(new TetrisAIUsermod()); usermods.add(new TetrisAIUsermod());
#endif #endif

Wyświetl plik

@ -228,7 +228,6 @@ bool requestJSONBufferLock(uint8_t module)
DEBUG_PRINT(F("JSON buffer locked. (")); DEBUG_PRINT(F("JSON buffer locked. ("));
DEBUG_PRINT(jsonBufferLock); DEBUG_PRINT(jsonBufferLock);
DEBUG_PRINTLN(")"); DEBUG_PRINTLN(")");
fileDoc = pDoc; // used for applying presets (presets.cpp)
pDoc->clear(); pDoc->clear();
return true; return true;
} }
@ -239,7 +238,6 @@ void releaseJSONBufferLock()
DEBUG_PRINT(F("JSON buffer released. (")); DEBUG_PRINT(F("JSON buffer released. ("));
DEBUG_PRINT(jsonBufferLock); DEBUG_PRINT(jsonBufferLock);
DEBUG_PRINTLN(")"); DEBUG_PRINTLN(")");
fileDoc = nullptr;
jsonBufferLock = 0; jsonBufferLock = 0;
} }
@ -265,8 +263,8 @@ uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLe
} else return 0; } else return 0;
} }
if (src == JSON_palette_names && mode > GRADIENT_PALETTE_COUNT) { if (src == JSON_palette_names && mode > (GRADIENT_PALETTE_COUNT + 13)) {
snprintf_P(dest, maxLen, PSTR("~ Custom %d~"), 255-mode); snprintf_P(dest, maxLen, PSTR("~ Custom %d ~"), 255-mode);
dest[maxLen-1] = '\0'; dest[maxLen-1] = '\0';
return strlen(dest); return strlen(dest);
} }

Wyświetl plik

@ -240,10 +240,11 @@ void WLED::loop()
DEBUG_PRINT(F("Runtime: ")); DEBUG_PRINTLN(millis()); DEBUG_PRINT(F("Runtime: ")); DEBUG_PRINTLN(millis());
DEBUG_PRINT(F("Unix time: ")); toki.printTime(toki.getTime()); DEBUG_PRINT(F("Unix time: ")); toki.printTime(toki.getTime());
DEBUG_PRINT(F("Free heap: ")); DEBUG_PRINTLN(ESP.getFreeHeap()); DEBUG_PRINT(F("Free heap: ")); DEBUG_PRINTLN(ESP.getFreeHeap());
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) #if defined(ARDUINO_ARCH_ESP32)
if (psramFound()) { if (psramFound()) {
DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB"); DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB");
DEBUG_PRINT(F("Free PSRAM: ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB"); DEBUG_PRINT(F("Free PSRAM: ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB");
if (!psramSafe) DEBUG_PRINTLN(F("Not using PSRAM."));
} }
#endif #endif
DEBUG_PRINT(F("Wifi state: ")); DEBUG_PRINTLN(WiFi.status()); DEBUG_PRINT(F("Wifi state: ")); DEBUG_PRINTLN(WiFi.status());
@ -361,56 +362,26 @@ void WLED::setup()
DEBUG_PRINT(F(", speed ")); DEBUG_PRINT(ESP.getFlashChipSpeed()/1000000);DEBUG_PRINTLN(F("MHz.")); DEBUG_PRINT(F(", speed ")); DEBUG_PRINT(ESP.getFlashChipSpeed()/1000000);DEBUG_PRINTLN(F("MHz."));
#else #else
DEBUG_PRINT(F("esp8266 ")); DEBUG_PRINT(F("esp8266 @ ")); DEBUG_PRINT(ESP.getCpuFreqMHz()); DEBUG_PRINT(F("MHz.\nCore: "));
DEBUG_PRINTLN(ESP.getCoreVersion()); DEBUG_PRINTLN(ESP.getCoreVersion());
DEBUG_PRINT(F("FLASH: ")); DEBUG_PRINT((ESP.getFlashChipSize()/1024)/1024); DEBUG_PRINTLN(F(" MB"));
#endif #endif
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap()); DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) #if defined(ARDUINO_ARCH_ESP32)
/* // BOARD_HAS_PSRAM also means that a compiler flag "-mfix-esp32-psram-cache-issue" was used and so PSRAM is safe to use on rev.1 ESP32
* The following code is obsolete as PinManager::isPinOK() will return false for reserved GPIO. #if !defined(BOARD_HAS_PSRAM) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3))
* Additionally xml.cpp will inform UI about reserved GPIO. if (psramFound() && ESP.getChipRevision() < 3) psramSafe = false;
* if (!psramSafe) DEBUG_PRINTLN(F("Not using PSRAM."));
#if defined(CONFIG_IDF_TARGET_ESP32S3)
// S3: reserve GPIO 33-37 for "octal" PSRAM
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);
#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)
managed_pin_type pins[] = { {26, true}, {27, true}, {28, true}, {29, true}, {30, true}, {31, true}, {32, true} };
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
// C3: reserve GPIO 12-17 for PSRAM (may fail due to isPinOk() but that will also prevent other allocation)
managed_pin_type pins[] = { {12, true}, {13, true}, {14, true}, {15, true}, {16, true}, {17, true} };
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
#else
// GPIO16/GPIO17 reserved for SPI RAM
managed_pin_type pins[] = { {16, true}, {17, true} };
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
#endif #endif
*/ pDoc = new PSRAMDynamicJsonDocument((psramSafe && psramFound() ? 2 : 1)*JSON_BUFFER_SIZE);
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM) DEBUG_PRINT(F("JSON buffer allocated: ")); DEBUG_PRINTLN((psramSafe && psramFound() ? 2 : 1)*JSON_BUFFER_SIZE);
pDoc = new PSRAMDynamicJsonDocument(2*JSON_BUFFER_SIZE); // if the above fails requestJsonBufferLock() will always return false preventing crashes
if (!pDoc) pDoc = new PSRAMDynamicJsonDocument(JSON_BUFFER_SIZE); // falback if double sized buffer could not be allocated
// if the above still fails requestJsonBufferLock() will always return false preventing crashes
if (psramFound()) { if (psramFound()) {
DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB"); DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB");
DEBUG_PRINT(F("Free PSRAM : ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB"); DEBUG_PRINT(F("Free PSRAM : ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB");
} }
#else
if (!pDoc) pDoc = &gDoc; // just in case ... (it should be globally assigned)
DEBUG_PRINTLN(F("PSRAM not used."));
#endif
#endif #endif
#if defined(ARDUINO_ESP32_PICO)
// special handling for PICO-D4: gpio16+17 are in use for onboard SPI FLASH (not PSRAM)
managed_pin_type pins[] = { {16, true}, {17, true} };
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
#endif
//DEBUG_PRINT(F("LEDs inited. heap usage ~"));
//DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
#if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST) #if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST)
pinManager.allocatePin(hardwareTX, true, PinOwner::DebugOut); // TX (GPIO1 on ESP32) reserved for debug output pinManager.allocatePin(hardwareTX, true, PinOwner::DebugOut); // TX (GPIO1 on ESP32) reserved for debug output
@ -452,6 +423,7 @@ void WLED::setup()
DEBUG_PRINTLN(F("Reading config")); DEBUG_PRINTLN(F("Reading config"));
deserializeConfigFromFS(); deserializeConfigFromFS();
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
#if defined(STATUSLED) && STATUSLED>=0 #if defined(STATUSLED) && STATUSLED>=0
if (!pinManager.isPinAllocated(STATUSLED)) { if (!pinManager.isPinAllocated(STATUSLED)) {
@ -555,7 +527,7 @@ void WLED::setup()
void WLED::beginStrip() void WLED::beginStrip()
{ {
// Initialize NeoPixel Strip and button // Initialize NeoPixel Strip and button
strip.finalizeInit(); // busses created during deserializeConfig() strip.finalizeInit(); // busses created during deserializeConfig() if config existed
strip.makeAutoSegments(); strip.makeAutoSegments();
strip.setBrightness(0); strip.setBrightness(0);
strip.setShowCallback(handleOverlayDraw); strip.setShowCallback(handleOverlayDraw);

Wyświetl plik

@ -3,12 +3,12 @@
/* /*
Main sketch, global variable declarations Main sketch, global variable declarations
@title WLED project sketch @title WLED project sketch
@version 0.15.0-b1 @version 0.15.0-b3
@author Christian Schwinne @author Christian Schwinne
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2403190 #define VERSION 2404120
//uncomment this if you have a "my_config.h" file you'd like to use //uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG //#define WLED_USE_MY_CONFIG
@ -158,15 +158,16 @@
// The following is a construct to enable code to compile without it. // The following is a construct to enable code to compile without it.
// There is a code that will still not use PSRAM though: // There is a code that will still not use PSRAM though:
// AsyncJsonResponse is a derived class that implements DynamicJsonDocument (AsyncJson-v6.h) // AsyncJsonResponse is a derived class that implements DynamicJsonDocument (AsyncJson-v6.h)
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM) #if defined(ARDUINO_ARCH_ESP32)
extern bool psramSafe;
struct PSRAM_Allocator { struct PSRAM_Allocator {
void* allocate(size_t size) { void* allocate(size_t size) {
if (psramFound()) return ps_malloc(size); // use PSRAM if it exists if (psramSafe && psramFound()) return ps_malloc(size); // use PSRAM if it exists
else return malloc(size); // fallback else return malloc(size); // fallback
} }
void* reallocate(void* ptr, size_t new_size) { void* reallocate(void* ptr, size_t new_size) {
if (psramFound()) return ps_realloc(ptr, new_size); // use PSRAM if it exists if (psramSafe && psramFound()) return ps_realloc(ptr, new_size); // use PSRAM if it exists
else return realloc(ptr, new_size); // fallback else return realloc(ptr, new_size); // fallback
} }
void deallocate(void* pointer) { void deallocate(void* pointer) {
free(pointer); free(pointer);
@ -348,6 +349,11 @@ WLED_GLOBAL bool useGlobalLedBuffer _INIT(true); // double buffering enabled on
#endif #endif
WLED_GLOBAL bool correctWB _INIT(false); // CCT color correction of RGB color WLED_GLOBAL bool correctWB _INIT(false); // CCT color correction of RGB color
WLED_GLOBAL bool cctFromRgb _INIT(false); // CCT is calculated from RGB instead of using seg.cct WLED_GLOBAL bool cctFromRgb _INIT(false); // CCT is calculated from RGB instead of using seg.cct
#ifdef WLED_USE_IC_CCT
WLED_GLOBAL bool cctICused _INIT(true); // CCT IC used (Athom 15W bulbs)
#else
WLED_GLOBAL bool cctICused _INIT(false); // CCT IC used (Athom 15W bulbs)
#endif
WLED_GLOBAL bool gammaCorrectCol _INIT(true); // use gamma correction on colors WLED_GLOBAL bool gammaCorrectCol _INIT(true); // use gamma correction on colors
WLED_GLOBAL bool gammaCorrectBri _INIT(false); // use gamma correction on brightness WLED_GLOBAL bool gammaCorrectBri _INIT(false); // use gamma correction on brightness
WLED_GLOBAL float gammaCorrectVal _INIT(2.8f); // gamma correction value WLED_GLOBAL float gammaCorrectVal _INIT(2.8f); // gamma correction value
@ -692,7 +698,6 @@ WLED_GLOBAL uint16_t olen _INIT(0);
WLED_GLOBAL size_t fsBytesUsed _INIT(0); WLED_GLOBAL size_t fsBytesUsed _INIT(0);
WLED_GLOBAL size_t fsBytesTotal _INIT(0); WLED_GLOBAL size_t fsBytesTotal _INIT(0);
WLED_GLOBAL unsigned long presetsModifiedTime _INIT(0L); WLED_GLOBAL unsigned long presetsModifiedTime _INIT(0L);
WLED_GLOBAL JsonDocument* fileDoc;
WLED_GLOBAL bool doCloseFile _INIT(false); WLED_GLOBAL bool doCloseFile _INIT(false);
// presets // presets
@ -706,6 +711,8 @@ WLED_GLOBAL byte optionType;
WLED_GLOBAL bool doSerializeConfig _INIT(false); // flag to initiate saving of config WLED_GLOBAL bool doSerializeConfig _INIT(false); // flag to initiate saving of config
WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers
WLED_GLOBAL bool psramSafe _INIT(true); // is it safe to use PSRAM (on ESP32 rev.1; compiler fix used "-mfix-esp32-psram-cache-issue")
// status led // status led
#if defined(STATUSLED) #if defined(STATUSLED)
WLED_GLOBAL unsigned long ledStatusLastMillis _INIT(0); WLED_GLOBAL unsigned long ledStatusLastMillis _INIT(0);
@ -781,7 +788,7 @@ WLED_GLOBAL int8_t spi_sclk _INIT(SPISCLKPIN);
#endif #endif
// global ArduinoJson buffer // global ArduinoJson buffer
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM) #if defined(ARDUINO_ARCH_ESP32)
WLED_GLOBAL JsonDocument *pDoc _INIT(nullptr); WLED_GLOBAL JsonDocument *pDoc _INIT(nullptr);
#else #else
WLED_GLOBAL StaticJsonDocument<JSON_BUFFER_SIZE> gDoc; WLED_GLOBAL StaticJsonDocument<JSON_BUFFER_SIZE> gDoc;

Wyświetl plik

@ -18,36 +18,6 @@ static const char s_unlock_ota [] PROGMEM = "Please unlock OTA in security setti
static const char s_unlock_cfg [] PROGMEM = "Please unlock settings using PIN code!"; static const char s_unlock_cfg [] PROGMEM = "Please unlock settings using PIN code!";
static const char s_notimplemented[] PROGMEM = "Not implemented"; static const char s_notimplemented[] PROGMEM = "Not implemented";
static const char s_accessdenied[] PROGMEM = "Access Denied"; static const char s_accessdenied[] PROGMEM = "Access Denied";
static const char s_javascript[] PROGMEM = "application/javascript";
static const char s_json[] = "application/json"; // AsyncJson-v6.h
static const char s_html[] PROGMEM = "text/html";
static const char s_plain[] = "text/plain"; // Espalexa.h
static const char s_css[] PROGMEM = "text/css";
static const char s_png[] PROGMEM = "image/png";
static const char s_gif[] PROGMEM = "image/gif";
static const char s_jpg[] PROGMEM = "image/jpeg";
static const char s_ico[] PROGMEM = "image/x-icon";
//static const char s_xml[] PROGMEM = "text/xml";
//static const char s_pdf[] PROGMEM = "application/x-pdf";
//static const char s_zip[] PROGMEM = "application/x-zip";
//static const char s_gz[] PROGMEM = "application/x-gzip";
String getFileContentType(String &filename) {
if (filename.endsWith(F(".htm"))) return FPSTR(s_html);
else if (filename.endsWith(F(".html"))) return FPSTR(s_html);
else if (filename.endsWith(F(".css"))) return FPSTR(s_css);
else if (filename.endsWith(F(".js"))) return FPSTR(s_javascript);
else if (filename.endsWith(F(".json"))) return s_json;
else if (filename.endsWith(F(".png"))) return FPSTR(s_png);
else if (filename.endsWith(F(".gif"))) return FPSTR(s_gif);
else if (filename.endsWith(F(".jpg"))) return FPSTR(s_jpg);
else if (filename.endsWith(F(".ico"))) return FPSTR(s_ico);
// else if (filename.endsWith(F(".xml"))) return FPSTR(s_xml);
// else if (filename.endsWith(F(".pdf"))) return FPSTR(s_pdf);
// else if (filename.endsWith(F(".zip"))) return FPSTR(s_zip);
// else if (filename.endsWith(F(".gz"))) return FPSTR(s_gz);
return s_plain;
}
//Is this an IP? //Is this an IP?
static bool isIp(String str) { static bool isIp(String str) {
@ -183,7 +153,7 @@ static String msgProcessor(const String& var)
static void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) { static void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) {
if (!correctPIN) { if (!correctPIN) {
if (final) request->send(401, FPSTR(s_plain), FPSTR(s_unlock_cfg)); if (final) request->send(401, FPSTR(CONTENT_TYPE_PLAIN), FPSTR(s_unlock_cfg));
return; return;
} }
if (!index) { if (!index) {
@ -204,10 +174,10 @@ static void handleUpload(AsyncWebServerRequest *request, const String& filename,
request->_tempFile.close(); request->_tempFile.close();
if (filename.indexOf(F("cfg.json")) >= 0) { // check for filename with or without slash if (filename.indexOf(F("cfg.json")) >= 0) { // check for filename with or without slash
doReboot = true; doReboot = true;
request->send(200, FPSTR(s_plain), F("Configuration restore successful.\nRebooting...")); request->send(200, FPSTR(CONTENT_TYPE_PLAIN), F("Configuration restore successful.\nRebooting..."));
} else { } else {
if (filename.indexOf(F("palette")) >= 0 && filename.indexOf(F(".json")) >= 0) strip.loadCustomPalettes(); if (filename.indexOf(F("palette")) >= 0 && filename.indexOf(F(".json")) >= 0) strip.loadCustomPalettes();
request->send(200, FPSTR(s_plain), F("File Uploaded!")); request->send(200, FPSTR(CONTENT_TYPE_PLAIN), F("File Uploaded!"));
} }
cacheInvalidate++; cacheInvalidate++;
} }
@ -259,24 +229,24 @@ void initServer()
#ifdef WLED_ENABLE_WEBSOCKETS #ifdef WLED_ENABLE_WEBSOCKETS
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
server.on(SET_F("/liveview2D"), HTTP_GET, [](AsyncWebServerRequest *request) { server.on(F("/liveview2D"), HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, "", 200, FPSTR(s_html), PAGE_liveviewws2D, PAGE_liveviewws2D_length); handleStaticContent(request, "", 200, FPSTR(CONTENT_TYPE_HTML), PAGE_liveviewws2D, PAGE_liveviewws2D_length);
}); });
#endif #endif
#endif #endif
server.on(SET_F("/liveview"), HTTP_GET, [](AsyncWebServerRequest *request) { server.on(F("/liveview"), HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, "", 200, FPSTR(s_html), PAGE_liveview, PAGE_liveview_length); handleStaticContent(request, "", 200, FPSTR(CONTENT_TYPE_HTML), PAGE_liveview, PAGE_liveview_length);
}); });
//settings page //settings page
server.on(SET_F("/settings"), HTTP_GET, [](AsyncWebServerRequest *request){ server.on(F("/settings"), HTTP_GET, [](AsyncWebServerRequest *request){
serveSettings(request); serveSettings(request);
}); });
// "/settings/settings.js&p=x" request also handled by serveSettings() // "/settings/settings.js&p=x" request also handled by serveSettings()
static const char _style_css[] PROGMEM = "/style.css"; static const char _style_css[] PROGMEM = "/style.css";
server.on(_style_css, HTTP_GET, [](AsyncWebServerRequest *request) { server.on(_style_css, HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, FPSTR(_style_css), 200, FPSTR(s_css), PAGE_settingsCss, PAGE_settingsCss_length); handleStaticContent(request, FPSTR(_style_css), 200, FPSTR(CONTENT_TYPE_CSS), PAGE_settingsCss, PAGE_settingsCss_length);
}); });
static const char _favicon_ico[] PROGMEM = "/favicon.ico"; static const char _favicon_ico[] PROGMEM = "/favicon.ico";
@ -287,28 +257,29 @@ void initServer()
static const char _skin_css[] PROGMEM = "/skin.css"; static const char _skin_css[] PROGMEM = "/skin.css";
server.on(_skin_css, HTTP_GET, [](AsyncWebServerRequest *request) { server.on(_skin_css, HTTP_GET, [](AsyncWebServerRequest *request) {
if (handleFileRead(request, FPSTR(_skin_css))) return; if (handleFileRead(request, FPSTR(_skin_css))) return;
AsyncWebServerResponse *response = request->beginResponse(200, FPSTR(s_css)); AsyncWebServerResponse *response = request->beginResponse(200, FPSTR(CONTENT_TYPE_CSS));
request->send(response); request->send(response);
}); });
server.on(SET_F("/welcome"), HTTP_GET, [](AsyncWebServerRequest *request){ server.on(F("/welcome"), HTTP_GET, [](AsyncWebServerRequest *request){
serveSettings(request); serveSettings(request);
}); });
server.on(SET_F("/reset"), HTTP_GET, [](AsyncWebServerRequest *request){ server.on(F("/reset"), HTTP_GET, [](AsyncWebServerRequest *request){
serveMessage(request, 200,F("Rebooting now..."),F("Please wait ~10 seconds..."),129); serveMessage(request, 200,F("Rebooting now..."),F("Please wait ~10 seconds..."),129);
doReboot = true; doReboot = true;
}); });
server.on(SET_F("/settings"), HTTP_POST, [](AsyncWebServerRequest *request){ server.on(F("/settings"), HTTP_POST, [](AsyncWebServerRequest *request){
serveSettings(request, true); serveSettings(request, true);
}); });
server.on(SET_F("/json"), HTTP_GET, [](AsyncWebServerRequest *request){ const static char _json[] PROGMEM = "/json";
server.on(FPSTR(_json), HTTP_GET, [](AsyncWebServerRequest *request){
serveJson(request); serveJson(request);
}); });
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler(F("/json"), [](AsyncWebServerRequest *request) { AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler(FPSTR(_json), [](AsyncWebServerRequest *request) {
bool verboseResponse = false; bool verboseResponse = false;
bool isConfig = false; bool isConfig = false;
@ -356,33 +327,33 @@ void initServer()
doSerializeConfig = true; //serializeConfig(); //Save new settings to FS doSerializeConfig = true; //serializeConfig(); //Save new settings to FS
} }
} }
request->send(200, s_json, F("{\"success\":true}")); request->send(200, CONTENT_TYPE_JSON, F("{\"success\":true}"));
}, JSON_BUFFER_SIZE); }, JSON_BUFFER_SIZE);
server.addHandler(handler); server.addHandler(handler);
server.on(SET_F("/version"), HTTP_GET, [](AsyncWebServerRequest *request){ server.on(F("/version"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(s_plain), (String)VERSION); request->send(200, FPSTR(CONTENT_TYPE_PLAIN), (String)VERSION);
}); });
server.on(SET_F("/uptime"), HTTP_GET, [](AsyncWebServerRequest *request){ server.on(F("/uptime"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(s_plain), (String)millis()); request->send(200, FPSTR(CONTENT_TYPE_PLAIN), (String)millis());
}); });
server.on(SET_F("/freeheap"), HTTP_GET, [](AsyncWebServerRequest *request){ server.on(F("/freeheap"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(s_plain), (String)ESP.getFreeHeap()); request->send(200, FPSTR(CONTENT_TYPE_PLAIN), (String)ESP.getFreeHeap());
}); });
#ifdef WLED_ENABLE_USERMOD_PAGE #ifdef WLED_ENABLE_USERMOD_PAGE
server.on("/u", HTTP_GET, [](AsyncWebServerRequest *request) { server.on("/u", HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, "", 200, FPSTR(s_html), PAGE_usermod, PAGE_usermod_length); handleStaticContent(request, "", 200, FPSTR(CONTENT_TYPE_HTML), PAGE_usermod, PAGE_usermod_length);
}); });
#endif #endif
server.on(SET_F("/teapot"), HTTP_GET, [](AsyncWebServerRequest *request){ server.on(F("/teapot"), HTTP_GET, [](AsyncWebServerRequest *request){
serveMessage(request, 418, F("418. I'm a teapot."), F("(Tangible Embedded Advanced Project Of Twinkling)"), 254); serveMessage(request, 418, F("418. I'm a teapot."), F("(Tangible Embedded Advanced Project Of Twinkling)"), 254);
}); });
server.on(SET_F("/upload"), HTTP_POST, [](AsyncWebServerRequest *request) {}, server.on(F("/upload"), HTTP_POST, [](AsyncWebServerRequest *request) {},
[](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, [](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data,
size_t len, bool final) {handleUpload(request, filename, index, data, len, final);} size_t len, bool final) {handleUpload(request, filename, index, data, len, final);}
); );
@ -453,7 +424,7 @@ void initServer()
#ifdef WLED_ENABLE_DMX #ifdef WLED_ENABLE_DMX
server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){ server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, FPSTR(s_html), PAGE_dmxmap , dmxProcessor); request->send_P(200, FPSTR(CONTENT_TYPE_HTML), PAGE_dmxmap , dmxProcessor);
}); });
#else #else
server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){ server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){
@ -464,7 +435,7 @@ void initServer()
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
if (captivePortal(request)) return; if (captivePortal(request)) return;
if (!showWelcomePage || request->hasArg(F("sliders"))) { if (!showWelcomePage || request->hasArg(F("sliders"))) {
handleStaticContent(request, F("/index.htm"), 200, FPSTR(s_html), PAGE_index, PAGE_index_L); handleStaticContent(request, F("/index.htm"), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_index, PAGE_index_L);
} else { } else {
serveSettings(request); serveSettings(request);
} }
@ -473,20 +444,20 @@ void initServer()
#ifdef WLED_ENABLE_PIXART #ifdef WLED_ENABLE_PIXART
static const char _pixart_htm[] PROGMEM = "/pixart.htm"; static const char _pixart_htm[] PROGMEM = "/pixart.htm";
server.on(_pixart_htm, HTTP_GET, [](AsyncWebServerRequest *request) { server.on(_pixart_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, FPSTR(_pixart_htm), 200, FPSTR(s_html), PAGE_pixart, PAGE_pixart_L); handleStaticContent(request, FPSTR(_pixart_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_pixart, PAGE_pixart_L);
}); });
#endif #endif
#ifndef WLED_DISABLE_PXMAGIC #ifndef WLED_DISABLE_PXMAGIC
static const char _pxmagic_htm[] PROGMEM = "/pxmagic.htm"; static const char _pxmagic_htm[] PROGMEM = "/pxmagic.htm";
server.on(_pxmagic_htm, HTTP_GET, [](AsyncWebServerRequest *request) { server.on(_pxmagic_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, FPSTR(_pxmagic_htm), 200, FPSTR(s_html), PAGE_pxmagic, PAGE_pxmagic_L); handleStaticContent(request, FPSTR(_pxmagic_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_pxmagic, PAGE_pxmagic_L);
}); });
#endif #endif
static const char _cpal_htm[] PROGMEM = "/cpal.htm"; static const char _cpal_htm[] PROGMEM = "/cpal.htm";
server.on(_cpal_htm, HTTP_GET, [](AsyncWebServerRequest *request) { server.on(_cpal_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, FPSTR(_cpal_htm), 200, FPSTR(s_html), PAGE_cpal, PAGE_cpal_L); handleStaticContent(request, FPSTR(_cpal_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_cpal, PAGE_cpal_L);
}); });
#ifdef WLED_ENABLE_WEBSOCKETS #ifdef WLED_ENABLE_WEBSOCKETS
@ -511,7 +482,7 @@ void initServer()
#ifndef WLED_DISABLE_ALEXA #ifndef WLED_DISABLE_ALEXA
if(espalexa.handleAlexaApiCall(request)) return; if(espalexa.handleAlexaApiCall(request)) return;
#endif #endif
handleStaticContent(request, request->url(), 404, FPSTR(s_html), PAGE_404, PAGE_404_length); handleStaticContent(request, request->url(), 404, FPSTR(CONTENT_TYPE_HTML), PAGE_404, PAGE_404_length);
}); });
} }
@ -522,7 +493,7 @@ void serveMessage(AsyncWebServerRequest* request, uint16_t code, const String& h
messageSub = subl; messageSub = subl;
optionType = optionT; optionType = optionT;
request->send_P(code, FPSTR(s_html), PAGE_msg, msgProcessor); request->send_P(code, FPSTR(CONTENT_TYPE_HTML), PAGE_msg, msgProcessor);
} }
@ -530,7 +501,7 @@ void serveJsonError(AsyncWebServerRequest* request, uint16_t code, uint16_t erro
{ {
AsyncJsonResponse *response = new AsyncJsonResponse(64); AsyncJsonResponse *response = new AsyncJsonResponse(64);
if (error < ERR_NOT_IMPL) response->addHeader(F("Retry-After"), F("1")); if (error < ERR_NOT_IMPL) response->addHeader(F("Retry-After"), F("1"));
response->setContentType(s_json); response->setContentType(CONTENT_TYPE_JSON);
response->setCode(code); response->setCode(code);
JsonObject obj = response->getRoot(); JsonObject obj = response->getRoot();
obj[F("error")] = error; obj[F("error")] = error;
@ -546,12 +517,12 @@ void serveSettingsJS(AsyncWebServerRequest* request)
byte subPage = request->arg(F("p")).toInt(); byte subPage = request->arg(F("p")).toInt();
if (subPage > 10) { if (subPage > 10) {
strcpy_P(buf, PSTR("alert('Settings for this request are not implemented.');")); strcpy_P(buf, PSTR("alert('Settings for this request are not implemented.');"));
request->send(501, FPSTR(s_javascript), buf); request->send(501, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
return; return;
} }
if (subPage > 0 && !correctPIN && strlen(settingsPIN)>0) { if (subPage > 0 && !correctPIN && strlen(settingsPIN)>0) {
strcpy_P(buf, PSTR("alert('PIN incorrect.');")); strcpy_P(buf, PSTR("alert('PIN incorrect.');"));
request->send(401, FPSTR(s_javascript), buf); request->send(401, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
return; return;
} }
strcat_P(buf,PSTR("function GetV(){var d=document;")); strcat_P(buf,PSTR("function GetV(){var d=document;"));
@ -559,7 +530,7 @@ void serveSettingsJS(AsyncWebServerRequest* request)
strcat_P(buf,PSTR("}")); strcat_P(buf,PSTR("}"));
AsyncWebServerResponse *response; AsyncWebServerResponse *response;
response = request->beginResponse(200, FPSTR(s_javascript), buf); response = request->beginResponse(200, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
response->addHeader(F("Cache-Control"), F("no-store")); response->addHeader(F("Cache-Control"), F("no-store"));
response->addHeader(F("Expires"), F("0")); response->addHeader(F("Expires"), F("0"));
request->send(response); request->send(response);
@ -640,7 +611,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) {
} }
int code = 200; int code = 200;
String contentType = FPSTR(s_html); String contentType = FPSTR(CONTENT_TYPE_HTML);
const uint8_t* content; const uint8_t* content;
size_t len; size_t len;
@ -666,7 +637,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) {
return; return;
} }
case SUBPAGE_PINREQ : content = PAGE_settings_pin; len = PAGE_settings_pin_length; code = 401; break; case SUBPAGE_PINREQ : content = PAGE_settings_pin; len = PAGE_settings_pin_length; code = 401; break;
case SUBPAGE_CSS : content = PAGE_settingsCss; len = PAGE_settingsCss_length; contentType = FPSTR(s_css); break; case SUBPAGE_CSS : content = PAGE_settingsCss; len = PAGE_settingsCss_length; contentType = FPSTR(CONTENT_TYPE_CSS); break;
case SUBPAGE_JS : serveSettingsJS(request); return; case SUBPAGE_JS : serveSettingsJS(request); return;
case SUBPAGE_WELCOME : content = PAGE_welcome; len = PAGE_welcome_length; break; case SUBPAGE_WELCOME : content = PAGE_welcome; len = PAGE_welcome_length; break;
default: content = PAGE_settings; len = PAGE_settings_length; break; default: content = PAGE_settings; len = PAGE_settings_length; break;

Wyświetl plik

@ -55,7 +55,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
} else { } else {
verboseResponse = deserializeState(root); verboseResponse = deserializeState(root);
} }
releaseJSONBufferLock(); // will clean fileDoc releaseJSONBufferLock();
if (!interfaceUpdateCallMode) { // individual client response only needed if no WS broadcast soon if (!interfaceUpdateCallMode) { // individual client response only needed if no WS broadcast soon
if (verboseResponse) { if (verboseResponse) {
@ -102,7 +102,6 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
void sendDataWs(AsyncWebSocketClient * client) void sendDataWs(AsyncWebSocketClient * client)
{ {
if (!ws.count()) return; if (!ws.count()) return;
AsyncWebSocketMessageBuffer * buffer;
if (!requestJSONBufferLock(12)) { if (!requestJSONBufferLock(12)) {
if (client) { if (client) {
@ -129,7 +128,7 @@ void sendDataWs(AsyncWebSocketClient * client)
return; return;
} }
#endif #endif
buffer = ws.makeBuffer(len); // will not allocate correct memory sometimes on ESP8266 AsyncWebSocketBuffer buffer(len);
#ifdef ESP8266 #ifdef ESP8266
size_t heap2 = ESP.getFreeHeap(); size_t heap2 = ESP.getFreeHeap();
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap()); DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
@ -141,23 +140,18 @@ void sendDataWs(AsyncWebSocketClient * client)
DEBUG_PRINTLN(F("WS buffer allocation failed.")); DEBUG_PRINTLN(F("WS buffer allocation failed."));
ws.closeAll(1013); //code 1013 = temporary overload, try again later ws.closeAll(1013); //code 1013 = temporary overload, try again later
ws.cleanupClients(0); //disconnect all clients to release memory ws.cleanupClients(0); //disconnect all clients to release memory
ws._cleanBuffers();
return; //out of memory return; //out of memory
} }
serializeJson(*pDoc, (char *)buffer.data(), len);
buffer->lock();
serializeJson(*pDoc, (char *)buffer->get(), len);
DEBUG_PRINT(F("Sending WS data ")); DEBUG_PRINT(F("Sending WS data "));
if (client) { if (client) {
client->text(buffer); client->text(std::move(buffer));
DEBUG_PRINTLN(F("to a single client.")); DEBUG_PRINTLN(F("to a single client."));
} else { } else {
ws.textAll(buffer); ws.textAll(std::move(buffer));
DEBUG_PRINTLN(F("to multiple clients.")); DEBUG_PRINTLN(F("to multiple clients."));
} }
buffer->unlock();
ws._cleanBuffers();
releaseJSONBufferLock(); releaseJSONBufferLock();
} }
@ -187,11 +181,10 @@ bool sendLiveLedsWs(uint32_t wsClient)
#endif #endif
size_t bufSize = pos + (used/n)*3; size_t bufSize = pos + (used/n)*3;
AsyncWebSocketMessageBuffer * wsBuf = ws.makeBuffer(bufSize); AsyncWebSocketBuffer wsBuf(bufSize);
if (!wsBuf) return false; //out of memory if (!wsBuf) return false; //out of memory
uint8_t* buffer = wsBuf->get(); uint8_t* buffer = reinterpret_cast<uint8_t*>(wsBuf.data());
if (!buffer) return false; //out of memory if (!buffer) return false; //out of memory
wsBuf->lock(); // protect buffer from being cleaned by another WS instance
buffer[0] = 'L'; buffer[0] = 'L';
buffer[1] = 1; //version buffer[1] = 1; //version
@ -218,9 +211,7 @@ bool sendLiveLedsWs(uint32_t wsClient)
buffer[pos++] = scale8(qadd8(w, b), strip.getBrightness()); //B buffer[pos++] = scale8(qadd8(w, b), strip.getBrightness()); //B
} }
wsc->binary(wsBuf); wsc->binary(std::move(wsBuf));
wsBuf->unlock(); // un-protect buffer
ws._cleanBuffers();
return true; return true;
} }

12
wled00/xml.cpp 100755 → 100644
Wyświetl plik

@ -145,10 +145,13 @@ void appendGPIOinfo() {
oappend(SET_F("d.rsvd=[22,23,24,25,26,27,28,29,30,31,32")); oappend(SET_F("d.rsvd=[22,23,24,25,26,27,28,29,30,31,32"));
#elif defined(CONFIG_IDF_TARGET_ESP32S3) #elif defined(CONFIG_IDF_TARGET_ESP32S3)
oappend(SET_F("d.rsvd=[19,20,22,23,24,25,26,27,28,29,30,31,32")); // includes 19+20 for USB OTG (JTAG) oappend(SET_F("d.rsvd=[19,20,22,23,24,25,26,27,28,29,30,31,32")); // includes 19+20 for USB OTG (JTAG)
if (psramFound()) oappend(SET_F(",33,34,35,36,37")); // in use for "octal" PSRAM or "octal" FLASH -seems that octal PSRAM is very common on S3.
#elif defined(CONFIG_IDF_TARGET_ESP32C3) #elif defined(CONFIG_IDF_TARGET_ESP32C3)
oappend(SET_F("d.rsvd=[11,12,13,14,15,16,17")); oappend(SET_F("d.rsvd=[11,12,13,14,15,16,17"));
#elif defined(ESP32) #elif defined(ESP32)
oappend(SET_F("d.rsvd=[6,7,8,9,10,11,24,28,29,30,31,37,38")); oappend(SET_F("d.rsvd=[6,7,8,9,10,11,24,28,29,30,31,37,38"));
if (!pinManager.isPinOk(16,false)) oappend(SET_F(",16")); // covers PICO & WROVER
if (!pinManager.isPinOk(17,false)) oappend(SET_F(",17")); // covers PICO & WROVER
#else #else
oappend(SET_F("d.rsvd=[6,7,8,9,10,11")); oappend(SET_F("d.rsvd=[6,7,8,9,10,11"));
#endif #endif
@ -163,14 +166,6 @@ void appendGPIOinfo() {
//Note: Using pin 3 (RX) disables Adalight / Serial JSON //Note: Using pin 3 (RX) disables Adalight / Serial JSON
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C3)
if (psramFound()) oappend(SET_F(",16,17")); // GPIO16 & GPIO17 reserved for SPI RAM on ESP32 (not on S2, S3 or C3)
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
if (psramFound()) oappend(SET_F(",33,34,35,36,37")); // in use for "octal" PSRAM or "octal" FLASH -seems that octal PSRAM is very common on S3.
#endif
#endif
#ifdef WLED_USE_ETHERNET #ifdef WLED_USE_ETHERNET
if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) { if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) {
for (uint8_t p=0; p<WLED_ETH_RSVD_PINS_COUNT; p++) { oappend(","); oappend(itoa(esp32_nonconfigurable_ethernet_pins[p].pin,nS,10)); } for (uint8_t p=0; p<WLED_ETH_RSVD_PINS_COUNT; p++) { oappend(","); oappend(itoa(esp32_nonconfigurable_ethernet_pins[p].pin,nS,10)); }
@ -360,6 +355,7 @@ void getSettingsJS(byte subPage, char* dest)
sappend('c',SET_F("MS"),autoSegments); sappend('c',SET_F("MS"),autoSegments);
sappend('c',SET_F("CCT"),correctWB); sappend('c',SET_F("CCT"),correctWB);
sappend('c',SET_F("IC"),cctICused);
sappend('c',SET_F("CR"),cctFromRgb); sappend('c',SET_F("CR"),cctFromRgb);
sappend('v',SET_F("CB"),strip.cctBlending); sappend('v',SET_F("CB"),strip.cctBlending);
sappend('v',SET_F("FR"),strip.getTargetFps()); sappend('v',SET_F("FR"),strip.getTargetFps());