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

Wyświetl plik

@ -1,5 +1,51 @@
## 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
- limit max PWM frequency (fix incorrect PWM resolution)
- Segment UI bugfix
@ -52,7 +98,7 @@
#### Build 2309120 till build 2402010
- 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.
- Github CI build system enhancements (#3718 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",
"version": "0.15.0-b1",
"version": "0.15.0-b3",
"description": "Tools for WLED project",
"main": "tools/cdata.js",
"directories": {
@ -26,7 +26,6 @@
"clean-css": "^5.3.3",
"html-minifier-terser": "^7.2.0",
"inliner": "^1.13.1",
"nodemon": "^3.0.2",
"zlib": "^1.0.5"
"nodemon": "^3.0.2"
}
}

Wyświetl plik

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

Wyświetl plik

@ -10,7 +10,11 @@
# ------------------------------------------------------------------------------
# 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
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}
# 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 = platformio/framework-arduinoespressif8266
platformio/toolchain-xtensa @ ~2.100300.220621 #2.40802.200502
platform_packages = platformio/toolchain-xtensa @ ~2.100300.220621 #2.40802.200502
platformio/tool-esptool #@ ~1.413.0
platformio/tool-esptoolpy #@ ~1.30000.0
## 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
;; platform_wled_default = ${common.arduino_core_3_2_0}
## 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_0_2}
;; platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7
;; platformio/toolchain-xtensa @ ~2.40802.200502
;; platformio/tool-esptool @ ~1.413.0
@ -143,8 +146,8 @@ lib_compat_mode = strict
lib_deps =
fastled/FastLED @ 3.6.0
IRremoteESP8266 @ 2.8.2
makuna/NeoPixelBus @ 2.7.5
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ^2.1.0
makuna/NeoPixelBus @ 2.7.9
https://github.com/Aircoookie/ESPAsyncWebServer.git @ 2.2.1
# for I2C interface
;Wire
# ESP-NOW library
@ -164,6 +167,9 @@ lib_deps =
#For ADS1115 sensor uncomment following
;adafruit/Adafruit BusIO @ 1.13.2
;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
;electroniccats/MPU6050 @1.0.1
# For -D USERMOD_ANIMARTRIX
@ -172,7 +178,7 @@ lib_deps =
# SHT85
;robtillaart/SHT85@~0.3.3
# Audioreactive usermod
;kosme/arduinoFFT @ 2.0.0
;kosme/arduinoFFT @ 2.0.1
extra_scripts = ${scripts_defaults.extra_scripts}
@ -223,7 +229,7 @@ lib_deps =
${env.lib_deps}
# additional build flags for 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]
;; 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
-Wshadow=compatible-local ;; emit warning in case a local variable "shadows" another local one
-DARDUINO_ARCH_ESP32 -DESP32
#-DCONFIG_LITTLEFS_FOR_IDF_3_2
-D CONFIG_ASYNC_TCP_USE_WDT=0
-DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3
default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
@ -310,14 +315,14 @@ platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_4m1m}
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}
monitor_filters = esp8266_exception_decoder
[env:nodemcuv2_160]
extends = env:nodemcuv2
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]
board = esp_wroom_02
@ -325,13 +330,13 @@ platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k}
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}
[env:esp8266_2m_160]
extends = env:esp8266_2m
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]
board = esp01_1m
@ -339,14 +344,14 @@ platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_1m128k}
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
lib_deps = ${esp8266.lib_deps}
[env:esp01_1m_full_160]
extends = env:esp01_1m_full
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
[env:esp32dev]
@ -354,7 +359,7 @@ board = esp32dev
platform = ${esp32.platform}
platform_packages = ${esp32.platform_packages}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32 #-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}
monitor_filters = esp32_exception_decoder
board_build.partitions = ${esp32.default_partitions}
@ -364,7 +369,7 @@ board = esp32dev
platform = ${esp32.platform}
platform_packages = ${esp32.platform_packages}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_audioreactive #-D WLED_DISABLE_BROWNOUT_DET
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}
lib_deps = ${esp32.lib_deps}
${esp32.AR_lib_deps}
@ -379,7 +384,7 @@ platform = ${esp32.platform}
platform_packages = ${esp32.platform_packages}
upload_speed = 921600
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
lib_deps = ${esp32.lib_deps}
board_build.partitions = ${esp32.default_partitions}
@ -389,11 +394,10 @@ platform = ${esp32.platform}
board = ttgo-t7-v14-mini32
board_build.f_flash = 80000000L
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_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_WROVER
-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue
-D WLED_USE_PSRAM
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 ;; 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 LEDPIN=25
lib_deps = ${esp32.lib_deps}
@ -404,7 +408,7 @@ platform_packages = ${esp32c3.platform_packages}
framework = arduino
board = esp32-c3-devkitm-1
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
-DLOLIN_WIFI_FIX ; seems to work much better with this
-DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB
@ -420,12 +424,13 @@ platform = ${esp32s3.platform}
platform_packages = ${esp32s3.platform_packages}
upload_speed = 921600 ; or 460800
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_8MB
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 ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
;-D ARDUINO_USB_CDC_ON_BOOT=1 ;; -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
;-D WLED_DEBUG
${esp32.AR_build_flags}
lib_deps = ${esp32s3.lib_deps}
${esp32.AR_lib_deps}
board_build.partitions = tools/WLED_ESP32_8MB.csv
board_build.f_flash = 80000000L
board_build.flash_mode = qio
@ -440,18 +445,39 @@ 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_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 ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
; -D WLED_RELEASE_NAME=ESP32-S3_PSRAM
-D WLED_USE_PSRAM -DBOARD_HAS_PSRAM ; tells WLED that PSRAM shall be used
-DBOARD_HAS_PSRAM
${esp32.AR_build_flags}
lib_deps = ${esp32s3.lib_deps}
${esp32.AR_lib_deps}
board_build.partitions = tools/WLED_ESP32_8MB.csv
board_build.f_flash = 80000000L
board_build.flash_mode = qio
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]
platform = ${esp32s2.platform}
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.f_flash = 80000000L
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=ESP32-S2
-DBOARD_HAS_PSRAM
build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=ESP32-S2 -D WLED_PRODUCT_NAME=FOSS_PSRAM
-DARDUINO_USB_CDC_ON_BOOT=1
-DARDUINO_USB_MSC_ON_BOOT=0
-DARDUINO_USB_DFU_ON_BOOT=0
-DBOARD_HAS_PSRAM
-DLOLIN_WIFI_FIX ; seems to work much better with this
-D WLED_USE_PSRAM
-D WLED_WATCHDOG_TIMEOUT=0
-D CONFIG_ASYNC_TCP_USE_WDT=0
-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_MISOSPI=9
; -D STATUSLED=15
${esp32.AR_build_flags}
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
; -D DEFAULT_LED_COLOR_ORDER=COL_ORDER_GRB
;
; use PSRAM if a device (ESP) has one
; -DBOARD_HAS_PSRAM
; -D WLED_USE_PSRAM
; use PSRAM on classic ESP32 rev.1 (rev.3 or above has no issues)
; -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue
;
; configure I2C and SPI interface (for various hardware)
; -D I2CSDAPIN=33 # initialise interface

Wyświetl plik

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

Wyświetl plik

@ -1,6 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x180000,
app1, app, ota_1, 0x190000,0x180000,
spiffs, data, spiffs, 0x310000,0xF0000,
app0, app, ota_0, 0x10000, 0x1A0000,
app1, app, ota_1, 0x1B0000,0x1A0000,
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
fs.cpSync("wled00/data", "wled00Backup", { recursive: true });
fs.cpSync("tools/cdata.js", "cdata.bak.js");
fs.cpSync("package.json", "package.bak.json");
});
after(() => {
// Restore backup
@ -90,6 +91,8 @@ describe('Script', () => {
fs.renameSync("wled00Backup", "wled00/data");
fs.rmSync("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
@ -131,7 +134,7 @@ describe('Script', () => {
// run script cdata.js again and wait for it to finish
await execPromise('node tools/cdata.js');
checkIfFileWasNewlyCreated(path.join(folderPath, resultFile));
await checkIfFileWasNewlyCreated(path.join(folderPath, resultFile));
}
describe('should build if', () => {
@ -182,6 +185,10 @@ describe('Script', () => {
it('cdata.js changes', async () => {
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', () => {

Wyświetl plik

@ -2,7 +2,7 @@
* Writes compressed C arrays of data files (web interface)
* How to use it?
*
* 1) Install Node 11+ and npm
* 1) Install Node 20+ and npm
* 2) npm install
* 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.
*/
const fs = require("fs");
const fs = require("node:fs");
const path = require("path");
const inliner = require("inliner");
const zlib = require("zlib");
const zlib = require("node:zlib");
const CleanCSS = require("clean-css");
const minifyHtml = require("html-minifier-terser").minify;
const packageJson = require("../package.json");
@ -207,7 +207,7 @@ function isAnyFileInFolderNewerThan(folderPath, time) {
}
// Check if the web UI is already built
function isAlreadyBuilt(folderPath) {
function isAlreadyBuilt(webUIPath, packageJsonPath = "package.json") {
let lastBuildTime = Infinity;
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

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.
## Installation
### using customised _arduinoFFT_ library for use with this usermod
Add `-D USERMOD_AUDIOREACTIVE` to your PlatformIO environment `build_flags`, as well as `https://github.com/blazoncek/arduinoFFT.git` to your `lib_deps`.
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.
### using latest _arduinoFFT_ library version 2.x
The latest arduinoFFT release version should be used for audioreactive.
Customised _arduinoFFT_ library for use with this usermod can be found at https://github.com/blazoncek/arduinoFFT.git
### 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`
* `build_flags` = `-D USERMOD_AUDIOREACTIVE`
* `lib_deps`= `kosme/arduinoFFT @ 2.0.1`
## Configuration

Wyświetl plik

@ -667,7 +667,7 @@ void MultiRelay::addToJsonInfo(JsonObject &root) {
for (int i=0; i<MULTI_RELAY_MAX_RELAYS; i++) {
if (_relay[i].pin<0 || !_relay[i].external) continue;
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 += 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!
"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 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.
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.
The original "usermod_v2_auto_save" will not work with the display just yet.
Press the encoder to cycle through the options:
*Brightness
*Speed
*Intensity
*Palette
*Effect
*Main Color (only if display is used)
*Saturation (only if display is used)
* Brightness
* Speed
* Intensity
* Palette
* Effect
* Main Color (only if display is used)
* Saturation (only if display is used)
Press and hold the encoder to display Network Info
if AP is active, it will display AP, SSID and password
Press and hold the encoder to display Network Info. If AP is active, it will display AP, SSID and password
Also shows if the timer is enabled
@ -30,11 +29,47 @@ Also shows if the timer is enabled
## Installation
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,
Please refer to the original `usermod_v2_rotary_encoder_ui` readme for the main instructions.
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
## 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
Note: the Four Line Display usermod requires the libraries `U8g2` and `Wire`.

Wyświetl plik

@ -17,7 +17,7 @@
// for WLED.
//
// Dependencies
// * This Usermod works best, by far, when coupled
// * This Usermod works best, by far, when coupled
// with RotaryEncoderUI ALT Usermod.
//
// 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
SSD1306_SPI, // U8X8_SSD1306_128X32_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;
@ -235,7 +236,7 @@ class FourLineDisplayUsermod : public Usermod {
void updateSpeed();
void updateIntensity();
void drawStatusIcons();
/**
* marks the position of the arrow showing
* the current setting being changed
@ -246,8 +247,8 @@ class FourLineDisplayUsermod : public Usermod {
//Draw the arrow for the current setting being changed
void drawArrow();
//Display the current effect or palette (desiredEntry)
// on the appropriate line (row).
//Display the current effect or palette (desiredEntry)
// on the appropriate line (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.
* 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().
*
*
* CAUTION: serializeConfig() will initiate a filesystem write operation.
* 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!
*
*
* 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.
*
*
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/
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().
* 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),
* 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 :)
@ -494,7 +495,7 @@ void FourLineDisplayUsermod::showTime() {
}
if (knownHour != hourCurrent) {
// 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
}
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 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 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
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
@ -581,7 +583,7 @@ void FourLineDisplayUsermod::setup() {
// gets called every time WiFi is (re-)connected. Initialize own network
// interfaces here
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();
networkOverlay(PSTR("NETWORK INFO"),7000);
}
@ -637,7 +639,7 @@ void FourLineDisplayUsermod::redraw(bool forceRedraw) {
powerON = !powerON;
drawStatusIcons();
return;
} else if (knownnightlight != nightlightActive) { //trigger moon icon
} else if (knownnightlight != nightlightActive) { //trigger moon icon
knownnightlight = nightlightActive;
drawStatusIcons();
if (knownnightlight) {
@ -652,7 +654,7 @@ void FourLineDisplayUsermod::redraw(bool forceRedraw) {
return;
} else if (knownMode != effectCurrent || knownPalette != effectPalette) {
if (displayTurnedOff) needRedraw = true;
else {
else {
if (knownPalette != effectPalette) { showCurrentEffectOrPalette(effectPalette, JSON_palette_names, 2); knownPalette = effectPalette; }
if (knownMode != effectCurrent) { showCurrentEffectOrPalette(effectCurrent, JSON_mode_names, 3); knownMode = effectCurrent; }
lastRedraw = now;
@ -703,7 +705,7 @@ void FourLineDisplayUsermod::redraw(bool forceRedraw) {
drawArrow();
drawStatusIcons();
// Second row
// Second row
updateBrightness();
updateSpeed();
updateIntensity();
@ -805,8 +807,8 @@ void FourLineDisplayUsermod::drawArrow() {
lockRedraw = false;
}
//Display the current effect or palette (desiredEntry)
// on the appropriate line (row).
//Display the current effect or palette (desiredEntry)
// on the appropriate line (row).
void FourLineDisplayUsermod::showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row) {
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
unsigned long now = millis();
@ -857,7 +859,7 @@ void FourLineDisplayUsermod::showCurrentEffectOrPalette(int inputEffPal, const c
while (smallChars1 < (MAX_MODE_LINE_SPACE-1)) smallBuffer1[smallChars1++]=' ';
smallBuffer1[smallChars1] = 0;
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;
drawString(1, row*lineHeight+1, smallBuffer2, true);
}
@ -1150,7 +1152,7 @@ void FourLineDisplayUsermod::onUpdateBegin(bool init) {
xTaskCreatePinnedToCore(
[](void * par) { // Function to implement the task
// 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();
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.
@ -1205,6 +1207,7 @@ void FourLineDisplayUsermod::appendConfigData() {
oappend(SET_F("addOption(dd,'SSD1306 128x64',3);"));
oappend(SET_F("addOption(dd,'SSD1305',4);"));
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 128x64',7);"));
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.
* 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().
*
*
* CAUTION: serializeConfig() will initiate a filesystem write operation.
* 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!
*
*
* 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.
*
*
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/
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().
* 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),
* 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 :)
@ -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_SetPin_HW_I2C(u8x8->getU8x8(), U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE);
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:
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

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 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.
The original "usermod_v2_auto_save" will not work with the display just yet.
Press the encoder to cycle through the options:
*Brightness
*Speed
*Intensity
*Palette
*Effect
*Main Color (only if display is used)
*Saturation (only if display is used)
* Brightness
* Speed
* Intensity
* Palette
* Effect
* Main Color (only if display is used)
* Saturation (only if display is used)
Press and hold the encoder to display Network Info
if AP is active, it will display the AP, SSID and Password
@ -30,10 +30,23 @@ Also shows if the timer is enabled.
## Installation
Please refer to the original `usermod_v2_rotary_encoder_ui` readme for the main instructions.<br/>
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.
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` (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

Wyświetl plik

@ -392,26 +392,26 @@ byte RotaryEncoderUIUsermod::readPin(uint8_t pin) {
* modes_alpha_indexes and palettes_alpha_indexes.
*/
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 = strip.getModeDataSrc();
modes_alpha_indexes = re_initIndexArray(strip.getModeCount());
re_sortModes(modes_qstrings, modes_alpha_indexes, strip.getModeCount(), MODE_SORT_SKIP_COUNT);
palettes_qstrings = re_findModeStrings(JSON_palette_names, strip.getPaletteCount()+strip.customPalettes.size());
palettes_alpha_indexes = re_initIndexArray(strip.getPaletteCount()+strip.customPalettes.size());
DEBUG_PRINT(F("Sorting palettes: ")); DEBUG_PRINT(strip.getPaletteCount()); DEBUG_PRINT('/'); DEBUG_PRINTLN(strip.customPalettes.size());
palettes_qstrings = re_findModeStrings(JSON_palette_names, strip.getPaletteCount());
palettes_alpha_indexes = re_initIndexArray(strip.getPaletteCount());
if (strip.customPalettes.size()) {
for (int i=0; i<strip.customPalettes.size(); i++) {
palettes_alpha_indexes[strip.getPaletteCount()+i] = 255-i;
palettes_qstrings[strip.getPaletteCount()+i] = PSTR("~Custom~");
palettes_alpha_indexes[strip.getPaletteCount()-strip.customPalettes.size()+i] = 255-i;
palettes_qstrings[strip.getPaletteCount()-strip.customPalettes.size()+i] = PSTR("~Custom~");
}
}
// How many palette names start with '*' and should not be sorted?
// (Also skipping the first one, 'Default').
int skipPaletteCount = 1;
while (pgm_read_byte_near(palettes_qstrings[skipPaletteCount++]) == '*') ;
re_sortModes(palettes_qstrings, palettes_alpha_indexes, strip.getPaletteCount(), skipPaletteCount);
while (pgm_read_byte_near(palettes_qstrings[skipPaletteCount]) == '*') skipPaletteCount++;
re_sortModes(palettes_qstrings, palettes_alpha_indexes, strip.getPaletteCount()-strip.customPalettes.size(), skipPaletteCount);
}
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;;!";
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.
*/
uint16_t mode_larson_scanner(void){
return larson_scanner(false);
}
static const char _data_FX_MODE_LARSON_SCANNER[] PROGMEM = "Scanner@!,Fade rate;!,!;!;;m12=0";
if (SEGLEN == 1) return mode_static();
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
* Custom mode by Keith Lord: https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/DualLarson.h
*/
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));
#ifdef WLED_USE_AA_PIXELS
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(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);
if (blob->r[i] > 1.f) SEGMENT.fill_circle(blob->x[i], blob->y[i], roundf(blob->r[i]), c);
else SEGMENT.setPixelColorXY(blob->x[i], blob->y[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((int)roundf(blob->x[i]), (int)roundf(blob->y[i]), c);
// 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));
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 */
#define WLED_FPS 42
#define FRAMETIME_FIXED (1000/WLED_FPS)
//#define FRAMETIME _frametime
#define FRAMETIME strip.getFrameTime()
/* each segment uses 82 bytes of SRAM memory, so if you're application fails because of
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
#ifdef ESP8266
#define MAX_NUM_SEGMENTS 12
#define MAX_NUM_SEGMENTS 16
/* How much data bytes all segments combined may allocate */
#define MAX_SEGMENT_DATA 5120
#else
@ -73,11 +72,7 @@
#define MAX_NUM_SEGMENTS 32
#endif
#if defined(ARDUINO_ARCH_ESP32S2)
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*1024 // 32k by default
#else
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*768 // 24k by default
#endif
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*768 // 24k by default (S2 is short on free RAM)
#else
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*1280 // 40k by default
#endif
@ -187,7 +182,7 @@
#define FX_MODE_LIGHTNING 57
#define FX_MODE_ICU 58
#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_OSCILLATE 62
#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(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)); }
#ifdef WLED_USE_AA_PIXELS
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, CRGB c, bool aa = true) { setPixelColor(i, RGBW32(c.r,c.g,c.b,0), aa); }
#endif
uint32_t getPixelColor(int i);
// 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 fade_out(uint8_t r);
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(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)); }
#ifdef WLED_USE_AA_PIXELS
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, 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
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); }
@ -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 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 blurRow(uint16_t row, fract8 blur_amount);
void blurCol(uint16_t col, fract8 blur_amount);
void blurRow(uint32_t row, fract8 blur_amount, bool smear = false);
void blurCol(uint32_t col, fract8 blur_amount, bool smear = false);
void moveX(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);
@ -640,11 +639,14 @@ typedef struct Segment {
#else
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(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, 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, 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); }
#endif
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, 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 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 blurRow(uint16_t row, fract8 blur_amount) {}
inline void blurCol(uint16_t col, fract8 blur_amount) {}
inline void blurRow(uint32_t row, fract8 blur_amount, bool smear = false) {}
inline void blurCol(uint32_t col, fract8 blur_amount, bool smear = false) {}
inline void moveX(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) {}
@ -810,7 +812,7 @@ class WS2812FX { // 96 bytes
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 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 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
if (customMappingTable == nullptr) customMappingTable = new uint16_t[getLengthTotal()];
if (customMappingTable) delete[] customMappingTable;
customMappingTable = new uint16_t[getLengthTotal()];
if (customMappingTable != nullptr) {
if (customMappingTable) {
customMappingSize = getLengthTotal();
// fill with empty in case we don't fill the entire matrix
@ -138,7 +139,7 @@ void WS2812FX::setUpMatrix() {
DEBUG_PRINTLN();
#endif
} else { // memory allocation error
DEBUG_PRINTLN(F("Ledmap alloc error."));
DEBUG_PRINTLN(F("ERROR 2D LED map allocation error."));
isMatrix = false;
panels = 0;
panel.clear();
@ -174,11 +175,7 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
uint8_t _bri_t = currentBri();
if (_bri_t < 255) {
byte r = scale8(R(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);
col = color_fade(col, _bri_t);
}
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()
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);
}
}
#endif
// 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 (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;
@ -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
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
const uint_fast16_t cols = virtualWidth();
const uint_fast16_t rows = virtualHeight();
if (row >= rows) return;
// blur one row
uint8_t keep = 255 - blur_amount;
uint8_t keep = smear ? 255 : 255 - blur_amount;
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++) {
CRGB cur = getPixelColorXY(x, row);
CRGB before = cur; // remember color before blur
CRGB part = cur;
part.nscale8(seep);
cur.nscale8(keep);
cur += carryover;
if (x>0) {
CRGB prev = CRGB(getPixelColorXY(x-1, row)) + part;
setPixelColorXY(x-1, row, prev);
uint32_t cur = getPixelColorXY(x, row);
uint32_t part = color_fade(cur, seep);
curnew = color_fade(cur, keep);
if (x > 0) {
if (carryover)
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
setPixelColorXY(x - 1, row, prev);
}
if (before != cur) // optimization: only set pixel if color has changed
setPixelColorXY(x, row, cur);
else // first pixel
setPixelColorXY(x, row, curnew);
lastnew = curnew;
last = cur; // save original value for comparison on next iteration
carryover = part;
}
setPixelColorXY(cols-1, row, curnew); // set last pixel
}
// 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
const uint_fast16_t cols = virtualWidth();
const uint_fast16_t rows = virtualHeight();
if (col >= cols) return;
// blur one column
uint8_t keep = 255 - blur_amount;
uint8_t keep = smear ? 255 : 255 - blur_amount;
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++) {
CRGB cur = getPixelColorXY(col, y);
CRGB part = cur;
CRGB before = cur; // remember color before blur
part.nscale8(seep);
cur.nscale8(keep);
cur += carryover;
if (y>0) {
CRGB prev = CRGB(getPixelColorXY(col, y-1)) + part;
setPixelColorXY(col, y-1, prev);
uint32_t cur = getPixelColorXY(col, y);
uint32_t part = color_fade(cur, seep);
curnew = color_fade(cur, keep);
if (y > 0) {
if (carryover)
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
setPixelColorXY(col, y - 1, prev);
}
if (before != cur) // optimization: only set pixel if color has changed
setPixelColorXY(col, y, cur);
carryover = part;
else // first pixel
setPixelColorXY(col, y, curnew);
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])

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
void Segment::handleRandomPalette() {
// 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();
_lastPaletteChange = millis()/1000U;
_lastPaletteBlend = (uint16_t)(millis() & 0xFFFF)-512; // starts blending immediately
_lastPaletteChange = (uint16_t)(millis() / 1000U);
_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 (strip.paletteFade) {
// 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
if ((millis() & 0xFFFF) - _lastPaletteBlend < strip.getTransition() >> 7) return; // not yet time to fade, delay the update
_lastPaletteBlend = millis();
if ((uint16_t)((uint16_t)millis() - _lastPaletteBlend) < strip.getTransition() >> 7) return; // not yet time to fade, delay the update
_lastPaletteBlend = (uint16_t)millis();
}
nblendPaletteTowardPalette(_randomPalette, _newRandomPalette, 48);
}
@ -735,11 +735,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
uint16_t len = length();
uint8_t _bri_t = currentBri();
if (_bri_t < 255) {
byte r = scale8(R(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);
col = color_fade(col, _bri_t);
}
// 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()
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);
}
}
#endif
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
*/
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"
#ifndef WLED_DISABLE_2D
if (is2D()) {
// compatibility with 2D
const unsigned cols = virtualWidth();
const unsigned rows = virtualHeight();
for (unsigned i = 0; i < rows; i++) blurRow(i, blur_amount); // blur all rows
for (unsigned k = 0; k < cols; k++) blurCol(k, blur_amount); // blur all columns
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, smear); // blur all columns
return;
}
#endif
uint8_t keep = 255 - blur_amount;
uint8_t keep = smear ? 255 : 255 - blur_amount;
uint8_t seep = blur_amount >> 1;
uint32_t carryover = BLACK;
unsigned vlength = virtualLength();
uint32_t carryover = BLACK;
uint32_t lastnew;
uint32_t last;
uint32_t curnew;
for (unsigned i = 0; i < vlength; i++) {
uint32_t cur = getPixelColor(i);
uint32_t part = color_fade(cur, seep);
cur = color_add(color_fade(cur, keep), carryover, true);
curnew = color_fade(cur, keep);
if (i > 0) {
uint32_t c = getPixelColor(i-1);
setPixelColor(i-1, color_add(c, part, true));
if (carryover)
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;
}
setPixelColor(vlength - 1, curnew);
}
/*
@ -1098,6 +1106,12 @@ void WS2812FX::finalizeInit(void) {
uint16_t prevLen = 0;
for (int i = 0; i < defNumBusses && i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; 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 count = defCounts[(i < defNumCounts) ? i : defNumCounts -1];
prevLen += count;
@ -1162,12 +1176,16 @@ void WS2812FX::service() {
uint16_t delay = FRAMETIME;
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
_colors_t[0] = gamma32(seg.currentColor(0));
_colors_t[1] = gamma32(seg.currentColor(1));
_colors_t[2] = gamma32(seg.currentColor(2));
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
// 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.
@ -1190,20 +1208,19 @@ void WS2812FX::service() {
#endif
seg.call++;
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;
}
// if (_segment_index == _queuedChangesSegId) setUpSegmentFromQueuedChanges();
_segment_index++;
}
_virtualSegmentLength = 0;
BusManager::setSegmentCCT(-1);
_isServicing = false;
_triggered = false;
#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
if (doShow) {
yield();
@ -1211,7 +1228,7 @@ void WS2812FX::service() {
show();
}
#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
}
@ -1390,11 +1407,7 @@ bool WS2812FX::hasCCTBus(void) {
for (size_t b = 0; b < BusManager::getNumBusses(); b++) {
Bus *bus = BusManager::getBus(b);
if (bus == nullptr || bus->getLength()==0) break;
switch (bus->getType()) {
case TYPE_ANALOG_5CH:
case TYPE_ANALOG_2CH:
return true;
}
if (bus->hasCCT()) return true;
}
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()));
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();
_segments[segId].setUp(i1, i2, grouping, spacing, offset, startY, stopY);
resume();
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() {
_segments.clear(); // destructs all Segment as part of clearing
#ifndef WLED_DISABLE_2D
@ -1670,19 +1664,23 @@ bool WS2812FX::deserializeMap(uint8_t n) {
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()];
JsonObject root = pDoc->as<JsonObject>();
JsonArray map = root[F("map")];
if (!map.isNull() && map.size()) { // not an empty map
customMappingSize = min((unsigned)map.size(), (unsigned)getLengthTotal());
for (unsigned i=0; i<customMappingSize; i++) customMappingTable[i] = (uint16_t) (map[i]<0 ? 0xFFFFU : map[i]);
if (customMappingTable) {
DEBUG_PRINT(F("Reading LED map from ")); DEBUG_PRINTLN(fileName);
JsonObject root = pDoc->as<JsonObject>();
JsonArray map = root[F("map")];
if (!map.isNull() && map.size()) { // not an empty map
customMappingSize = min((unsigned)map.size(), (unsigned)getLengthTotal());
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();
return true;
return (customMappingSize > 0);
}
uint16_t IRAM_ATTR WS2812FX::getMappedPixelIndex(uint16_t index) {

Wyświetl plik

@ -9,9 +9,10 @@
#include "bus_wrapper.h"
#include "bus_manager.h"
extern bool cctICused;
//colors.cpp
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
uint16_t approximateKelvinFromRGB(uint32_t rgb);
//udp.cpp
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);
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;
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
_busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr, _frequencykHz);
_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
@ -205,13 +206,15 @@ void BusDigital::show() {
_milliAmpsTotal = 0;
if (!_valid) return;
uint8_t cctWW = 0, cctCW = 0;
uint8_t newBri = estimateCurrentAndLimitBri(); // will fill _milliAmpsTotal
if (newBri < _bri) PolyBus::setBrightness(_busPtr, _iType, newBri); // limit brightness to stay within current limits
if (_data) { // use _buffering this causes ~20% FPS drop
size_t channels = Bus::hasWhite(_type) + 3*Bus::hasRGB(_type);
if (_data) {
size_t channels = getNumberOfChannels();
int16_t oldCCT = Bus::_cct; // temporarily save bus CCT
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);
uint32_t c;
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;
}
} 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;
if (_reversed) pix = _len - pix -1;
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 (_skip) PolyBus::setPixelColor(_busPtr, _iType, 0, 0, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); // paint skipped pixels black
#endif
for (int i=1; i<_skip; i++) PolyBus::setPixelColor(_busPtr, _iType, i, 0, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); // paint skipped pixels black
Bus::_cct = oldCCT;
} else {
if (newBri < _bri) {
uint16_t hwLen = _len;
@ -239,7 +251,8 @@ void BusDigital::show() {
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
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) {
if (!_valid) return;
if (Bus::hasWhite(_type)) c = autoWhiteCalc(c);
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
if (_data) { // use _buffering this causes ~20% FPS drop
size_t channels = Bus::hasWhite(_type) + 3*Bus::hasRGB(_type);
size_t offset = pix*channels;
if (Bus::hasRGB(_type)) {
uint8_t cctWW = 0, cctCW = 0;
if (hasWhite()) c = autoWhiteCalc(c);
if (Bus::_cct >= 1900) c = colorBalanceFromKelvin(Bus::_cct, c); //color correction from CCT
if (_data) {
size_t offset = pix * getNumberOfChannels();
if (hasRGB()) {
_data[offset++] = R(c);
_data[offset++] = G(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 {
if (_reversed) pix = _len - pix -1;
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;
}
}
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
uint32_t IRAM_ATTR BusDigital::getPixelColor(uint16_t pix) {
if (!_valid) return 0;
if (_data) { // use _buffering this causes ~20% FPS drop
size_t channels = Bus::hasWhite(_type) + 3*Bus::hasRGB(_type);
size_t offset = pix*channels;
if (_data) {
size_t offset = pix * getNumberOfChannels();
uint32_t c;
if (!Bus::hasRGB(_type)) {
if (!hasRGB()) {
c = RGBW32(_data[offset], _data[offset], _data[offset], _data[offset]);
} 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;
} else {
@ -414,48 +430,31 @@ BusPwm::BusPwm(BusConfig &bc)
void BusPwm::setPixelColor(uint16_t pix, uint32_t c) {
if (pix != 0 || !_valid) return; //only react to first pixel
if (_type != TYPE_ANALOG_3CH) c = autoWhiteCalc(c);
if (_cct >= 1900 && (_type == TYPE_ANALOG_3CH || _type == TYPE_ANALOG_4CH)) {
c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
if (Bus::_cct >= 1900 && (_type == TYPE_ANALOG_3CH || _type == TYPE_ANALOG_4CH)) {
c = colorBalanceFromKelvin(Bus::_cct, c); //color correction from CCT
}
uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(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) {
case TYPE_ANALOG_1CH: //one channel (white), relies on auto white calculation
_data[0] = w;
break;
case TYPE_ANALOG_2CH: //warm white + cold white
_data[1] = cw;
_data[0] = ww;
if (cctICused) {
_data[0] = w;
_data[1] = Bus::_cct < 0 || Bus::_cct > 255 ? 127 : Bus::_cct;
} else {
Bus::calculateCCT(c, _data[0], _data[1]);
}
break;
case TYPE_ANALOG_5CH: //RGB + warm white + cold white
_data[4] = cw;
w = ww;
if (cctICused)
_data[4] = Bus::_cct < 0 || Bus::_cct > 255 ? 127 : Bus::_cct;
else
Bus::calculateCCT(c, w, _data[4]);
case TYPE_ANALOG_4CH: //RGBW
_data[3] = w;
case TYPE_ANALOG_3CH: //standard dumb RGB
@ -506,7 +505,7 @@ void BusPwm::show() {
uint8_t numPins = NUM_PWM_PINS(_type);
unsigned maxBri = (1<<_depth) - 1;
#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
unsigned pwmBri = cieLUT[_bri] >> (12 - _depth); // use CIE LUT
#endif
@ -620,7 +619,7 @@ BusNetwork::BusNetwork(BusConfig &bc)
void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
if (!_valid || pix >= _len) return;
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;
_data[offset] = R(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;
uint16_t len = bc.count + bc.skipAmount;
uint16_t channels = 3;
uint16_t channels = Bus::getNumberOfChannels(bc.type);
uint16_t multiplier = 1;
if (IS_DIGITAL(bc.type)) { // digital types
if (IS_16BIT(bc.type)) len *= 2; // 16-bit LEDs
#ifdef ESP8266
if (bc.type > 28) channels = 4; //RGBW
if (bc.pins[0] == 3) { //8266 DMA uses 5x the mem
multiplier = 5;
}
#else //ESP32 RMT uses double buffer, I2S uses 5x buffer
if (bc.type > 28) channels = 4; //RGBW
multiplier = 2;
#endif
}
if (IS_VIRTUAL(bc.type)) {
switch (bc.type) {
case TYPE_NET_DDP_RGBW: channels = 4; break;
}
}
return len * channels * multiplier; //RGB
}
@ -740,7 +732,7 @@ void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) {
if (cct >= 0) {
//if white balance correction allowed, save as kelvin value instead of 0-255
if (allowWBCorrection) cct = 1900 + (cct << 5);
} else cct = -1;
} else cct = -1; // will use kelvin approximation from RGB
Bus::setCCT(cct);
}

Wyświetl plik

@ -7,6 +7,9 @@
#include "const.h"
//colors.cpp
uint16_t approximateKelvinFromRGB(uint32_t rgb);
#define GET_BIT(var,bit) (((var)>>(bit))&0x01)
#define SET_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;
bool refreshReq;
uint8_t autoWhite;
uint8_t pins[5] = {LEDPIN, 255, 255, 255, 255};
uint8_t pins[5] = {255, 255, 255, 255, 255};
uint16_t frequency;
bool doubleBuffer;
uint8_t milliAmpsPerLed;
@ -53,9 +56,9 @@ struct BusConfig {
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)
size_t nPins = 1;
if (type >= TYPE_NET_DDP_RGB && type < 96) nPins = 4; //virtual network bus. 4 "pins" store IP address
else if (type > 47) nPins = 2;
else if (type > 40 && type < 46) nPins = NUM_PWM_PINS(type);
if (IS_VIRTUAL(type)) nPins = 4; //virtual network bus. 4 "pins" store IP address
else if (IS_2PIN(type)) nPins = 2;
else if (IS_PWM(type)) nPins = NUM_PWM_PINS(type);
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 getUsedCurrent() { 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 uint16_t getStart() { return _start; }
inline void setStart(uint16_t start) { _start = start; }
@ -154,18 +159,22 @@ class Bus {
}
virtual bool hasWhite(void) { return Bus::hasWhite(_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_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;
}
virtual bool hasCCT(void) { return Bus::hasCCT(_type); }
static bool hasCCT(uint8_t type) {
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;
}
static void setCCT(uint16_t cct) {
static int16_t getCCT() { return _cct; }
static void setCCT(int16_t cct) {
_cct = cct;
}
static void setCCTBlend(uint8_t b) {
@ -176,6 +185,26 @@ class Bus {
if (_cctBlend > WLED_MAX_CCT_BLEND) _cctBlend = WLED_MAX_CCT_BLEND;
#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 uint8_t getAutoWhiteMode() { return _autoWhiteMode; }
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;
uint8_t _autoWhiteMode;
uint8_t *_data;
// global Auto White Calculation override
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;
// _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;
uint32_t autoWhiteCalc(uint32_t c);
@ -334,9 +372,12 @@ class BusManager {
static void setStatusPixel(uint32_t c);
static void setPixelColor(uint16_t pix, uint32_t c);
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 setMilliampsMax(uint16_t max) { _milliAmpsMax = max;}
static uint32_t getPixelColor(uint16_t pix);
static inline int16_t getSegmentCCT() { return Bus::getCCT(); }
static Bus* getBus(uint8_t busNr);

Wyświetl plik

@ -2,6 +2,7 @@
#define BusWrapper_h
#include "NeoPixelBusLg.h"
#include "bus_manager.h"
// temporary - these defines should actually be set in platformio.ini
// 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_DM_UCS_4 55
#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
#define I_8266_U0_APA106_3 81
#define I_8266_U1_APA106_3 82
#define I_8266_DM_APA106_3 83
#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 ***/
//RGB
#define I_32_RN_NEO_3 21
#define I_32_I0_NEO_3 22
#define I_32_I1_NEO_3 23
#define I_32_BB_NEO_3 24 // bitbanging on ESP32 not recommended
//RGBW
#define I_32_RN_NEO_4 25
#define I_32_I0_NEO_4 26
#define I_32_I1_NEO_4 27
#define I_32_BB_NEO_4 28 // bitbanging on ESP32 not recommended
//400Kbps
#define I_32_RN_400_3 29
#define I_32_I0_400_3 30
#define I_32_I1_400_3 31
#define I_32_BB_400_3 32 // bitbanging on ESP32 not recommended
//TM1814 (RGBW)
#define I_32_RN_TM1_4 33
#define I_32_I0_TM1_4 34
#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)
#define I_32_RN_TM2_3 36
#define I_32_I0_TM2_3 37
#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)
#define I_32_RN_UCS_3 57
#define I_32_I0_UCS_3 58
#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)
#define I_32_RN_UCS_4 60
#define I_32_I0_UCS_4 61
#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_I0_APA106_3 86
#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
#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_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)
//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
/*** ESP32 Neopixel methods ***/
@ -183,75 +206,102 @@
//RGB
#define B_32_RN_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
#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
#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
//#define B_32_BB_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32BitBang800KbpsMethod, NeoGammaNullMethod> // NeoEsp8266BitBang800KbpsMethod
//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
#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
#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
//#define B_32_BB_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32BitBang800KbpsMethod, NeoGammaNullMethod> // NeoEsp8266BitBang800KbpsMethod
//400Kbps
#define B_32_RN_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtN400KbpsMethod, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0400KbpsMethod, NeoGammaNullMethod>
//#define B_32_I0_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0X8400KbpsMethod, NeoGammaNullMethod> // parallel I2S
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1400KbpsMethod, NeoGammaNullMethod>
//#define B_32_I1_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1X8400KbpsMethod, NeoGammaNullMethod> // parallel I2S
#endif
//#define B_32_BB_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32BitBang400KbpsMethod, NeoGammaNullMethod> // NeoEsp8266BitBang400KbpsMethod
//TM1814 (RGBW)
#define B_32_RN_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32RmtNTm1814Method, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s0Tm1814Method, NeoGammaNullMethod>
//#define B_32_I0_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s0X8Tm1814Method, NeoGammaNullMethod> // parallel I2S
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s1Tm1814Method, NeoGammaNullMethod>
//#define B_32_I1_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s1X8Tm1814Method, NeoGammaNullMethod> // parallel I2S
#endif
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
//TM1829 (RGB)
#define B_32_RN_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32RmtNTm1829Method, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s0Tm1829Method, NeoGammaNullMethod>
//#define B_32_I0_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s0X8Tm1829Method, NeoGammaNullMethod> // parallel I2S
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s1Tm1829Method, NeoGammaNullMethod>
//#define B_32_I1_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s1X8Tm1829Method, NeoGammaNullMethod> // parallel I2S
#endif
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
//UCS8903
#define B_32_RN_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod>
//#define B_32_I0_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s0X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
//#define B_32_I1_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s1X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
#endif
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
//UCS8904
#define B_32_RN_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
#ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod>
//#define B_32_I0_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s0X8800KbpsMethod, NeoGammaNullMethod>// parallel I2S
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
#define B_32_I1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
//#define B_32_I1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s1X8800KbpsMethod, NeoGammaNullMethod>// parallel I2S
#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>
#ifndef WLED_NO_I2S0_PIXELBUS
#define B_32_I0_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0Apa106Method, NeoGammaNullMethod>
//#define B_32_I0_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0X8Apa106Method, NeoGammaNullMethod> // parallel I2S
#endif
#ifndef WLED_NO_I2S1_PIXELBUS
#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
//#define B_32_BB_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266BitBangApa106Method, NeoGammaNullMethod> // NeoEsp8266BitBang800KbpsMethod
#endif
//APA102
@ -290,6 +340,7 @@
//handles pointer type conversion for all possible bus types
class PolyBus {
public:
// initialize SPI bus speed for DotStar methods
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) {
@ -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_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_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
#ifdef ARDUINO_ARCH_ESP32
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
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->Begin(); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->Begin(); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Begin(); break;
#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_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->Begin(); break;
#ifndef WLED_NO_I2S0_PIXELBUS
@ -396,7 +452,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->Begin(); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Begin(); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->Begin(); break;
#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()
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;
@ -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_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_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
#ifdef ARDUINO_ARCH_ESP32
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
case I_32_I1_NEO_3: busPtr = new B_32_I1_NEO_3(len, pins[0]); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_NEO_4: busPtr = new B_32_I1_NEO_4(len, pins[0]); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_400_3: busPtr = new B_32_I1_400_3(len, pins[0]); break;
#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_TM2_3: busPtr = new B_32_RN_TM2_3(len, pins[0], (NeoBusChannel)channel); break;
#ifndef WLED_NO_I2S0_PIXELBUS
@ -508,7 +580,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_3: busPtr = new B_32_I1_UCS_3(len, pins[0]); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_UCS_4: busPtr = new B_32_I1_UCS_4(len, pins[0]); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_APA106_3: busPtr = new B_32_I1_APA106_3(len, pins[0]); break;
#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
// 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;
@ -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_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_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
#ifdef ARDUINO_ARCH_ESP32
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
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->Show(consistent); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->Show(consistent); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Show(consistent); break;
#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_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->Show(consistent); break;
#ifndef WLED_NO_I2S0_PIXELBUS
@ -621,7 +709,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->Show(consistent); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Show(consistent); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->Show(consistent); break;
#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
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;
@ -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_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_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
#ifdef ARDUINO_ARCH_ESP32
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
case I_32_I1_NEO_3: return (static_cast<B_32_I1_NEO_3*>(busPtr))->CanShow(); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_NEO_4: return (static_cast<B_32_I1_NEO_4*>(busPtr))->CanShow(); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_400_3: return (static_cast<B_32_I1_400_3*>(busPtr))->CanShow(); break;
#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_TM2_3: return (static_cast<B_32_RN_TM2_3*>(busPtr))->CanShow(); break;
#ifndef WLED_NO_I2S0_PIXELBUS
@ -730,7 +834,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_3: return (static_cast<B_32_I1_UCS_3*>(busPtr))->CanShow(); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_UCS_4: return (static_cast<B_32_I1_UCS_4*>(busPtr))->CanShow(); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_APA106_3: return (static_cast<B_32_I1_APA106_3*>(busPtr))->CanShow(); break;
#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
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;
@ -762,12 +877,13 @@ class PolyBus {
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 g = c >> 8;
uint8_t b = c >> 0;
uint8_t w = c >> 24;
RgbwColor col;
uint8_t cctWW = wwcw & 0xFF, cctCW = (wwcw>>8) & 0xFF;
// reorder channels to selected order
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_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_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
#ifdef ARDUINO_ARCH_ESP32
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
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
#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_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
#ifndef WLED_NO_I2S0_PIXELBUS
@ -864,7 +985,6 @@ class PolyBus {
#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;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
#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
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;
@ -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_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_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
#ifdef ARDUINO_ARCH_ESP32
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
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->SetLuminance(b); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->SetLuminance(b); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetLuminance(b); break;
#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_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->SetLuminance(b); break;
#ifndef WLED_NO_I2S0_PIXELBUS
@ -974,7 +1111,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->SetLuminance(b); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetLuminance(b); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->SetLuminance(b); break;
#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
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;
@ -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_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_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
#ifdef ARDUINO_ARCH_ESP32
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
case I_32_I1_NEO_3: col = (static_cast<B_32_I1_NEO_3*>(busPtr))->GetPixelColor(pix); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_NEO_4: col = (static_cast<B_32_I1_NEO_4*>(busPtr))->GetPixelColor(pix); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_400_3: col = (static_cast<B_32_I1_400_3*>(busPtr))->GetPixelColor(pix); break;
#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_TM2_3: col = (static_cast<B_32_RN_TM2_3*>(busPtr))->GetPixelColor(pix); break;
#ifndef WLED_NO_I2S0_PIXELBUS
@ -1085,7 +1238,6 @@ class PolyBus {
#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;
#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;
#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;
@ -1093,7 +1245,6 @@ class PolyBus {
#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;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_APA106_3: col = (static_cast<B_32_I1_APA106_3*>(busPtr))->GetPixelColor(pix); break;
#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
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;
@ -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_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_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
#ifdef ARDUINO_ARCH_ESP32
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
case I_32_I1_NEO_3: delete (static_cast<B_32_I1_NEO_3*>(busPtr)); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_NEO_4: delete (static_cast<B_32_I1_NEO_4*>(busPtr)); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_400_3: delete (static_cast<B_32_I1_400_3*>(busPtr)); break;
#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_TM2_3: delete (static_cast<B_32_RN_TM2_3*>(busPtr)); break;
#ifndef WLED_NO_I2S0_PIXELBUS
@ -1214,7 +1383,6 @@ class PolyBus {
#ifndef WLED_NO_I2S1_PIXELBUS
case I_32_I1_UCS_3: delete (static_cast<B_32_I1_UCS_3*>(busPtr)); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_UCS_4: delete (static_cast<B_32_I1_UCS_4*>(busPtr)); break;
#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;
#ifndef WLED_NO_I2S0_PIXELBUS
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
case I_32_I1_APA106_3: delete (static_cast<B_32_I1_APA106_3*>(busPtr)); break;
#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
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;
@ -1292,13 +1472,17 @@ class PolyBus {
return I_8266_U0_UCS_4 + offset;
case TYPE_APA106:
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
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)
// ESP32-S2 only has 4 RMT channels
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)
// On ESP32-C3 only the first 2 RMT channels are usable for transmitting
if (num > 1) return I_NONE;
@ -1310,7 +1494,8 @@ class PolyBus {
#else
// standard ESP32 has 8 RMT and 2 I2S channels
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
switch (busType) {
case TYPE_WS2812_1CH_X3:
@ -1332,11 +1517,14 @@ class PolyBus {
return I_32_RN_UCS_4 + offset;
case TYPE_APA106:
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
}
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_SWITCH:
#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
break;
break;
}
return false;
}
@ -403,3 +407,8 @@ void handleIO()
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);
CJSON(correctWB, hw_led["cct"]);
CJSON(cctFromRgb, hw_led[F("cr")]);
CJSON(cctICused, hw_led[F("ic")]);
CJSON(strip.cctBlending, hw_led[F("cb")]);
Bus::setCCTBlend(strip.cctBlending);
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;
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)
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;
maMax = 0;
}
@ -228,6 +229,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
// read multiple button configuration
JsonObject btn_obj = hw["btn"];
CJSON(touchThreshold, btn_obj[F("tt")]);
bool pull = btn_obj[F("pull")] | (!disablePullUp); // if true, pullup is enabled
disablePullUp = !pull;
JsonArray hw_btn_ins = btn_obj["ins"];
@ -252,6 +254,13 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
btnPin[s] = -1;
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
#endif
{
@ -308,7 +317,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
}
}
}
CJSON(touchThreshold,btn_obj[F("tt")]);
CJSON(buttonPublishMqtt,btn_obj["mqtt"]);
#ifndef WLED_DISABLE_INFRARED
@ -632,12 +641,12 @@ static const char s_cfg_json[] PROGMEM = "/cfg.json";
void deserializeConfigFromFS() {
bool success = deserializeConfigSec();
#ifdef WLED_ADD_EEPROM_SUPPORT
if (!success) { //if file does not exist, try reading from EEPROM
#ifdef WLED_ADD_EEPROM_SUPPORT
deEEPSettings();
return;
#endif
}
#endif
if (!requestJSONBufferLock(1)) return;
@ -767,6 +776,7 @@ void serializeConfig() {
hw_led[F("ledma")] = 0; // no longer used
hw_led["cct"] = correctWB;
hw_led[F("cr")] = cctFromRgb;
hw_led[F("ic")] = cctICused;
hw_led[F("cb")] = strip.cctBlending;
hw_led["fps"] = strip.getTargetFps();
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
* 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)
{
uint8_t r = R(c1);
uint8_t g = G(c1);
uint8_t b = B(c1);
uint8_t w = W(c1);
if (video) {
r = scale8_video(r, amount);
g = scale8_video(g, amount);
b = scale8_video(b, amount);
w = scale8_video(w, amount);
} else {
r = scale8(r, amount);
g = scale8(g, amount);
b = scale8(b, amount);
w = scale8(w, amount);
uint32_t scaledcolor; // color order is: W R G B from MSB to LSB
uint32_t r = R(c1);
uint32_t g = G(c1);
uint32_t b = B(c1);
uint32_t w = W(c1);
if (video) {
uint32_t scale = amount; // 32bit for faster calculation
scaledcolor = (((r * scale) >> 8) << 16) + ((r && scale) ? 1 : 0);
scaledcolor |= (((g * scale) >> 8) << 8) + ((g && scale) ? 1 : 0);
scaledcolor |= ((b * scale) >> 8) + ((b && scale) ? 1 : 0);
scaledcolor |= (((w * scale) >> 8) << 24) + ((w && scale) ? 1 : 0);
return scaledcolor;
}
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)

Wyświetl plik

@ -21,7 +21,7 @@
#define WLED_BRAND "WLED"
#endif
#ifndef WLED_PRODUCT_NAME
#define WLED_PRODUCT_NAME "FOSS"
#define WLED_PRODUCT_NAME "DIY"
#endif
//Defaults
@ -53,24 +53,16 @@
#define WLED_MAX_BUSSES 3 // will allow 2 digital & 1 analog (or the other way around)
#define WLED_MIN_VIRTUAL_BUSSES 3
#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
#define WLED_MAX_BUSSES 6 // will allow 4 digital & 2 analog
#define WLED_MIN_VIRTUAL_BUSSES 4
#else
#define WLED_MAX_BUSSES 7 // will allow 5 digital & 2 analog
#define WLED_MIN_VIRTUAL_BUSSES 3
#endif
// the 5th bus (I2S) will prevent Audioreactive usermod from functioning (it is last used though)
#define WLED_MAX_BUSSES 7 // will allow 5 digital & 2 analog
#define WLED_MIN_VIRTUAL_BUSSES 3
#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_MIN_VIRTUAL_BUSSES 4
#else
#if defined(USERMOD_AUDIOREACTIVE) // requested by @softhack007 https://github.com/blazoncek/WLED/issues/33
#define WLED_MAX_BUSSES 8
#define WLED_MIN_VIRTUAL_BUSSES 2
#else
#define WLED_MAX_BUSSES 10
#define WLED_MIN_VIRTUAL_BUSSES 0
#endif
// the 10th digital bus (I2S0) will prevent Audioreactive usermod from functioning (it is last used though)
#define WLED_MAX_BUSSES 10
#define WLED_MIN_VIRTUAL_BUSSES 0
#endif
#endif
#else
@ -181,6 +173,7 @@
#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_TETRISAI 47 //Usermod "usermod_v2_tetris.h"
#define USERMOD_ID_MAX17048 48 //Usermod "usermod_max17048.h"
//Access point behavior
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
@ -270,9 +263,11 @@
#define TYPE_TM1829 25
#define TYPE_UCS8903 26
#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_SK6812_RGBW 30
#define TYPE_TM1814 31
#define TYPE_WS2805 32 //RGB + WW + CW
//"Analog" types (40-47)
#define TYPE_ONOFF 40 //binary output (relays etc.; NOT PWM)
#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_2PIN(t) ((t) > 47 && (t) < 64)
#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 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
@ -374,6 +370,7 @@
//Playlist option byte
#define PL_OPTION_SHUFFLE 0x01
#define PL_OPTION_RESTORE 0x02
// Segment capability byte
#define SEG_CAPABILITY_RGB 0x01
@ -511,10 +508,10 @@
//this is merely a default now and can be changed at runtime
#ifndef LEDPIN
#if defined(ESP8266) || (defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32_PICO)
#define LEDPIN 2 // GPIO2 (D4) on Wemos D1 mini compatible boards, and on boards where GPIO16 is not available
#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, safe to use on any board
#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

Wyświetl plik

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

Wyświetl plik

@ -694,8 +694,6 @@ function parseInfo(i) {
function populateInfo(i)
{
var cn="";
var heap = i.freeheap/1024;
heap = heap.toFixed(1);
var pwr = i.leds.pwr;
var pwru = "Not calculated";
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("Uptime",getRuntimeStr(i.uptime))}
${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"):""}
${inforow("Estimated current",pwru)}
${inforow("Average FPS",i.leds.fps)}
${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("Environment",i.arch + " " + i.core + " (" + i.lwip + ")")}
</table>`;
@ -863,14 +863,11 @@ function populateSegments(s)
gId("segcont").classList.remove("hide");
let noNewSegs = (lowestUnused >= maxSeg);
resetUtil(noNewSegs);
if (gId('selall')) gId('selall').checked = true;
for (var i = 0; i <= lSeg; i++) {
if (!gId(`seg${i}`)) continue;
updateLen(i);
updateTrail(gId(`seg${i}bri`));
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) {
gId(`segd${lSeg}`).classList.add("hide"); // hide delete if only one segment
@ -1462,8 +1459,6 @@ function readState(s,command=false)
return true;
}
if (s.seg.length>2) d.querySelectorAll(".pop").forEach((e)=>{e.classList.remove("hide");});
var cd = gId('csl').querySelectorAll("button");
for (let e = cd.length-1; e >= 0; e--) {
cd[e].dataset.r = i.col[e][0];
@ -1838,7 +1833,7 @@ function makeSeg()
});
var cn = `<div class="seg lstI expanded">`+
`<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">`+
`<tr>`+
`<td width="38%">${isM?'Start X':'Start LED'}</td>`+
@ -1864,13 +1859,19 @@ function makeSeg()
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>'
+ `<div class="segname" ${off?'':'onclick="makeSeg()"'}><i class="icons btn-icon">&#xe18a;</i>Add segment</div>`
+ '<div class="pop hide" onclick="event.stopPropagation();">'
+ `<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></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)
@ -1984,7 +1985,7 @@ function makeP(i,pl)
<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}>
<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)}
</select></div></div>
</div>

Wyświetl plik

@ -23,6 +23,8 @@
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 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
function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
@ -151,7 +153,7 @@
{
const t = parseInt(d.Sf["LT"+n].value); // LED type SELECT
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;
}
function setABL()
@ -188,6 +190,7 @@
if (isDig(t)) {
if (is16b(t)) len *= 2; // 16 bit LEDs
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
mul = 5;
}
@ -202,7 +205,7 @@
function UI(change=false)
{
let isRGBW = false, gRGBW = false, memu = 0;
let gRGBW = false, memu = 0;
let busMA = 0;
let sLC = 0, sPC = 0, sDI = 0, maxLC = 0;
const ablEN = d.Sf.ABL.checked;
@ -242,15 +245,15 @@
d.Sf["MA"+n].min = (isVir(t) || isAna(t)) ? 0 : 250;
}
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("dig"+n+"w").style.display = (isDig(t) && isRGBW) ? "inline":"none"; // show swap channels dropdown
if (!(isDig(t) && isRGBW)) d.Sf["WO"+n].value = 0; // reset swapping
gId("dig"+n+"w").style.display = (isDig(t) && hasW(t)) ? "inline":"none"; // show swap channels dropdown
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+"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+"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("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
@ -383,7 +386,9 @@ ${i+1}:
<option value="25">TM1829</option>\
<option value="26">UCS8903</option>\
<option value="27">APA106/PL9823</option>\
<option value="28">FW1906 GRBCW</option>\
<option value="29">UCS8904 RGBW</option>\
<option value="32">WS2805 RGBCW</option>\
<option value="50">WS2801</option>\
<option value="51">APA102</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="0">Custom</option>
</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>
<div id="co${i}" style="display:inline">Color Order:
@ -861,6 +866,7 @@ Swap: <select id="xw${i}" name="XW${i}">
</select>
<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> %
</div>
<h3>Advanced</h3>

Wyświetl plik

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

Wyświetl plik

@ -20,6 +20,7 @@ void doublePressAction(uint8_t b=0);
bool isButtonPressed(uint8_t b=0);
void handleButton();
void handleIO();
void IRAM_ATTR touchButtonISR();
//cfg.cpp
bool deserializeConfig(JsonObject doc, bool fromFS = false);
@ -233,6 +234,7 @@ const char *getPresetsFileName(bool persistent = true);
void initPresetsFile();
void handlePresets();
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);
inline bool applyTemporaryPreset() {return applyPreset(255);};
void savePreset(byte index, const char* pname = nullptr, JsonObject saveobj = JsonObject());
@ -434,7 +436,6 @@ void handleSerial();
void updateBaudRate(uint32_t rate);
//wled_server.cpp
String getFileContentType(String &filename);
void createEditHandler(bool enable);
void initServer();
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
}
#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
// 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 unsigned long presetsCachedTime;
static uint8_t *presetsCached;
static size_t presetsCachedSize;
if (!psramFound()) {
size = 0;
return nullptr;
}
if (presetsModifiedTime != presetsCachedTime) {
if (presetsCached) {
free(presetsCached);
@ -420,26 +416,19 @@ bool handleFileRead(AsyncWebServerRequest* request, String path){
DEBUG_PRINT(F("WS FileRead: ")); DEBUG_PRINTLN(path);
if(path.endsWith("/")) path += "index.htm";
if(path.indexOf(F("sec")) > -1) return false;
String contentType = getFileContentType(path);
if(request->hasArg(F("download"))) contentType = F("application/octet-stream");
/*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()))) {
#ifdef ARDUINO_ARCH_ESP32
if (psramSafe && psramFound() && path.endsWith(FPSTR(getPresetsFileName()))) {
size_t psize;
const uint8_t *presets = getPresetCache(psize);
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);
return true;
}
}
#endif
if(WLED_FS.exists(path)) {
request->send(WLED_FS, path, contentType);
if(WLED_FS.exists(path) || WLED_FS.exists(path + ".gz")) {
request->send(WLED_FS, path, String(), request->hasArg(F("download")));
return true;
}
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
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
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};
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) {
// 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};
bool colValid = false;
JsonArray colX = colarr[i];
if (colX.isNull()) {
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);
JsonObject oCol = colarr[i];
if (!oCol.isNull()) {
// we have a JSON object for color {"w":123,"r":123,...}; allows individual channel control
rgbw[0] = oCol["r"] | R(seg.colors[i]);
rgbw[1] = oCol["g"] | G(seg.colors[i]);
rgbw[2] = oCol["b"] | B(seg.colors[i]);
rgbw[3] = oCol["w"] | W(seg.colors[i]);
colValid = true;
} else { //HEX string, e.g. "FFAA00"
colValid = colorFromHexString(brgbw, hexCol);
} else {
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]
byte sz = colX.size();
if (sz == 0) continue; //do nothing on empty array
copyArray(colX, rgbw, 4);
colValid = true;
}
@ -226,14 +240,19 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
getVal(elem["ix"], &seg.intensity);
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 (getVal(elem["pal"], &pal)) seg.setPalette(pal);
if (getVal(elem["pal"], &pal, 0, last)) seg.setPalette(pal);
}
getVal(elem["c1"], &seg.custom1);
getVal(elem["c2"], &seg.custom2);
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.check1 = getBoolVal(elem["o1"], seg.check1);
@ -257,8 +276,8 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
seg.fill(BLACK);
}
uint16_t start = 0, stop = 0;
byte set = 0; //0 nothing set, 1 start set, 2 range set
start = 0, stop = 0;
set = 0; //0 nothing set, 1 start set, 2 range set
for (size_t i = 0; i < iarr.size(); i++) {
if(iarr[i].is<JsonInteger>()) {
@ -298,7 +317,7 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
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()
bool deserializeState(JsonObject root, byte callMode, byte presetId)
{
@ -730,6 +749,8 @@ void serializeInfo(JsonObject root)
root[F("arch")] = ESP.getChipModel();
#endif
root[F("core")] = ESP.getSdkVersion();
root[F("clock")] = ESP.getCpuFreqMHz();
root[F("flash")] = (ESP.getFlashChipSize()/1024)/1024;
#ifdef WLED_DEBUG
root[F("maxalloc")] = ESP.getMaxAllocHeap();
root[F("resetReason0")] = (int)rtc_get_reset_reason(0);
@ -739,6 +760,8 @@ void serializeInfo(JsonObject root)
#else
root[F("arch")] = "esp8266";
root[F("core")] = ESP.getCoreVersion();
root[F("clock")] = ESP.getCpuFreqMHz();
root[F("flash")] = (ESP.getFlashChipSize()/1024)/1024;
#ifdef WLED_DEBUG
root[F("maxalloc")] = ESP.getMaxFreeBlockSize();
root[F("resetReason")] = (int)ESP.getResetInfoPtr()->reason;
@ -747,8 +770,8 @@ void serializeInfo(JsonObject root)
#endif
root[F("freeheap")] = ESP.getFreeHeap();
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
if (psramFound()) root[F("psram")] = ESP.getFreePsram();
#if defined(ARDUINO_ARCH_ESP32)
if (psramSafe && psramFound()) root[F("psram")] = ESP.getFreePsram();
#endif
root[F("uptime")] = millis()/1000 + rolloverMillis*4294967;
@ -850,8 +873,8 @@ void serializePalettes(JsonObject root, int page)
int itemPerPage = 8;
#endif
int palettesCount = strip.getPaletteCount();
int customPalettes = strip.customPalettes.size();
int palettesCount = strip.getPaletteCount() - customPalettes;
int maxPage = (palettesCount + customPalettes -1) / itemPerPage;
if (page > maxPage) page = maxPage;
@ -1063,7 +1086,7 @@ void serveJson(AsyncWebServerRequest* request)
}
#endif
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;
}
else if (url.indexOf(F("cfg")) > 0 && handleFileRead(request, F("/cfg.json"))) {
@ -1150,10 +1173,10 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
}
#endif
char buffer[2048]; // shoud be enough for 256 LEDs [RRGGBB] + all other text (9+25)
strcpy_P(buffer, PSTR("{\"leds\":["));
obuf = buffer; // assign buffer for oappnd() functions
olen = 9;
DynamicBuffer buffer(9 + (9*(1+(used/n))) + 7 + 5 + 6 + 5 + 6 + 5 + 2);
char* buf = buffer.data(); // assign buffer for oappnd() functions
strncpy_P(buffer.data(), PSTR("{\"leds\":["), buffer.size());
buf += 9; // sizeof(PSTR()) from last line
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
g = scale8(qadd8(w, g), strip.getBrightness()); //G
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;
oappend((const char*)F("],\"n\":"));
oappendi(n);
buf--; // remove last comma
buf += sprintf_P(buf, PSTR("],\"n\":%d"), n);
#ifndef WLED_DISABLE_2D
if (strip.isMatrix) {
oappend((const char*)F(",\"w\":"));
oappendi(Segment::maxWidth/n);
oappend((const char*)F(",\"h\":"));
oappendi(Segment::maxHeight/n);
buf += sprintf_P(buf, PSTR(",\"w\":%d"), Segment::maxWidth/n);
buf += sprintf_P(buf, PSTR(",\"h\":%d"), Segment::maxHeight/n);
}
#endif
oappend("}");
(*buf++) = '}';
(*buf++) = 0;
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
else {
wsc->text(obuf, olen);
wsc->text(toString(std::move(buffer)));
}
#endif
obuf = nullptr;
#endif
return true;
}
#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 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 ((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 bi = gpio - (by<<3);
return bitRead(pinAlloc[by], bi);
@ -236,8 +235,9 @@ bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag)
*/
// 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
if (digitalPinIsValid(gpio)) {
#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.
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 > 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.
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
// strapping pins: 0, 45 & 46
@ -257,9 +257,8 @@ bool PinManagerClass::isPinOk(byte gpio, bool output)
// GPIO46 is input only and pulled down
#else
if (gpio > 5 && gpio < 12) return false; //SPI flash pins
#ifdef BOARD_HAS_PSRAM
if (gpio == 16 || gpio == 17) return false; //PSRAM pins
#endif
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 !psramFound(); //PSRAM pins on ESP32 (these are IO)
#endif
if (output) return digitalPinCanOutput(gpio);
else return true;
@ -272,8 +271,8 @@ bool PinManagerClass::isPinOk(byte gpio, bool output)
return false;
}
PinOwner PinManagerClass::getPinOwner(byte gpio) {
if (gpio >= WLED_NUM_PINS) return PinOwner::None; // catch error case, to avoid array out-of-bounds access
PinOwner PinManagerClass::getPinOwner(byte gpio) const
{
if (!isPinOk(gpio, false)) return PinOwner::None;
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_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_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");
@ -108,11 +109,11 @@ class PinManagerClass {
inline void deallocatePin(byte gpio) { deallocatePin(gpio, PinOwner::None); }
// 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
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
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
playlistEndPreset = playlistObj["end"] | 0;
// 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;
shuffle = shuffle || playlistObj["r"];
if (shuffle) playlistOptions |= PL_OPTION_SHUFFLE;
@ -122,8 +125,7 @@ int16_t loadPlaylist(JsonObject playlistObj, byte presetId) {
void handlePlaylist() {
static unsigned long presetCycledTime = 0;
// if fileDoc is not null JSON buffer is in use so just quit
if (currentPlaylist < 0 || playlistEntries == nullptr || fileDoc != nullptr) return;
if (currentPlaylist < 0 || playlistEntries == nullptr) return;
if (millis() - presetCycledTime > (100*playlistEntryDur)) {
presetCycledTime = millis();
@ -135,7 +137,7 @@ void handlePlaylist() {
if (!playlistIndex) {
if (playlistRepeat == 1) { //stop if all repetitions are done
unloadPlaylist();
if (playlistEndPreset) applyPreset(playlistEndPreset);
if (playlistEndPreset) applyPresetFromPlaylist(playlistEndPreset);
return;
}
if (playlistRepeat > 1) playlistRepeat--; // decrease repeat count on each index reset if not an endless playlist
@ -146,7 +148,7 @@ void handlePlaylist() {
jsonTransitionOnce = true;
strip.setTransition(fadeTransition ? playlistEntries[playlistIndex].tr * 100 : 0);
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 transition = playlist.createNestedArray(F("transition"));
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;
for (int i=0; i<playlistLen; i++) {
ps.add(playlistEntries[i].preset);

Wyświetl plik

@ -27,7 +27,7 @@ static void doSaveState() {
unsigned long start = millis();
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
JsonObject sObj = pDoc->to<JsonObject>();
@ -53,23 +53,21 @@ static void doSaveState() {
#if defined(ARDUINO_ARCH_ESP32)
if (!persist) {
if (tmpRAMbuffer!=nullptr) free(tmpRAMbuffer);
size_t len = measureJson(*fileDoc) + 1;
size_t len = measureJson(*pDoc) + 1;
DEBUG_PRINTLN(len);
// if possible use SPI RAM on ESP32
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
if (psramFound())
if (psramSafe && psramFound())
tmpRAMbuffer = (char*) ps_malloc(len);
else
#endif
tmpRAMbuffer = (char*) malloc(len);
if (tmpRAMbuffer!=nullptr) {
serializeJson(*fileDoc, tmpRAMbuffer, len);
serializeJson(*pDoc, tmpRAMbuffer, len);
} else {
writeObjectToFileUsingId(getPresetsFileName(persist), presetToSave, fileDoc);
writeObjectToFileUsingId(getPresetsFileName(persist), presetToSave, pDoc);
}
} else
#endif
writeObjectToFileUsingId(getPresetsFileName(persist), presetToSave, fileDoc);
writeObjectToFileUsingId(getPresetsFileName(persist), presetToSave, pDoc);
if (persist) presetsModifiedTime = toki.second(); //unix time
releaseJSONBufferLock();
@ -117,6 +115,15 @@ void initPresetsFile()
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)
{
unloadPlaylist(); // applying a preset unloads the playlist (#3827)
@ -145,7 +152,7 @@ void handlePresets()
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;
uint8_t tmpPreset = presetToApply; // store temporary since deserializeState() may call applyPreset()
@ -153,9 +160,6 @@ void handlePresets()
JsonObject fdo;
// allocate buffer
if (!requestJSONBufferLock(9)) return; // will also assign fileDoc
presetToApply = 0; //clear request for preset
callModeToApply = 0;
@ -164,14 +168,14 @@ void handlePresets()
#ifdef ARDUINO_ARCH_ESP32
if (tmpPreset==255 && tmpRAMbuffer!=nullptr) {
deserializeJson(*fileDoc,tmpRAMbuffer);
deserializeJson(*pDoc,tmpRAMbuffer);
errorFlag = ERR_NONE;
} else
#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
const char* httpwin = fdo["win"];
@ -198,13 +202,13 @@ void handlePresets()
}
#endif
releaseJSONBufferLock(); // will also clear fileDoc
releaseJSONBufferLock();
if (changePreset) notify(tmpMode); // force UDP notification
stateUpdated(tmpMode); // was colorUpdated() if anything breaks
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)
{
if (!saveName) saveName = new char[33];
@ -242,7 +246,7 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
if (sObj[F("playlist")].isNull()) {
// we will save API call immediately (often causes presets.json corruption)
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("v");
sObj.remove("time");
@ -250,7 +254,7 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
sObj.remove(F("psave"));
if (sObj["n"].isNull()) sObj["n"] = saveName;
initPresetsFile(); // just in case if someone deleted presets.json using /edit
writeObjectToFileUsingId(getPresetsFileName(), index, fileDoc);
writeObjectToFileUsingId(getPresetsFileName(), index, pDoc);
presetsModifiedTime = toki.second(); //unix time
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++) {
if (btnPin[s]>=0 && pinManager.isPinAllocated(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"));
correctWB = request->hasArg(F("CCT"));
cctFromRgb = request->hasArg(F("CR"));
cctICused = request->hasArg(F("IC"));
strip.cctBlending = request->arg(F("CB")).toInt();
Bus::setCCTBlend(strip.cctBlending);
Bus::setGlobalAWMode(request->arg(F("AW")).toInt());
@ -240,6 +245,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
rlyMde = (bool)request->hasArg(F("RM"));
disablePullUp = (bool)request->hasArg(F("IP"));
touchThreshold = request->arg(F("TT")).toInt();
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 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;
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
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);
if (digitalPinToTouchChannel(btnPin[i]) < 0)
{
// not a touch pin
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
#endif
@ -281,7 +296,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
buttonType[i] = BTN_TYPE_NONE;
}
}
touchThreshold = request->arg(F("TT")).toInt();
briS = request->arg(F("CA")).toInt();

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -240,10 +240,11 @@ void WLED::loop()
DEBUG_PRINT(F("Runtime: ")); DEBUG_PRINTLN(millis());
DEBUG_PRINT(F("Unix time: ")); toki.printTime(toki.getTime());
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()) {
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");
if (!psramSafe) DEBUG_PRINTLN(F("Not using PSRAM."));
}
#endif
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."));
#else
DEBUG_PRINT(F("esp8266 "));
DEBUG_PRINT(F("esp8266 @ ")); DEBUG_PRINT(ESP.getCpuFreqMHz()); DEBUG_PRINT(F("MHz.\nCore: "));
DEBUG_PRINTLN(ESP.getCoreVersion());
DEBUG_PRINT(F("FLASH: ")); DEBUG_PRINT((ESP.getFlashChipSize()/1024)/1024); DEBUG_PRINTLN(F(" MB"));
#endif
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
/*
* The following code is obsolete as PinManager::isPinOK() will return false for reserved GPIO.
* Additionally xml.cpp will inform UI about reserved GPIO.
*
#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);
#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
#if !defined(BOARD_HAS_PSRAM) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3))
if (psramFound() && ESP.getChipRevision() < 3) psramSafe = false;
if (!psramSafe) DEBUG_PRINTLN(F("Not using PSRAM."));
#endif
*/
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
pDoc = new PSRAMDynamicJsonDocument(2*JSON_BUFFER_SIZE);
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
pDoc = new PSRAMDynamicJsonDocument((psramSafe && psramFound() ? 2 : 1)*JSON_BUFFER_SIZE);
DEBUG_PRINT(F("JSON buffer allocated: ")); DEBUG_PRINTLN((psramSafe && psramFound() ? 2 : 1)*JSON_BUFFER_SIZE);
// if the above fails requestJsonBufferLock() will always return false preventing crashes
if (psramFound()) {
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");
}
#else
if (!pDoc) pDoc = &gDoc; // just in case ... (it should be globally assigned)
DEBUG_PRINTLN(F("PSRAM not used."));
#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)
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"));
deserializeConfigFromFS();
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
#if defined(STATUSLED) && STATUSLED>=0
if (!pinManager.isPinAllocated(STATUSLED)) {
@ -555,7 +527,7 @@ void WLED::setup()
void WLED::beginStrip()
{
// Initialize NeoPixel Strip and button
strip.finalizeInit(); // busses created during deserializeConfig()
strip.finalizeInit(); // busses created during deserializeConfig() if config existed
strip.makeAutoSegments();
strip.setBrightness(0);
strip.setShowCallback(handleOverlayDraw);

Wyświetl plik

@ -3,12 +3,12 @@
/*
Main sketch, global variable declarations
@title WLED project sketch
@version 0.15.0-b1
@version 0.15.0-b3
@author Christian Schwinne
*/
// 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
//#define WLED_USE_MY_CONFIG
@ -158,15 +158,16 @@
// The following is a construct to enable code to compile without it.
// There is a code that will still not use PSRAM though:
// 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 {
void* allocate(size_t size) {
if (psramFound()) return ps_malloc(size); // use PSRAM if it exists
else return malloc(size); // fallback
if (psramSafe && psramFound()) return ps_malloc(size); // use PSRAM if it exists
else return malloc(size); // fallback
}
void* reallocate(void* ptr, size_t new_size) {
if (psramFound()) return ps_realloc(ptr, new_size); // use PSRAM if it exists
else return realloc(ptr, new_size); // fallback
if (psramSafe && psramFound()) return ps_realloc(ptr, new_size); // use PSRAM if it exists
else return realloc(ptr, new_size); // fallback
}
void deallocate(void* pointer) {
free(pointer);
@ -348,6 +349,11 @@ WLED_GLOBAL bool useGlobalLedBuffer _INIT(true); // double buffering enabled on
#endif
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
#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 gammaCorrectBri _INIT(false); // use gamma correction on brightness
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 fsBytesTotal _INIT(0);
WLED_GLOBAL unsigned long presetsModifiedTime _INIT(0L);
WLED_GLOBAL JsonDocument* fileDoc;
WLED_GLOBAL bool doCloseFile _INIT(false);
// presets
@ -706,6 +711,8 @@ WLED_GLOBAL byte optionType;
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 psramSafe _INIT(true); // is it safe to use PSRAM (on ESP32 rev.1; compiler fix used "-mfix-esp32-psram-cache-issue")
// status led
#if defined(STATUSLED)
WLED_GLOBAL unsigned long ledStatusLastMillis _INIT(0);
@ -781,7 +788,7 @@ WLED_GLOBAL int8_t spi_sclk _INIT(SPISCLKPIN);
#endif
// 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);
#else
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_notimplemented[] PROGMEM = "Not implemented";
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?
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) {
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;
}
if (!index) {
@ -204,10 +174,10 @@ static void handleUpload(AsyncWebServerRequest *request, const String& filename,
request->_tempFile.close();
if (filename.indexOf(F("cfg.json")) >= 0) { // check for filename with or without slash
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 {
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++;
}
@ -259,24 +229,24 @@ void initServer()
#ifdef WLED_ENABLE_WEBSOCKETS
#ifndef WLED_DISABLE_2D
server.on(SET_F("/liveview2D"), HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, "", 200, FPSTR(s_html), PAGE_liveviewws2D, PAGE_liveviewws2D_length);
server.on(F("/liveview2D"), HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, "", 200, FPSTR(CONTENT_TYPE_HTML), PAGE_liveviewws2D, PAGE_liveviewws2D_length);
});
#endif
#endif
server.on(SET_F("/liveview"), HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, "", 200, FPSTR(s_html), PAGE_liveview, PAGE_liveview_length);
server.on(F("/liveview"), HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, "", 200, FPSTR(CONTENT_TYPE_HTML), PAGE_liveview, PAGE_liveview_length);
});
//settings page
server.on(SET_F("/settings"), HTTP_GET, [](AsyncWebServerRequest *request){
server.on(F("/settings"), HTTP_GET, [](AsyncWebServerRequest *request){
serveSettings(request);
});
// "/settings/settings.js&p=x" request also handled by serveSettings()
static const char _style_css[] PROGMEM = "/style.css";
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";
@ -287,28 +257,29 @@ void initServer()
static const char _skin_css[] PROGMEM = "/skin.css";
server.on(_skin_css, HTTP_GET, [](AsyncWebServerRequest *request) {
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);
});
server.on(SET_F("/welcome"), HTTP_GET, [](AsyncWebServerRequest *request){
server.on(F("/welcome"), HTTP_GET, [](AsyncWebServerRequest *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);
doReboot = true;
});
server.on(SET_F("/settings"), HTTP_POST, [](AsyncWebServerRequest *request){
server.on(F("/settings"), HTTP_POST, [](AsyncWebServerRequest *request){
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);
});
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler(F("/json"), [](AsyncWebServerRequest *request) {
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler(FPSTR(_json), [](AsyncWebServerRequest *request) {
bool verboseResponse = false;
bool isConfig = false;
@ -356,33 +327,33 @@ void initServer()
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);
server.addHandler(handler);
server.on(SET_F("/version"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(s_plain), (String)VERSION);
server.on(F("/version"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), (String)VERSION);
});
server.on(SET_F("/uptime"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(s_plain), (String)millis());
server.on(F("/uptime"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), (String)millis());
});
server.on(SET_F("/freeheap"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(s_plain), (String)ESP.getFreeHeap());
server.on(F("/freeheap"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), (String)ESP.getFreeHeap());
});
#ifdef WLED_ENABLE_USERMOD_PAGE
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
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);
});
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,
size_t len, bool final) {handleUpload(request, filename, index, data, len, final);}
);
@ -453,7 +424,7 @@ void initServer()
#ifdef WLED_ENABLE_DMX
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
server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){
@ -464,7 +435,7 @@ void initServer()
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
if (captivePortal(request)) return;
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 {
serveSettings(request);
}
@ -473,20 +444,20 @@ void initServer()
#ifdef WLED_ENABLE_PIXART
static const char _pixart_htm[] PROGMEM = "/pixart.htm";
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
#ifndef WLED_DISABLE_PXMAGIC
static const char _pxmagic_htm[] PROGMEM = "/pxmagic.htm";
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
static const char _cpal_htm[] PROGMEM = "/cpal.htm";
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
@ -511,7 +482,7 @@ void initServer()
#ifndef WLED_DISABLE_ALEXA
if(espalexa.handleAlexaApiCall(request)) return;
#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;
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);
if (error < ERR_NOT_IMPL) response->addHeader(F("Retry-After"), F("1"));
response->setContentType(s_json);
response->setContentType(CONTENT_TYPE_JSON);
response->setCode(code);
JsonObject obj = response->getRoot();
obj[F("error")] = error;
@ -546,12 +517,12 @@ void serveSettingsJS(AsyncWebServerRequest* request)
byte subPage = request->arg(F("p")).toInt();
if (subPage > 10) {
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;
}
if (subPage > 0 && !correctPIN && strlen(settingsPIN)>0) {
strcpy_P(buf, PSTR("alert('PIN incorrect.');"));
request->send(401, FPSTR(s_javascript), buf);
request->send(401, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
return;
}
strcat_P(buf,PSTR("function GetV(){var d=document;"));
@ -559,7 +530,7 @@ void serveSettingsJS(AsyncWebServerRequest* request)
strcat_P(buf,PSTR("}"));
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("Expires"), F("0"));
request->send(response);
@ -640,7 +611,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) {
}
int code = 200;
String contentType = FPSTR(s_html);
String contentType = FPSTR(CONTENT_TYPE_HTML);
const uint8_t* content;
size_t len;
@ -666,7 +637,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) {
return;
}
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_WELCOME : content = PAGE_welcome; len = PAGE_welcome_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 {
verboseResponse = deserializeState(root);
}
releaseJSONBufferLock(); // will clean fileDoc
releaseJSONBufferLock();
if (!interfaceUpdateCallMode) { // individual client response only needed if no WS broadcast soon
if (verboseResponse) {
@ -102,7 +102,6 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
void sendDataWs(AsyncWebSocketClient * client)
{
if (!ws.count()) return;
AsyncWebSocketMessageBuffer * buffer;
if (!requestJSONBufferLock(12)) {
if (client) {
@ -129,7 +128,7 @@ void sendDataWs(AsyncWebSocketClient * client)
return;
}
#endif
buffer = ws.makeBuffer(len); // will not allocate correct memory sometimes on ESP8266
AsyncWebSocketBuffer buffer(len);
#ifdef ESP8266
size_t heap2 = 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."));
ws.closeAll(1013); //code 1013 = temporary overload, try again later
ws.cleanupClients(0); //disconnect all clients to release memory
ws._cleanBuffers();
return; //out of memory
}
buffer->lock();
serializeJson(*pDoc, (char *)buffer->get(), len);
serializeJson(*pDoc, (char *)buffer.data(), len);
DEBUG_PRINT(F("Sending WS data "));
if (client) {
client->text(buffer);
client->text(std::move(buffer));
DEBUG_PRINTLN(F("to a single client."));
} else {
ws.textAll(buffer);
ws.textAll(std::move(buffer));
DEBUG_PRINTLN(F("to multiple clients."));
}
buffer->unlock();
ws._cleanBuffers();
releaseJSONBufferLock();
}
@ -187,11 +181,10 @@ bool sendLiveLedsWs(uint32_t wsClient)
#endif
size_t bufSize = pos + (used/n)*3;
AsyncWebSocketMessageBuffer * wsBuf = ws.makeBuffer(bufSize);
AsyncWebSocketBuffer wsBuf(bufSize);
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
wsBuf->lock(); // protect buffer from being cleaned by another WS instance
buffer[0] = 'L';
buffer[1] = 1; //version
@ -218,9 +211,7 @@ bool sendLiveLedsWs(uint32_t wsClient)
buffer[pos++] = scale8(qadd8(w, b), strip.getBrightness()); //B
}
wsc->binary(wsBuf);
wsBuf->unlock(); // un-protect buffer
ws._cleanBuffers();
wsc->binary(std::move(wsBuf));
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"));
#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)
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)
oappend(SET_F("d.rsvd=[11,12,13,14,15,16,17"));
#elif defined(ESP32)
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
oappend(SET_F("d.rsvd=[6,7,8,9,10,11"));
#endif
@ -163,14 +166,6 @@ void appendGPIOinfo() {
//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
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)); }
@ -360,6 +355,7 @@ void getSettingsJS(byte subPage, char* dest)
sappend('c',SET_F("MS"),autoSegments);
sappend('c',SET_F("CCT"),correctWB);
sappend('c',SET_F("IC"),cctICused);
sappend('c',SET_F("CR"),cctFromRgb);
sappend('v',SET_F("CB"),strip.cctBlending);
sappend('v',SET_F("FR"),strip.getTargetFps());