mirror of
https://github.com/wled/WLED.git
synced 2025-07-17 15:56:31 +00:00
Merge branch '0_15' into main
This commit is contained in:
commit
fa5d60ca26
4
.github/workflows/wled-ci.yml
vendored
4
.github/workflows/wled-ci.yml
vendored
@ -37,7 +37,7 @@ jobs:
|
|||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
- run: npm install
|
- run: npm ci
|
||||||
- name: Cache PlatformIO
|
- name: Cache PlatformIO
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
@ -61,7 +61,7 @@ jobs:
|
|||||||
name: firmware-${{ matrix.environment }}
|
name: firmware-${{ matrix.environment }}
|
||||||
path: |
|
path: |
|
||||||
build_output/release/*.bin
|
build_output/release/*.bin
|
||||||
build_output/release/*_ESP02.bin.gz
|
build_output/release/*_ESP02*.bin.gz
|
||||||
release:
|
release:
|
||||||
name: Create Release
|
name: Create Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
58
CHANGELOG.md
58
CHANGELOG.md
@ -1,5 +1,43 @@
|
|||||||
## WLED changelog
|
## WLED changelog
|
||||||
|
|
||||||
|
#### 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 (for future WS2805 support)
|
||||||
|
- 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
|
||||||
|
- Updated AsyncWebServer (by @wlillmmiles)
|
||||||
|
- Simpler boot preset (fix for #3806)
|
||||||
|
- Effect: Fix for 2D Drift animation (#3816 by @BaptisteHudyma)
|
||||||
|
- Effect: Add twin option to 2D Drift
|
||||||
|
- MQTT cleanup
|
||||||
|
- DDP: Support sources that don't push (#3833 by @willmmiles)
|
||||||
|
- Usermod: Tetris AI usermod (#3711 by @muebau)
|
||||||
|
|
||||||
|
#### Build 2403171
|
||||||
|
- merge 0.14.2 changes into 0.15
|
||||||
|
|
||||||
#### Build 2403070
|
#### Build 2403070
|
||||||
- Add additional segment options when controlling over e1.31 (#3616 by @demophoon)
|
- Add additional segment options when controlling over e1.31 (#3616 by @demophoon)
|
||||||
- LockedJsonResponse: Release early if possible (#3760 by @willmmiles)
|
- LockedJsonResponse: Release early if possible (#3760 by @willmmiles)
|
||||||
@ -120,6 +158,26 @@
|
|||||||
- send UDP/WS on segment change
|
- send UDP/WS on segment change
|
||||||
- pop_back() when removing last segment
|
- pop_back() when removing last segment
|
||||||
|
|
||||||
|
#### Build 2403170
|
||||||
|
- WLED 0.14.2 release
|
||||||
|
|
||||||
|
#### Build 2403110
|
||||||
|
- Beta WLED 0.14.2-b2
|
||||||
|
- New AsyncWebServer (improved performance and reduced memory use)
|
||||||
|
- New builds for ESP8266 with 160MHz CPU clock
|
||||||
|
- Fixing stairway usermod and adding buildflags (#3758 by @lost-hope)
|
||||||
|
- Fixing a potential array bounds violation in ESPDMX
|
||||||
|
- Reduced RAM usage (moved strings and TZ data (by @willmmiles) to PROGMEM)
|
||||||
|
- LockedJsonResponse: Release early if possible (by @willmmiles)
|
||||||
|
|
||||||
|
#### Build 2402120
|
||||||
|
- Beta WLED 0.14.2-b1
|
||||||
|
- Possible fix for #3589 & partial fix for #3605
|
||||||
|
- Prevent JSON buffer clear after failed lock attempt
|
||||||
|
- Multiple analog button fix for #3549
|
||||||
|
- UM Audioreactive: add two compiler options (#3732 by @wled-install)
|
||||||
|
- Fix for #3693
|
||||||
|
|
||||||
#### Build 2401141
|
#### Build 2401141
|
||||||
- Official release of WLED 0.14.1
|
- Official release of WLED 0.14.1
|
||||||
- Fix for #3566, #3665, #3672
|
- Fix for #3566, #3665, #3672
|
||||||
|
@ -2,6 +2,20 @@
|
|||||||
|
|
||||||
Here are a few suggestions to make it easier for you to contribute!
|
Here are a few suggestions to make it easier for you to contribute!
|
||||||
|
|
||||||
|
### Describe your PR
|
||||||
|
|
||||||
|
Please add a description of your proposed code changes. It does not need to be an exhaustive essay, however a PR with no description or just a few words might not get accepted, simply because very basic information is missing.
|
||||||
|
|
||||||
|
A good description helps us to review and understand your proposed changes. For example, you could say a few words about
|
||||||
|
* what you try to achieve (new feature, fixing a bug, refactoring, security enhancements, etc.)
|
||||||
|
* how your code works (short technical summary - focus on important aspects that might not be obvious when reading the code)
|
||||||
|
* testing you performed, known limitations, open ends you possibly could not solve.
|
||||||
|
* any areas where you like to get help from an experienced maintainer (yes WLED has become big 😉)
|
||||||
|
|
||||||
|
### Target branch for pull requests
|
||||||
|
|
||||||
|
Please make all PRs against the `0_15` branch.
|
||||||
|
|
||||||
### Code style
|
### Code style
|
||||||
|
|
||||||
When in doubt, it is easiest to replicate the code style you find in the files you want to edit :)
|
When in doubt, it is easiest to replicate the code style you find in the files you want to edit :)
|
||||||
@ -73,6 +87,6 @@ Good:
|
|||||||
<!-- This is an HTML comment -->
|
<!-- This is an HTML comment -->
|
||||||
```
|
```
|
||||||
|
|
||||||
There is no set character limit for a comment within a line,
|
There is no hard character limit for a comment within a line,
|
||||||
though as a rule of thumb you should wrap your comment if it exceeds the width of your editor window.
|
though as a rule of thumb consider wrapping after 120 characters.
|
||||||
Inline comments are OK if they describe that line only and are not exceedingly wide.
|
Inline comments are OK if they describe that line only and are not exceedingly wide.
|
102
package-lock.json
generated
102
package-lock.json
generated
@ -1,57 +1,56 @@
|
|||||||
{
|
{
|
||||||
"name": "wled",
|
"name": "wled",
|
||||||
"version": "0.15.0-b1",
|
"version": "0.15.0-b2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "wled",
|
"name": "wled",
|
||||||
"version": "0.15.0-b1",
|
"version": "0.15.0-b2",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clean-css": "^5.3.3",
|
"clean-css": "^5.3.3",
|
||||||
"html-minifier-terser": "^7.2.0",
|
"html-minifier-terser": "^7.2.0",
|
||||||
"inliner": "^1.13.1",
|
"inliner": "^1.13.1",
|
||||||
"nodemon": "^3.0.2",
|
"nodemon": "^3.0.2"
|
||||||
"zlib": "^1.0.5"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/gen-mapping": {
|
"node_modules/@jridgewell/gen-mapping": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
|
||||||
"integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
|
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/set-array": "^1.0.1",
|
"@jridgewell/set-array": "^1.2.1",
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||||
"@jridgewell/trace-mapping": "^0.3.9"
|
"@jridgewell/trace-mapping": "^0.3.24"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/resolve-uri": {
|
"node_modules/@jridgewell/resolve-uri": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||||
"integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
|
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/set-array": {
|
"node_modules/@jridgewell/set-array": {
|
||||||
"version": "1.1.2",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
||||||
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
|
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/source-map": {
|
"node_modules/@jridgewell/source-map": {
|
||||||
"version": "0.3.5",
|
"version": "0.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
|
||||||
"integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==",
|
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/gen-mapping": "^0.3.0",
|
"@jridgewell/gen-mapping": "^0.3.5",
|
||||||
"@jridgewell/trace-mapping": "^0.3.9"
|
"@jridgewell/trace-mapping": "^0.3.25"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/sourcemap-codec": {
|
"node_modules/@jridgewell/sourcemap-codec": {
|
||||||
@ -60,9 +59,9 @@
|
|||||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
|
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/trace-mapping": {
|
"node_modules/@jridgewell/trace-mapping": {
|
||||||
"version": "0.3.21",
|
"version": "0.3.25",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
||||||
"integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==",
|
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/resolve-uri": "^3.1.0",
|
"@jridgewell/resolve-uri": "^3.1.0",
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
@ -209,11 +208,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/binary-extensions": {
|
"node_modules/binary-extensions": {
|
||||||
"version": "2.2.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/boolbase": {
|
"node_modules/boolbase": {
|
||||||
@ -324,15 +326,9 @@
|
|||||||
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
|
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
|
||||||
},
|
},
|
||||||
"node_modules/chokidar": {
|
"node_modules/chokidar": {
|
||||||
"version": "3.5.3",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||||
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "individual",
|
|
||||||
"url": "https://paulmillr.com/funding/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"anymatch": "~3.1.2",
|
"anymatch": "~3.1.2",
|
||||||
"braces": "~3.0.2",
|
"braces": "~3.0.2",
|
||||||
@ -345,6 +341,9 @@
|
|||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 8.10.0"
|
"node": ">= 8.10.0"
|
||||||
},
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
@ -1376,9 +1375,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/nodemon": {
|
"node_modules/nodemon": {
|
||||||
"version": "3.0.3",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz",
|
||||||
"integrity": "sha512-7jH/NXbFPxVaMwmBCC2B9F/V6X1VkEdNgx3iu9jji8WxWcvhMWkmhNWhI5077zknOnZnBzba9hZP6bCPJLSReQ==",
|
"integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": "^3.5.2",
|
"chokidar": "^3.5.2",
|
||||||
"debug": "^4",
|
"debug": "^4",
|
||||||
@ -1827,9 +1826,9 @@
|
|||||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.5.4",
|
"version": "7.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
||||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lru-cache": "^6.0.0"
|
"lru-cache": "^6.0.0"
|
||||||
},
|
},
|
||||||
@ -1925,9 +1924,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/stream-shift": {
|
"node_modules/stream-shift": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
|
||||||
"integrity": "sha512-rV4Bovi9xx0BFzOb/X0B2GqoIjvqPCttZdu0Wgtx2Dxkj7ETyWl9gmqJ4EutWRLvtZWm8dxE+InQZX1IryZn/w=="
|
"integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ=="
|
||||||
},
|
},
|
||||||
"node_modules/string_decoder": {
|
"node_modules/string_decoder": {
|
||||||
"version": "0.10.31",
|
"version": "0.10.31",
|
||||||
@ -1994,9 +1993,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/terser": {
|
"node_modules/terser": {
|
||||||
"version": "5.27.0",
|
"version": "5.29.2",
|
||||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz",
|
"resolved": "https://registry.npmjs.org/terser/-/terser-5.29.2.tgz",
|
||||||
"integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==",
|
"integrity": "sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/source-map": "^0.3.3",
|
"@jridgewell/source-map": "^0.3.3",
|
||||||
"acorn": "^8.8.2",
|
"acorn": "^8.8.2",
|
||||||
@ -2245,15 +2244,6 @@
|
|||||||
"decamelize": "^1.0.0",
|
"decamelize": "^1.0.0",
|
||||||
"window-size": "0.1.0"
|
"window-size": "0.1.0"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"node_modules/zlib": {
|
|
||||||
"version": "1.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/zlib/-/zlib-1.0.5.tgz",
|
|
||||||
"integrity": "sha512-40fpE2II+Cd3k8HWTWONfeKE2jL+P42iWJ1zzps5W51qcTsOUKM5Q5m2PFb0CLxlmFAaUuUdJGc3OfZy947v0w==",
|
|
||||||
"hasInstallScript": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.2.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "wled",
|
"name": "wled",
|
||||||
"version": "0.15.0-b1",
|
"version": "0.15.0-b2",
|
||||||
"description": "Tools for WLED project",
|
"description": "Tools for WLED project",
|
||||||
"main": "tools/cdata.js",
|
"main": "tools/cdata.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
@ -26,7 +26,6 @@
|
|||||||
"clean-css": "^5.3.3",
|
"clean-css": "^5.3.3",
|
||||||
"html-minifier-terser": "^7.2.0",
|
"html-minifier-terser": "^7.2.0",
|
||||||
"inliner": "^1.13.1",
|
"inliner": "^1.13.1",
|
||||||
"nodemon": "^3.0.2",
|
"nodemon": "^3.0.2"
|
||||||
"zlib": "^1.0.5"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
import gzip
|
import gzip
|
||||||
|
|
||||||
OUTPUT_DIR = "build_output{}".format(os.path.sep)
|
OUTPUT_DIR = os.path.join("build_output")
|
||||||
|
|
||||||
def _get_cpp_define_value(env, define):
|
def _get_cpp_define_value(env, define):
|
||||||
define_list = [item[-1] for item in env["CPPDEFINES"] if item[0] == define]
|
define_list = [item[-1] for item in env["CPPDEFINES"] if item[0] == define]
|
||||||
@ -13,24 +13,19 @@ def _get_cpp_define_value(env, define):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _create_dirs(dirs=["firmware", "map"]):
|
def _create_dirs(dirs=["map", "release"]):
|
||||||
# check if output directories exist and create if necessary
|
|
||||||
if not os.path.isdir(OUTPUT_DIR):
|
|
||||||
os.mkdir(OUTPUT_DIR)
|
|
||||||
|
|
||||||
for d in dirs:
|
for d in dirs:
|
||||||
if not os.path.isdir("{}{}".format(OUTPUT_DIR, d)):
|
os.makedirs(os.path.join(OUTPUT_DIR, d), exist_ok=True)
|
||||||
os.mkdir("{}{}".format(OUTPUT_DIR, d))
|
|
||||||
|
|
||||||
def create_release(source):
|
def create_release(source):
|
||||||
release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME")
|
release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME")
|
||||||
if release_name:
|
if release_name:
|
||||||
_create_dirs(["release"])
|
|
||||||
version = _get_cpp_define_value(env, "WLED_VERSION")
|
version = _get_cpp_define_value(env, "WLED_VERSION")
|
||||||
# get file extension of source file (.bin or .bin.gz)
|
release_file = os.path.join(OUTPUT_DIR, "release", f"WLED_{version}_{release_name}.bin")
|
||||||
ext = source.split(".", 1)[1]
|
release_gz_file = release_file + ".gz"
|
||||||
release_file = "{}release{}WLED_{}_{}.{}".format(OUTPUT_DIR, os.path.sep, version, release_name, ext)
|
print(f"Copying {source} to {release_file}")
|
||||||
shutil.copy(source, release_file)
|
shutil.copy(source, release_file)
|
||||||
|
bin_gzip(release_file, release_gz_file)
|
||||||
|
|
||||||
def bin_rename_copy(source, target, env):
|
def bin_rename_copy(source, target, env):
|
||||||
_create_dirs()
|
_create_dirs()
|
||||||
@ -38,38 +33,21 @@ def bin_rename_copy(source, target, env):
|
|||||||
|
|
||||||
# create string with location and file names based on variant
|
# create string with location and file names based on variant
|
||||||
map_file = "{}map{}{}.map".format(OUTPUT_DIR, os.path.sep, variant)
|
map_file = "{}map{}{}.map".format(OUTPUT_DIR, os.path.sep, variant)
|
||||||
bin_file = "{}firmware{}{}.bin".format(OUTPUT_DIR, os.path.sep, variant)
|
|
||||||
|
|
||||||
# check if new target files exist and remove if necessary
|
create_release(str(target[0]))
|
||||||
for f in [map_file, bin_file]:
|
|
||||||
if os.path.isfile(f):
|
|
||||||
os.remove(f)
|
|
||||||
|
|
||||||
# copy firmware.bin to firmware/<variant>.bin
|
|
||||||
shutil.copy(str(target[0]), bin_file)
|
|
||||||
|
|
||||||
create_release(bin_file)
|
|
||||||
|
|
||||||
# copy firmware.map to map/<variant>.map
|
# copy firmware.map to map/<variant>.map
|
||||||
if os.path.isfile("firmware.map"):
|
if os.path.isfile("firmware.map"):
|
||||||
shutil.move("firmware.map", map_file)
|
shutil.move("firmware.map", map_file)
|
||||||
|
|
||||||
def bin_gzip(source, target, env):
|
def bin_gzip(source, target):
|
||||||
_create_dirs()
|
# only create gzip for esp8266
|
||||||
variant = env["PIOENV"]
|
if not env["PIOPLATFORM"] == "espressif8266":
|
||||||
|
return
|
||||||
# create string with location and file names based on variant
|
|
||||||
bin_file = "{}firmware{}{}.bin".format(OUTPUT_DIR, os.path.sep, variant)
|
print(f"Creating gzip file {target} from {source}")
|
||||||
gzip_file = "{}firmware{}{}.bin.gz".format(OUTPUT_DIR, os.path.sep, variant)
|
with open(source,"rb") as fp:
|
||||||
|
with gzip.open(target, "wb", compresslevel = 9) as f:
|
||||||
# check if new target files exist and remove if necessary
|
|
||||||
if os.path.isfile(gzip_file): os.remove(gzip_file)
|
|
||||||
|
|
||||||
# write gzip firmware file
|
|
||||||
with open(bin_file,"rb") as fp:
|
|
||||||
with gzip.open(gzip_file, "wb", compresslevel = 9) as f:
|
|
||||||
shutil.copyfileobj(fp, f)
|
shutil.copyfileobj(fp, f)
|
||||||
|
|
||||||
create_release(gzip_file)
|
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", bin_rename_copy)
|
||||||
|
|
||||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [bin_rename_copy, bin_gzip])
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
# CI/release binaries
|
# CI/release binaries
|
||||||
default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, 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, esp32_wrover
|
||||||
|
|
||||||
src_dir = ./wled00
|
src_dir = ./wled00
|
||||||
data_dir = ./wled00/data
|
data_dir = ./wled00/data
|
||||||
@ -41,14 +41,13 @@ arduino_core_git = https://github.com/platformio/platform-espressif8266#feature/
|
|||||||
platform_wled_default = ${common.arduino_core_3_1_2}
|
platform_wled_default = ${common.arduino_core_3_1_2}
|
||||||
# We use 2.7.4.7 for all, includes PWM flicker fix and Wstring optimization
|
# We use 2.7.4.7 for all, includes PWM flicker fix and Wstring optimization
|
||||||
#platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7
|
#platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7
|
||||||
platform_packages = platformio/framework-arduinoespressif8266
|
platform_packages = platformio/toolchain-xtensa @ ~2.100300.220621 #2.40802.200502
|
||||||
platformio/toolchain-xtensa @ ~2.100300.220621 #2.40802.200502
|
|
||||||
platformio/tool-esptool #@ ~1.413.0
|
platformio/tool-esptool #@ ~1.413.0
|
||||||
platformio/tool-esptoolpy #@ ~1.30000.0
|
platformio/tool-esptoolpy #@ ~1.30000.0
|
||||||
|
|
||||||
## previous platform for 8266, in case of problems with the new one
|
## previous platform for 8266, in case of problems with the new one
|
||||||
## you'll need makuna/NeoPixelBus@ 2.6.9 for arduino_core_3_2_0, which does not support Ucs890x
|
## you'll need makuna/NeoPixelBus@ 2.6.9 for arduino_core_3_0_2, which does not support Ucs890x
|
||||||
;; platform_wled_default = ${common.arduino_core_3_2_0}
|
;; platform_wled_default = ${common.arduino_core_3_0_2}
|
||||||
;; platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7
|
;; platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7
|
||||||
;; platformio/toolchain-xtensa @ ~2.40802.200502
|
;; platformio/toolchain-xtensa @ ~2.40802.200502
|
||||||
;; platformio/tool-esptool @ ~1.413.0
|
;; platformio/tool-esptool @ ~1.413.0
|
||||||
@ -143,8 +142,8 @@ lib_compat_mode = strict
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
fastled/FastLED @ 3.6.0
|
fastled/FastLED @ 3.6.0
|
||||||
IRremoteESP8266 @ 2.8.2
|
IRremoteESP8266 @ 2.8.2
|
||||||
makuna/NeoPixelBus @ 2.7.5
|
makuna/NeoPixelBus @ 2.7.9
|
||||||
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.7
|
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ^2.2.0
|
||||||
# for I2C interface
|
# for I2C interface
|
||||||
;Wire
|
;Wire
|
||||||
# ESP-NOW library
|
# ESP-NOW library
|
||||||
@ -317,6 +316,11 @@ build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 #-DWLED
|
|||||||
lib_deps = ${esp8266.lib_deps}
|
lib_deps = ${esp8266.lib_deps}
|
||||||
monitor_filters = esp8266_exception_decoder
|
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
|
||||||
|
|
||||||
[env:esp8266_2m]
|
[env:esp8266_2m]
|
||||||
board = esp_wroom_02
|
board = esp_wroom_02
|
||||||
platform = ${common.platform_wled_default}
|
platform = ${common.platform_wled_default}
|
||||||
@ -326,6 +330,11 @@ 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
|
||||||
lib_deps = ${esp8266.lib_deps}
|
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
|
||||||
|
|
||||||
[env:esp01_1m_full]
|
[env:esp01_1m_full]
|
||||||
board = esp01_1m
|
board = esp01_1m
|
||||||
platform = ${common.platform_wled_default}
|
platform = ${common.platform_wled_default}
|
||||||
@ -336,6 +345,12 @@ build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01 -D WLED_D
|
|||||||
; -D WLED_USE_UNREAL_MATH ;; may cause wrong sunset/sunrise times, but saves 7064 bytes FLASH and 975 bytes RAM
|
; -D WLED_USE_UNREAL_MATH ;; may cause wrong sunset/sunrise times, but saves 7064 bytes FLASH and 975 bytes RAM
|
||||||
lib_deps = ${esp8266.lib_deps}
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:esp01_1m_full_160]
|
||||||
|
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
|
||||||
|
; -D WLED_USE_UNREAL_MATH ;; may cause wrong sunset/sunrise times, but saves 7064 bytes FLASH and 975 bytes RAM
|
||||||
|
|
||||||
[env:esp32dev]
|
[env:esp32dev]
|
||||||
board = esp32dev
|
board = esp32dev
|
||||||
platform = ${esp32.platform}
|
platform = ${esp32.platform}
|
||||||
@ -376,11 +391,10 @@ platform = ${esp32.platform}
|
|||||||
board = ttgo-t7-v14-mini32
|
board = ttgo-t7-v14-mini32
|
||||||
board_build.f_flash = 80000000L
|
board_build.f_flash = 80000000L
|
||||||
board_build.flash_mode = qio
|
board_build.flash_mode = qio
|
||||||
board_build.partitions = ${esp32.default_partitions}
|
board_build.partitions = tools/WLED_ESP32-wrover_4MB.csv
|
||||||
build_unflags = ${common.build_unflags}
|
build_unflags = ${common.build_unflags}
|
||||||
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_WROVER
|
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_WROVER
|
||||||
-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue
|
-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue ;; Older ESP32 (rev.<3) need a PSRAM fix (increases static RAM used) https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/external-ram.html
|
||||||
-D WLED_USE_PSRAM
|
|
||||||
-D LEDPIN=25
|
-D LEDPIN=25
|
||||||
lib_deps = ${esp32.lib_deps}
|
lib_deps = ${esp32.lib_deps}
|
||||||
|
|
||||||
@ -432,7 +446,6 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=
|
|||||||
;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
|
;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
|
||||||
-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
|
-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
|
||||||
; -D WLED_RELEASE_NAME=ESP32-S3_PSRAM
|
; -D WLED_RELEASE_NAME=ESP32-S3_PSRAM
|
||||||
-D WLED_USE_PSRAM -DBOARD_HAS_PSRAM ; tells WLED that PSRAM shall be used
|
|
||||||
lib_deps = ${esp32s3.lib_deps}
|
lib_deps = ${esp32s3.lib_deps}
|
||||||
board_build.partitions = tools/WLED_ESP32_8MB.csv
|
board_build.partitions = tools/WLED_ESP32_8MB.csv
|
||||||
board_build.f_flash = 80000000L
|
board_build.f_flash = 80000000L
|
||||||
@ -448,12 +461,10 @@ board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
|
|||||||
;board_build.f_flash = 80000000L
|
;board_build.f_flash = 80000000L
|
||||||
build_unflags = ${common.build_unflags}
|
build_unflags = ${common.build_unflags}
|
||||||
build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=ESP32-S2
|
build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=ESP32-S2
|
||||||
-DBOARD_HAS_PSRAM
|
|
||||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||||
-DARDUINO_USB_MSC_ON_BOOT=0
|
-DARDUINO_USB_MSC_ON_BOOT=0
|
||||||
-DARDUINO_USB_DFU_ON_BOOT=0
|
-DARDUINO_USB_DFU_ON_BOOT=0
|
||||||
-DLOLIN_WIFI_FIX ; seems to work much better with this
|
-DLOLIN_WIFI_FIX ; seems to work much better with this
|
||||||
-D WLED_USE_PSRAM
|
|
||||||
-D WLED_WATCHDOG_TIMEOUT=0
|
-D WLED_WATCHDOG_TIMEOUT=0
|
||||||
-D CONFIG_ASYNC_TCP_USE_WDT=0
|
-D CONFIG_ASYNC_TCP_USE_WDT=0
|
||||||
-D LEDPIN=16
|
-D LEDPIN=16
|
||||||
|
@ -155,9 +155,8 @@ build_flags = ${common.build_flags_esp8266}
|
|||||||
; set default color order of your led strip
|
; set default color order of your led strip
|
||||||
; -D DEFAULT_LED_COLOR_ORDER=COL_ORDER_GRB
|
; -D DEFAULT_LED_COLOR_ORDER=COL_ORDER_GRB
|
||||||
;
|
;
|
||||||
; use PSRAM if a device (ESP) has one
|
; use PSRAM on classic ESP32 rev.1 (rev.3 or above has no issues)
|
||||||
; -DBOARD_HAS_PSRAM
|
; -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue
|
||||||
; -D WLED_USE_PSRAM
|
|
||||||
;
|
;
|
||||||
; configure I2C and SPI interface (for various hardware)
|
; configure I2C and SPI interface (for various hardware)
|
||||||
; -D I2CSDAPIN=33 # initialise interface
|
; -D I2CSDAPIN=33 # initialise interface
|
||||||
|
@ -36,7 +36,7 @@ marshmallow==3.19.0
|
|||||||
# via platformio
|
# via platformio
|
||||||
packaging==23.1
|
packaging==23.1
|
||||||
# via marshmallow
|
# via marshmallow
|
||||||
platformio==6.1.6
|
platformio==6.1.14
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
pyelftools==0.29
|
pyelftools==0.29
|
||||||
# via platformio
|
# via platformio
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Name, Type, SubType, Offset, Size, Flags
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
nvs, data, nvs, 0x9000, 0x5000,
|
nvs, data, nvs, 0x9000, 0x5000,
|
||||||
otadata, data, ota, 0xe000, 0x2000,
|
otadata, data, ota, 0xe000, 0x2000,
|
||||||
app0, app, ota_0, 0x10000, 0x180000,
|
app0, app, ota_0, 0x10000, 0x1A0000,
|
||||||
app1, app, ota_1, 0x190000,0x180000,
|
app1, app, ota_1, 0x1B0000,0x1A0000,
|
||||||
spiffs, data, spiffs, 0x310000,0xF0000,
|
spiffs, data, spiffs, 0x350000,0xB0000,
|
||||||
|
|
@ -15,10 +15,10 @@
|
|||||||
* It uses NodeJS packages to inline, minify and GZIP files. See writeHtmlGzipped and writeChunks invocations at the bottom of the page.
|
* It uses NodeJS packages to inline, minify and GZIP files. See writeHtmlGzipped and writeChunks invocations at the bottom of the page.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require("fs");
|
const fs = require("node:fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const inliner = require("inliner");
|
const inliner = require("inliner");
|
||||||
const zlib = require("zlib");
|
const zlib = require("node:zlib");
|
||||||
const CleanCSS = require("clean-css");
|
const CleanCSS = require("clean-css");
|
||||||
const minifyHtml = require("html-minifier-terser").minify;
|
const minifyHtml = require("html-minifier-terser").minify;
|
||||||
const packageJson = require("../package.json");
|
const packageJson = require("../package.json");
|
||||||
@ -30,14 +30,12 @@ const output = ["wled00/html_ui.h", "wled00/html_pixart.h", "wled00/html_cpal.h"
|
|||||||
|
|
||||||
// \x1b[34m is blue, \x1b[36m is cyan, \x1b[0m is reset
|
// \x1b[34m is blue, \x1b[36m is cyan, \x1b[0m is reset
|
||||||
const wledBanner = `
|
const wledBanner = `
|
||||||
\t\x1b[34m## ## ## ######## ########
|
\t\x1b[34m ## ## ## ###### ######
|
||||||
\t\x1b[34m## ## ## ## ## ## ##
|
\t\x1b[34m## ## ## ## ## ## ##
|
||||||
\t\x1b[34m## ## ## ## ## ## ##
|
\t\x1b[34m## ## ## ## ###### ## ##
|
||||||
\t\x1b[34m## ## ## ## ###### ## ##
|
\t\x1b[34m## ## ## ## ## ## ##
|
||||||
\t\x1b[34m## ## ## ## ## ## ##
|
\t\x1b[34m ## ## ###### ###### ######
|
||||||
\t\x1b[34m## ## ## ## ## ## ##
|
\t\t\x1b[36m build script for web UI
|
||||||
\t\x1b[34m ### ### ######## ######## ########
|
|
||||||
\t\t\x1b[36mbuild script for web UI
|
|
||||||
\x1b[0m`;
|
\x1b[0m`;
|
||||||
|
|
||||||
const singleHeader = `/*
|
const singleHeader = `/*
|
||||||
|
117
usermods/TetrisAI_v2/gridbw.h
Normal file
117
usermods/TetrisAI_v2/gridbw.h
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* @file : gridbw.h
|
||||||
|
* @brief : contains the tetris grid as binary so black and white version
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* Copyright (c) muebau 2023
|
||||||
|
* All rights reserved.</center></h2>
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GRIDBW_H__
|
||||||
|
#define __GRIDBW_H__
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <vector>
|
||||||
|
#include "pieces.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class GridBW
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
uint8_t width;
|
||||||
|
uint8_t height;
|
||||||
|
std::vector<uint32_t> pixels;
|
||||||
|
|
||||||
|
GridBW(uint8_t width, uint8_t height):
|
||||||
|
width(width),
|
||||||
|
height(height),
|
||||||
|
pixels(height)
|
||||||
|
{
|
||||||
|
if (width > 32)
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("maximal width is 32");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void placePiece(Piece* piece, uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
for (uint8_t row = 4 - piece->getRotation().height; row < 4; row++)
|
||||||
|
{
|
||||||
|
pixels[y + (row - (4 - piece->getRotation().height))] |= piece->getGridRow(x, row, width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void erasePiece(Piece* piece, uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
for (uint8_t row = 4 - piece->getRotation().height; row < 4; row++)
|
||||||
|
{
|
||||||
|
pixels[y + (row - (4 - piece->getRotation().height))] &= ~piece->getGridRow(x, row, width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool noCollision(Piece* piece, uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
//if it touches a wall it is a collision
|
||||||
|
if (x > (this->width - piece->getRotation().width) || y > this->height - piece->getRotation().height)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t row = 4 - piece->getRotation().height; row < 4; row++)
|
||||||
|
{
|
||||||
|
if (piece->getGridRow(x, row, width) & pixels[y + (row - (4 - piece->getRotation().height))])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void findLandingPosition(Piece* piece)
|
||||||
|
{
|
||||||
|
// move down until the piece bumps into some occupied pixels or the 'wall'
|
||||||
|
while (noCollision(piece, piece->x, piece->landingY))
|
||||||
|
{
|
||||||
|
piece->landingY++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//at this point the positon is 'in the wall' or 'over some occupied pixel'
|
||||||
|
//so the previous position was the last correct one (clamped to 0 as minimum).
|
||||||
|
piece->landingY = piece->landingY > 0 ? piece->landingY - 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanupFullLines()
|
||||||
|
{
|
||||||
|
uint8_t offset = 0;
|
||||||
|
|
||||||
|
//from "height - 1" to "0", so from bottom row to top
|
||||||
|
for (uint8_t row = height; row-- > 0; )
|
||||||
|
{
|
||||||
|
//full line?
|
||||||
|
if (isLineFull(row))
|
||||||
|
{
|
||||||
|
offset++;
|
||||||
|
pixels[row] = 0x0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset > 0)
|
||||||
|
{
|
||||||
|
pixels[row + offset] = pixels[row];
|
||||||
|
pixels[row] = 0x0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isLineFull(uint8_t y)
|
||||||
|
{
|
||||||
|
return pixels[y] == (uint32_t)((1 << width) - 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __GRIDBW_H__ */
|
132
usermods/TetrisAI_v2/gridcolor.h
Normal file
132
usermods/TetrisAI_v2/gridcolor.h
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* @file : gridcolor.h
|
||||||
|
* @brief : contains the tetris grid as 8bit indexed color version
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* Copyright (c) muebau 2023
|
||||||
|
* All rights reserved.</center></h2>
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GRIDCOLOR_H__
|
||||||
|
#define __GRIDCOLOR_H__
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <vector>
|
||||||
|
#include "gridbw.h"
|
||||||
|
#include "gridcolor.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class GridColor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
uint8_t width;
|
||||||
|
uint8_t height;
|
||||||
|
GridBW gridBW;
|
||||||
|
std::vector<uint8_t> pixels;
|
||||||
|
|
||||||
|
GridColor(uint8_t width, uint8_t height):
|
||||||
|
width(width),
|
||||||
|
height(height),
|
||||||
|
gridBW(width, height),
|
||||||
|
pixels(width* height)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
for (uint8_t y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
gridBW.pixels[y] = 0x0;
|
||||||
|
for (int8_t x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
*getPixel(x, y) = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void placePiece(Piece* piece, uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
for (uint8_t pieceY = 0; pieceY < piece->getRotation().height; pieceY++)
|
||||||
|
{
|
||||||
|
for (uint8_t pieceX = 0; pieceX < piece->getRotation().width; pieceX++)
|
||||||
|
{
|
||||||
|
if (piece->getPixel(pieceX, pieceY))
|
||||||
|
{
|
||||||
|
*getPixel(x + pieceX, y + pieceY) = piece->pieceData->colorIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void erasePiece(Piece* piece, uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
for (uint8_t pieceY = 0; pieceY < piece->getRotation().height; pieceY++)
|
||||||
|
{
|
||||||
|
for (uint8_t pieceX = 0; pieceX < piece->getRotation().width; pieceX++)
|
||||||
|
{
|
||||||
|
if (piece->getPixel(pieceX, pieceY))
|
||||||
|
{
|
||||||
|
*getPixel(x + pieceX, y + pieceY) = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanupFullLines()
|
||||||
|
{
|
||||||
|
uint8_t offset = 0;
|
||||||
|
//from "height - 1" to "0", so from bottom row to top
|
||||||
|
for (uint8_t y = height; y-- > 0; )
|
||||||
|
{
|
||||||
|
if (gridBW.isLineFull(y))
|
||||||
|
{
|
||||||
|
offset++;
|
||||||
|
for (uint8_t x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
pixels[y * width + x] = 0;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset > 0)
|
||||||
|
{
|
||||||
|
if (gridBW.pixels[y])
|
||||||
|
{
|
||||||
|
for (uint8_t x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
pixels[(y + offset) * width + x] = pixels[y * width + x];
|
||||||
|
pixels[y * width + x] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gridBW.cleanupFullLines();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* getPixel(uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
return &pixels[y * width + x];
|
||||||
|
}
|
||||||
|
|
||||||
|
void sync()
|
||||||
|
{
|
||||||
|
for (uint8_t y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
gridBW.pixels[y] = 0x0;
|
||||||
|
for (int8_t x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
gridBW.pixels[y] <<= 1;
|
||||||
|
if (*getPixel(x, y) != 0)
|
||||||
|
{
|
||||||
|
gridBW.pixels[y] |= 0x1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __GRIDCOLOR_H__ */
|
184
usermods/TetrisAI_v2/pieces.h
Normal file
184
usermods/TetrisAI_v2/pieces.h
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* @file : pieces.h
|
||||||
|
* @brief : contains the tetris pieces with their colors indecies
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* Copyright (c) muebau 2022
|
||||||
|
* All rights reserved.</center></h2>
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PIECES_H__
|
||||||
|
#define __PIECES_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <bitset>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define numPieces 7
|
||||||
|
|
||||||
|
struct PieceRotation
|
||||||
|
{
|
||||||
|
uint8_t width;
|
||||||
|
uint8_t height;
|
||||||
|
uint16_t rows;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PieceData
|
||||||
|
{
|
||||||
|
uint8_t rotCount;
|
||||||
|
uint8_t colorIndex;
|
||||||
|
PieceRotation rotations[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
PieceData piecesData[numPieces] = {
|
||||||
|
// I
|
||||||
|
{
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
{
|
||||||
|
{ 1, 4, 0b0001000100010001},
|
||||||
|
{ 4, 1, 0b0000000000001111}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// O
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
{ 2, 2, 0b0000000000110011}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Z
|
||||||
|
{
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
{
|
||||||
|
{ 3, 2, 0b0000000001100011},
|
||||||
|
{ 2, 3, 0b0000000100110010}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// S
|
||||||
|
{
|
||||||
|
2,
|
||||||
|
4,
|
||||||
|
{
|
||||||
|
{ 3, 2, 0b0000000000110110},
|
||||||
|
{ 2, 3, 0b0000001000110001}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// L
|
||||||
|
{
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
{
|
||||||
|
{ 2, 3, 0b0000001000100011},
|
||||||
|
{ 3, 2, 0b0000000001110100},
|
||||||
|
{ 2, 3, 0b0000001100010001},
|
||||||
|
{ 3, 2, 0b0000000000010111}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// J
|
||||||
|
{
|
||||||
|
4,
|
||||||
|
6,
|
||||||
|
{
|
||||||
|
{ 2, 3, 0b0000000100010011},
|
||||||
|
{ 3, 2, 0b0000000001000111},
|
||||||
|
{ 2, 3, 0b0000001100100010},
|
||||||
|
{ 3, 2, 0b0000000001110001}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// T
|
||||||
|
{
|
||||||
|
4,
|
||||||
|
7,
|
||||||
|
{
|
||||||
|
{ 3, 2, 0b0000000001110010},
|
||||||
|
{ 2, 3, 0b0000000100110001},
|
||||||
|
{ 3, 2, 0b0000000000100111},
|
||||||
|
{ 2, 3, 0b0000001000110010}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
class Piece
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
uint8_t x;
|
||||||
|
uint8_t y;
|
||||||
|
PieceData* pieceData;
|
||||||
|
uint8_t rotation;
|
||||||
|
uint8_t landingY;
|
||||||
|
|
||||||
|
Piece(uint8_t pieceIndex = 0):
|
||||||
|
x(0),
|
||||||
|
y(0),
|
||||||
|
rotation(0),
|
||||||
|
landingY(0)
|
||||||
|
{
|
||||||
|
this->pieceData = &piecesData[pieceIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
this->rotation = 0;
|
||||||
|
this->x = 0;
|
||||||
|
this->y = 0;
|
||||||
|
this->landingY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getGridRow(uint8_t x, uint8_t y, uint8_t width)
|
||||||
|
{
|
||||||
|
if (x < width)
|
||||||
|
{
|
||||||
|
//shift the row with the "top-left" position to the "x" position
|
||||||
|
auto shiftx = (width - 1) - x;
|
||||||
|
auto topleftx = (getRotation().width - 1);
|
||||||
|
|
||||||
|
auto finalShift = shiftx - topleftx;
|
||||||
|
auto row = getRow(y);
|
||||||
|
auto finalResult = row << finalShift;
|
||||||
|
|
||||||
|
return finalResult;
|
||||||
|
}
|
||||||
|
return 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getRow(uint8_t y)
|
||||||
|
{
|
||||||
|
if (y < 4)
|
||||||
|
{
|
||||||
|
return (getRotation().rows >> (12 - (4 * y))) & 0xf;
|
||||||
|
}
|
||||||
|
return 0xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getPixel(uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
if(x > getRotation().width - 1 || y > getRotation().height - 1 )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x < 4 && y < 4)
|
||||||
|
{
|
||||||
|
return (getRow((4 - getRotation().height) + y) >> (3 - ((4 - getRotation().width) + x))) & 0x1;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PieceRotation getRotation()
|
||||||
|
{
|
||||||
|
return this->pieceData->rotations[rotation];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __PIECES_H__ */
|
64
usermods/TetrisAI_v2/rating.h
Normal file
64
usermods/TetrisAI_v2/rating.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* @file : rating.h
|
||||||
|
* @brief : contains the tetris rating of a grid
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* Copyright (c) muebau 2022
|
||||||
|
* All rights reserved.</center></h2>
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RATING_H__
|
||||||
|
#define __RATING_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <vector>
|
||||||
|
#include "rating.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class Rating
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
uint8_t minHeight;
|
||||||
|
uint8_t maxHeight;
|
||||||
|
uint16_t holes;
|
||||||
|
uint8_t fullLines;
|
||||||
|
uint16_t bumpiness;
|
||||||
|
uint16_t aggregatedHeight;
|
||||||
|
double score;
|
||||||
|
uint8_t width;
|
||||||
|
std::vector<uint8_t> lineHights;
|
||||||
|
|
||||||
|
Rating(uint8_t width):
|
||||||
|
width(width),
|
||||||
|
lineHights(width)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
this->minHeight = 0;
|
||||||
|
this->maxHeight = 0;
|
||||||
|
|
||||||
|
for (uint8_t line = 0; line < this->width; line++)
|
||||||
|
{
|
||||||
|
this->lineHights[line] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->holes = 0;
|
||||||
|
this->fullLines = 0;
|
||||||
|
this->bumpiness = 0;
|
||||||
|
this->aggregatedHeight = 0;
|
||||||
|
this->score = -DBL_MAX;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __RATING_H__ */
|
33
usermods/TetrisAI_v2/readme.md
Normal file
33
usermods/TetrisAI_v2/readme.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Tetris AI effect usermod
|
||||||
|
|
||||||
|
This usermod brings you a effect brings a self playing Tetris game. The mod needs version 0.14 or above as it is based on matrix support. The effect was tested on an ESP32 with a WS2812B 16x16 matrix.
|
||||||
|
|
||||||
|
Version 1.0
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Just activate the usermod with `-D USERMOD_TETRISAI` and the effect will become available under the name 'Tetris AI'.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
It is best to set the background color to black, the border color to light grey and the game over color (foreground) to dark grey.
|
||||||
|
|
||||||
|
### Sliders and boxes
|
||||||
|
|
||||||
|
#### Sliders
|
||||||
|
|
||||||
|
* speed: speed the game plays
|
||||||
|
* look ahead: how many pieces is the AI allowed to know the next pieces (0 - 2)
|
||||||
|
* intelligence: how good the AI will play
|
||||||
|
* Rotate color: make the colors shift (rotate) every few cicles
|
||||||
|
* Mistakes free: how many good moves between mistakes (if activated)
|
||||||
|
|
||||||
|
#### Checkboxes
|
||||||
|
|
||||||
|
* show next: if true a space of 5 pixels from the right is used to show the next pieces. The whole segment is used for the grid otherwise.
|
||||||
|
* show border: if true an additional column of 1 pixel is used to draw a border between the grid and the next pieces
|
||||||
|
* mistakes: if true the worst instead of the best move is choosen every few moves (read above)
|
||||||
|
|
||||||
|
## Best results
|
||||||
|
|
||||||
|
If the speed is set to be a little bit faster than a good human could play with maximal intelligence and very few mistakes it makes people furious/happy at a party.
|
302
usermods/TetrisAI_v2/tetrisai.h
Normal file
302
usermods/TetrisAI_v2/tetrisai.h
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* @file : ai.h
|
||||||
|
* @brief : contains the heuristic
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* Copyright (c) muebau 2023
|
||||||
|
* All rights reserved.</center></h2>
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AI_H__
|
||||||
|
#define __AI_H__
|
||||||
|
|
||||||
|
#include "gridbw.h"
|
||||||
|
#include "rating.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class TetrisAI
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
double aHeight;
|
||||||
|
double fullLines;
|
||||||
|
double holes;
|
||||||
|
double bumpiness;
|
||||||
|
bool findWorstMove = false;
|
||||||
|
|
||||||
|
uint8_t countOnes(uint32_t vector)
|
||||||
|
{
|
||||||
|
uint8_t count = 0;
|
||||||
|
while (vector)
|
||||||
|
{
|
||||||
|
vector &= (vector - 1);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateRating(GridBW grid, Rating* rating)
|
||||||
|
{
|
||||||
|
rating->minHeight = 0;
|
||||||
|
rating->maxHeight = 0;
|
||||||
|
rating->holes = 0;
|
||||||
|
rating->fullLines = 0;
|
||||||
|
rating->bumpiness = 0;
|
||||||
|
rating->aggregatedHeight = 0;
|
||||||
|
fill(rating->lineHights.begin(), rating->lineHights.end(), 0);
|
||||||
|
|
||||||
|
uint32_t columnvector = 0x0;
|
||||||
|
uint32_t lastcolumnvector = 0x0;
|
||||||
|
for (uint8_t row = 0; row < grid.height; row++)
|
||||||
|
{
|
||||||
|
columnvector |= grid.pixels[row];
|
||||||
|
|
||||||
|
//first (highest) column makes it
|
||||||
|
if (rating->maxHeight == 0 && columnvector)
|
||||||
|
{
|
||||||
|
rating->maxHeight = grid.height - row;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if column vector is full we found the minimal height (or it stays zero)
|
||||||
|
if (rating->minHeight == 0 && (columnvector == (uint32_t)((1 << grid.width) - 1)))
|
||||||
|
{
|
||||||
|
rating->minHeight = grid.height - row;
|
||||||
|
}
|
||||||
|
|
||||||
|
//line full if all ones in mask :-)
|
||||||
|
if (grid.isLineFull(row))
|
||||||
|
{
|
||||||
|
rating->fullLines++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//holes are basically a XOR with the "full" columns
|
||||||
|
rating->holes += countOnes(columnvector ^ grid.pixels[row]);
|
||||||
|
|
||||||
|
//calculate the difference (XOR) between the current column vector and the last one
|
||||||
|
uint32_t columnDelta = columnvector ^ lastcolumnvector;
|
||||||
|
|
||||||
|
//process every new column
|
||||||
|
uint8_t index = 0;
|
||||||
|
while (columnDelta)
|
||||||
|
{
|
||||||
|
//if this is a new column
|
||||||
|
if (columnDelta & 0x1)
|
||||||
|
{
|
||||||
|
//update hight of this column
|
||||||
|
rating->lineHights[(grid.width - 1) - index] = grid.height - row;
|
||||||
|
|
||||||
|
// update aggregatedHeight
|
||||||
|
rating->aggregatedHeight += grid.height - row;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
columnDelta >>= 1;
|
||||||
|
}
|
||||||
|
lastcolumnvector = columnvector;
|
||||||
|
}
|
||||||
|
|
||||||
|
//compare every two columns to get the difference and add them up
|
||||||
|
for (uint8_t column = 1; column < grid.width; column++)
|
||||||
|
{
|
||||||
|
rating->bumpiness += abs(rating->lineHights[column - 1] - rating->lineHights[column]);
|
||||||
|
}
|
||||||
|
|
||||||
|
rating->score = (aHeight * (rating->aggregatedHeight)) + (fullLines * (rating->fullLines)) + (holes * (rating->holes)) + (bumpiness * (rating->bumpiness));
|
||||||
|
}
|
||||||
|
|
||||||
|
TetrisAI(): TetrisAI(-0.510066, 0.760666, -0.35663, -0.184483)
|
||||||
|
{}
|
||||||
|
|
||||||
|
TetrisAI(double aHeight, double fullLines, double holes, double bumpiness):
|
||||||
|
aHeight(aHeight),
|
||||||
|
fullLines(fullLines),
|
||||||
|
holes(holes),
|
||||||
|
bumpiness(bumpiness)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void findBestMove(GridBW grid, Piece *piece)
|
||||||
|
{
|
||||||
|
vector<Piece> pieces = {*piece};
|
||||||
|
findBestMove(grid, &pieces);
|
||||||
|
*piece = pieces[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void findBestMove(GridBW grid, std::vector<Piece> *pieces)
|
||||||
|
{
|
||||||
|
findBestMove(grid, pieces->begin(), pieces->end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void findBestMove(GridBW grid, std::vector<Piece>::iterator start, std::vector<Piece>::iterator end)
|
||||||
|
{
|
||||||
|
Rating bestRating(grid.width);
|
||||||
|
findBestMove(grid, start, end, &bestRating);
|
||||||
|
}
|
||||||
|
|
||||||
|
void findBestMove(GridBW grid, std::vector<Piece>::iterator start, std::vector<Piece>::iterator end, Rating* bestRating)
|
||||||
|
{
|
||||||
|
grid.cleanupFullLines();
|
||||||
|
Rating curRating(grid.width);
|
||||||
|
Rating deeperRating(grid.width);
|
||||||
|
Piece piece = *start;
|
||||||
|
|
||||||
|
// for every rotation of the piece
|
||||||
|
for (piece.rotation = 0; piece.rotation < piece.pieceData->rotCount; piece.rotation++)
|
||||||
|
{
|
||||||
|
// put piece to top left corner
|
||||||
|
piece.x = 0;
|
||||||
|
piece.y = 0;
|
||||||
|
|
||||||
|
//test for every column
|
||||||
|
for (piece.x = 0; piece.x <= grid.width - piece.getRotation().width; piece.x++)
|
||||||
|
{
|
||||||
|
//todo optimise by the use of the previous grids height
|
||||||
|
piece.landingY = 0;
|
||||||
|
//will set landingY to final position
|
||||||
|
grid.findLandingPosition(&piece);
|
||||||
|
|
||||||
|
// draw piece
|
||||||
|
grid.placePiece(&piece, piece.x, piece.landingY);
|
||||||
|
|
||||||
|
if(start == end - 1)
|
||||||
|
{
|
||||||
|
//at the deepest level
|
||||||
|
updateRating(grid, &curRating);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//go deeper to take another piece into account
|
||||||
|
findBestMove(grid, start + 1, end, &deeperRating);
|
||||||
|
curRating = deeperRating;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eraese piece
|
||||||
|
grid.erasePiece(&piece, piece.x, piece.landingY);
|
||||||
|
|
||||||
|
if(findWorstMove)
|
||||||
|
{
|
||||||
|
//init rating for worst
|
||||||
|
if(bestRating->score == -DBL_MAX)
|
||||||
|
{
|
||||||
|
bestRating->score = DBL_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update if we found a worse one
|
||||||
|
if (bestRating->score > curRating.score)
|
||||||
|
{
|
||||||
|
*bestRating = curRating;
|
||||||
|
(*start) = piece;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// update if we found a better one
|
||||||
|
if (bestRating->score < curRating.score)
|
||||||
|
{
|
||||||
|
*bestRating = curRating;
|
||||||
|
(*start) = piece;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool findBestMoveNonBlocking(GridBW grid, std::vector<Piece>::iterator start, std::vector<Piece>::iterator end, Rating* bestRating)
|
||||||
|
{
|
||||||
|
//vector with pieces
|
||||||
|
//for every piece
|
||||||
|
//for every
|
||||||
|
switch (expression)
|
||||||
|
{
|
||||||
|
case INIT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool findBestMoveNonBlocking(GridBW grid, std::vector<Piece>::iterator start, std::vector<Piece>::iterator end, Rating* bestRating)
|
||||||
|
{
|
||||||
|
//INIT
|
||||||
|
grid.cleanupFullLines();
|
||||||
|
Rating curRating(grid.width);
|
||||||
|
Rating deeperRating(grid.width);
|
||||||
|
Piece piece = *start;
|
||||||
|
|
||||||
|
// for every rotation of the piece
|
||||||
|
piece.rotation = 0;
|
||||||
|
|
||||||
|
//HANDLE
|
||||||
|
while (piece.rotation < piece.pieceData->rotCount)
|
||||||
|
{
|
||||||
|
// put piece to top left corner
|
||||||
|
piece.x = 0;
|
||||||
|
piece.y = 0;
|
||||||
|
|
||||||
|
//test for every column
|
||||||
|
piece.x = 0;
|
||||||
|
while (piece.x <= grid.width - piece.getRotation().width)
|
||||||
|
{
|
||||||
|
|
||||||
|
//todo optimise by the use of the previous grids height
|
||||||
|
piece.landingY = 0;
|
||||||
|
//will set landingY to final position
|
||||||
|
grid.findLandingPosition(&piece);
|
||||||
|
|
||||||
|
// draw piece
|
||||||
|
grid.placePiece(&piece, piece.x, piece.landingY);
|
||||||
|
|
||||||
|
if(start == end - 1)
|
||||||
|
{
|
||||||
|
//at the deepest level
|
||||||
|
updateRating(grid, &curRating);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//go deeper to take another piece into account
|
||||||
|
findBestMove(grid, start + 1, end, &deeperRating);
|
||||||
|
curRating = deeperRating;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eraese piece
|
||||||
|
grid.erasePiece(&piece, piece.x, piece.landingY);
|
||||||
|
|
||||||
|
if(findWorstMove)
|
||||||
|
{
|
||||||
|
//init rating for worst
|
||||||
|
if(bestRating->score == -DBL_MAX)
|
||||||
|
{
|
||||||
|
bestRating->score = DBL_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update if we found a worse one
|
||||||
|
if (bestRating->score > curRating.score)
|
||||||
|
{
|
||||||
|
*bestRating = curRating;
|
||||||
|
(*start) = piece;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// update if we found a better one
|
||||||
|
if (bestRating->score < curRating.score)
|
||||||
|
{
|
||||||
|
*bestRating = curRating;
|
||||||
|
(*start) = piece;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
piece.x++;
|
||||||
|
}
|
||||||
|
piece.rotation++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//EXIT
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __AI_H__ */
|
150
usermods/TetrisAI_v2/tetrisaigame.h
Normal file
150
usermods/TetrisAI_v2/tetrisaigame.h
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* @file : tetrisaigame.h
|
||||||
|
* @brief : main tetris functions
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* Copyright (c) muebau 2022
|
||||||
|
* All rights reserved.</center></h2>
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TETRISAIGAME_H__
|
||||||
|
#define __TETRISAIGAME_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <vector>
|
||||||
|
#include "pieces.h"
|
||||||
|
#include "gridcolor.h"
|
||||||
|
#include "tetrisbag.h"
|
||||||
|
#include "tetrisai.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class TetrisAIGame
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool animateFallOfPiece(Piece* piece, bool skip)
|
||||||
|
{
|
||||||
|
if (skip || piece->y >= piece->landingY)
|
||||||
|
{
|
||||||
|
piece->y = piece->landingY;
|
||||||
|
grid.gridBW.placePiece(piece, piece->x, piece->landingY);
|
||||||
|
grid.placePiece(piece, piece->x, piece->y);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// eraese last drawing
|
||||||
|
grid.erasePiece(piece, piece->x, piece->y);
|
||||||
|
|
||||||
|
//move piece down
|
||||||
|
piece->y++;
|
||||||
|
|
||||||
|
// draw piece
|
||||||
|
grid.placePiece(piece, piece->x, piece->y);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint8_t width;
|
||||||
|
uint8_t height;
|
||||||
|
uint8_t nLookAhead;
|
||||||
|
TetrisBag bag;
|
||||||
|
GridColor grid;
|
||||||
|
TetrisAI ai;
|
||||||
|
Piece curPiece;
|
||||||
|
PieceData* piecesData;
|
||||||
|
enum States { INIT, TEST_GAME_OVER, GET_NEXT_PIECE, FIND_BEST_MOVE, ANIMATE_MOVE, ANIMATE_GAME_OVER } state = INIT;
|
||||||
|
|
||||||
|
TetrisAIGame(uint8_t width, uint8_t height, uint8_t nLookAhead, PieceData* piecesData, uint8_t nPieces):
|
||||||
|
width(width),
|
||||||
|
height(height),
|
||||||
|
nLookAhead(nLookAhead),
|
||||||
|
bag(nPieces, 1, nLookAhead),
|
||||||
|
grid(width, height + 4),
|
||||||
|
ai(),
|
||||||
|
piecesData(piecesData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void nextPiece()
|
||||||
|
{
|
||||||
|
grid.cleanupFullLines();
|
||||||
|
bag.queuePiece();
|
||||||
|
}
|
||||||
|
|
||||||
|
void findBestMove()
|
||||||
|
{
|
||||||
|
ai.findBestMove(grid.gridBW, &bag.piecesQueue);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool animateFall(bool skip)
|
||||||
|
{
|
||||||
|
return animateFallOfPiece(&(bag.piecesQueue[0]), skip);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isGameOver()
|
||||||
|
{
|
||||||
|
//if there is something in the 4 lines of the hidden area the game is over
|
||||||
|
return grid.gridBW.pixels[0] || grid.gridBW.pixels[1] || grid.gridBW.pixels[2] || grid.gridBW.pixels[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
void poll()
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case INIT:
|
||||||
|
reset();
|
||||||
|
state = TEST_GAME_OVER;
|
||||||
|
break;
|
||||||
|
case TEST_GAME_OVER:
|
||||||
|
if (isGameOver())
|
||||||
|
{
|
||||||
|
state = ANIMATE_GAME_OVER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = GET_NEXT_PIECE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GET_NEXT_PIECE:
|
||||||
|
nextPiece();
|
||||||
|
state = FIND_BEST_MOVE;
|
||||||
|
break;
|
||||||
|
case FIND_BEST_MOVE:
|
||||||
|
findBestMove();
|
||||||
|
state = ANIMATE_MOVE;
|
||||||
|
break;
|
||||||
|
case ANIMATE_MOVE:
|
||||||
|
if (!animateFall(false))
|
||||||
|
{
|
||||||
|
state = TEST_GAME_OVER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ANIMATE_GAME_OVER:
|
||||||
|
static auto curPixel = grid.pixels.size();
|
||||||
|
grid.pixels[curPixel] = 254;
|
||||||
|
|
||||||
|
if (curPixel == 0)
|
||||||
|
{
|
||||||
|
state = INIT;
|
||||||
|
curPixel = grid.pixels.size();
|
||||||
|
}
|
||||||
|
curPixel--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
grid.clear();
|
||||||
|
bag.init();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __TETRISAIGAME_H__ */
|
100
usermods/TetrisAI_v2/tetrisbag.h
Normal file
100
usermods/TetrisAI_v2/tetrisbag.h
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* @file : tetrisbag.h
|
||||||
|
* @brief : the tetris implementation of a random piece generator
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* Copyright (c) muebau 2022
|
||||||
|
* All rights reserved.</center></h2>
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TETRISBAG_H__
|
||||||
|
#define __TETRISBAG_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "tetrisbag.h"
|
||||||
|
|
||||||
|
class TetrisBag
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
uint8_t nPieces;
|
||||||
|
uint8_t nBagLength;
|
||||||
|
uint8_t bagIdx;
|
||||||
|
std::vector<uint8_t> bag;
|
||||||
|
std::vector<Piece> piecesQueue;
|
||||||
|
|
||||||
|
TetrisBag(uint8_t nPieces, uint8_t nBagLength, uint8_t queueLength):
|
||||||
|
nPieces(nPieces),
|
||||||
|
nBagLength(nBagLength),
|
||||||
|
bag(nPieces * nBagLength),
|
||||||
|
piecesQueue(queueLength)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
//will shuffle the bag at first use
|
||||||
|
bagIdx = nPieces - 1;
|
||||||
|
|
||||||
|
for (uint8_t bagIndex = 0; bagIndex < nPieces * nBagLength; bagIndex++)
|
||||||
|
{
|
||||||
|
bag[bagIndex] = bagIndex % nPieces;
|
||||||
|
}
|
||||||
|
|
||||||
|
//will init the queue
|
||||||
|
for (uint8_t index = 0; index < piecesQueue.size(); index++)
|
||||||
|
{
|
||||||
|
queuePiece();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shuffleBag()
|
||||||
|
{
|
||||||
|
uint8_t temp;
|
||||||
|
uint8_t swapIdx;
|
||||||
|
for (int index = nPieces - 1; index > 0; index--)
|
||||||
|
{
|
||||||
|
//get candidate to swap
|
||||||
|
swapIdx = rand() % index;
|
||||||
|
|
||||||
|
//swap it!
|
||||||
|
temp = bag[swapIdx];
|
||||||
|
bag[swapIdx] = bag[index];
|
||||||
|
bag[index] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Piece getNextPiece()
|
||||||
|
{
|
||||||
|
bagIdx++;
|
||||||
|
if (bagIdx >= nPieces)
|
||||||
|
{
|
||||||
|
shuffleBag();
|
||||||
|
bagIdx = 0;
|
||||||
|
}
|
||||||
|
return Piece(bag[bagIdx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void queuePiece()
|
||||||
|
{
|
||||||
|
//move vector to left
|
||||||
|
std::rotate(piecesQueue.begin(), piecesQueue.begin() + 1, piecesQueue.end());
|
||||||
|
piecesQueue[piecesQueue.size() - 1] = getNextPiece();
|
||||||
|
}
|
||||||
|
|
||||||
|
void queuePiece(uint8_t idx)
|
||||||
|
{
|
||||||
|
//move vector to left
|
||||||
|
std::rotate(piecesQueue.begin(), piecesQueue.begin() + 1, piecesQueue.end());
|
||||||
|
piecesQueue[piecesQueue.size() - 1] = Piece(idx % nPieces);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __TETRISBAG_H__ */
|
222
usermods/TetrisAI_v2/usermod_v2_tetrisai.h
Normal file
222
usermods/TetrisAI_v2/usermod_v2_tetrisai.h
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wled.h"
|
||||||
|
#include "FX.h"
|
||||||
|
#include "fcn_declare.h"
|
||||||
|
|
||||||
|
#include "tetrisaigame.h"
|
||||||
|
// By: muebau
|
||||||
|
|
||||||
|
typedef struct TetrisAI_data
|
||||||
|
{
|
||||||
|
unsigned long lastTime = 0;
|
||||||
|
TetrisAIGame tetris;
|
||||||
|
uint8_t intelligence;
|
||||||
|
uint8_t rotate;
|
||||||
|
bool showNext;
|
||||||
|
bool showBorder;
|
||||||
|
uint8_t colorOffset;
|
||||||
|
uint8_t colorInc;
|
||||||
|
uint8_t mistaceCountdown;
|
||||||
|
} tetrisai_data;
|
||||||
|
|
||||||
|
void drawGrid(TetrisAIGame* tetris, TetrisAI_data* tetrisai_data)
|
||||||
|
{
|
||||||
|
SEGMENT.fill(SEGCOLOR(1));
|
||||||
|
|
||||||
|
//GRID
|
||||||
|
for (auto index_y = 4; index_y < tetris->grid.height; index_y++)
|
||||||
|
{
|
||||||
|
for (auto index_x = 0; index_x < tetris->grid.width; index_x++)
|
||||||
|
{
|
||||||
|
CRGB color;
|
||||||
|
if (*tetris->grid.getPixel(index_x, index_y) == 0)
|
||||||
|
{
|
||||||
|
//BG color
|
||||||
|
color = SEGCOLOR(1);
|
||||||
|
}
|
||||||
|
//game over animation
|
||||||
|
else if(*tetris->grid.getPixel(index_x, index_y) == 254)
|
||||||
|
{
|
||||||
|
//use fg
|
||||||
|
color = SEGCOLOR(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//spread the color over the whole palette
|
||||||
|
uint8_t colorIndex = *tetris->grid.getPixel(index_x, index_y) * 32;
|
||||||
|
colorIndex += tetrisai_data->colorOffset;
|
||||||
|
color = ColorFromPalette(SEGPALETTE, colorIndex, 255, NOBLEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
SEGMENT.setPixelColorXY(index_x, index_y - 4, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tetrisai_data->colorOffset += tetrisai_data->colorInc;
|
||||||
|
|
||||||
|
//NEXT PIECE AREA
|
||||||
|
if (tetrisai_data->showNext)
|
||||||
|
{
|
||||||
|
//BORDER
|
||||||
|
if (tetrisai_data->showBorder)
|
||||||
|
{
|
||||||
|
//draw a line 6 pixels from right with the border color
|
||||||
|
for (auto index_y = 0; index_y < SEGMENT.virtualHeight(); index_y++)
|
||||||
|
{
|
||||||
|
SEGMENT.setPixelColorXY(SEGMENT.virtualWidth() - 6, index_y, SEGCOLOR(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//NEXT PIECE
|
||||||
|
int piecesOffsetX = SEGMENT.virtualWidth() - 4;
|
||||||
|
int piecesOffsetY = 1;
|
||||||
|
for (uint8_t nextPieceIdx = 1; nextPieceIdx < tetris->nLookAhead; nextPieceIdx++)
|
||||||
|
{
|
||||||
|
uint8_t pieceNbrOffsetY = (nextPieceIdx - 1) * 5;
|
||||||
|
|
||||||
|
Piece piece(tetris->bag.piecesQueue[nextPieceIdx]);
|
||||||
|
|
||||||
|
for (uint8_t pieceY = 0; pieceY < piece.getRotation().height; pieceY++)
|
||||||
|
{
|
||||||
|
for (uint8_t pieceX = 0; pieceX < piece.getRotation().width; pieceX++)
|
||||||
|
{
|
||||||
|
if (piece.getPixel(pieceX, pieceY))
|
||||||
|
{
|
||||||
|
uint8_t colIdx = ((piece.pieceData->colorIndex * 32) + tetrisai_data->colorOffset);
|
||||||
|
SEGMENT.setPixelColorXY(piecesOffsetX + pieceX, piecesOffsetY + pieceNbrOffsetY + pieceY, ColorFromPalette(SEGPALETTE, colIdx, 255, NOBLEND));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
// 2D Tetris AI //
|
||||||
|
////////////////////////////
|
||||||
|
uint16_t mode_2DTetrisAI()
|
||||||
|
{
|
||||||
|
if (!strip.isMatrix || !SEGENV.allocateData(sizeof(tetrisai_data)))
|
||||||
|
{
|
||||||
|
// not a 2D set-up
|
||||||
|
SEGMENT.fill(SEGCOLOR(0));
|
||||||
|
return 350;
|
||||||
|
}
|
||||||
|
TetrisAI_data* tetrisai_data = reinterpret_cast<TetrisAI_data*>(SEGENV.data);
|
||||||
|
|
||||||
|
const uint16_t cols = SEGMENT.virtualWidth();
|
||||||
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
|
//range 0 - 1024ms => 1024/255 ~ 4
|
||||||
|
uint16_t msDelayMove = 1024 - (4 * SEGMENT.speed);
|
||||||
|
int16_t msDelayGameOver = msDelayMove / 4;
|
||||||
|
|
||||||
|
//range 0 - 2 (not including current)
|
||||||
|
uint8_t nLookAhead = SEGMENT.intensity ? (SEGMENT.intensity >> 7) + 2 : 1;
|
||||||
|
//range 0 - 16
|
||||||
|
tetrisai_data->colorInc = SEGMENT.custom2 >> 4;
|
||||||
|
|
||||||
|
if (!tetrisai_data->tetris || (tetrisai_data->tetris.nLookAhead != nLookAhead
|
||||||
|
|| tetrisai_data->showNext != SEGMENT.check1
|
||||||
|
|| tetrisai_data->showBorder != SEGMENT.check2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
tetrisai_data->showNext = SEGMENT.check1;
|
||||||
|
tetrisai_data->showBorder = SEGMENT.check2;
|
||||||
|
|
||||||
|
//not more than 32 as this is the limit of this implementation
|
||||||
|
uint8_t gridWidth = cols < 32 ? cols : 32;
|
||||||
|
uint8_t gridHeight = rows;
|
||||||
|
|
||||||
|
// do we need space for the 'next' section?
|
||||||
|
if (tetrisai_data->showNext)
|
||||||
|
{
|
||||||
|
// make space for the piece and one pixel of space
|
||||||
|
gridWidth = gridWidth - 5;
|
||||||
|
|
||||||
|
// do we need space for a border?
|
||||||
|
if (tetrisai_data->showBorder)
|
||||||
|
{
|
||||||
|
gridWidth = gridWidth - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tetrisai_data->tetris = TetrisAIGame(gridWidth, gridHeight, nLookAhead, piecesData, numPieces);
|
||||||
|
SEGMENT.fill(SEGCOLOR(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tetrisai_data->intelligence != SEGMENT.custom1)
|
||||||
|
{
|
||||||
|
tetrisai_data->intelligence = SEGMENT.custom1;
|
||||||
|
double dui = 0.2 - (0.2 * (tetrisai_data->intelligence / 255.0));
|
||||||
|
|
||||||
|
tetrisai_data->tetris.ai.aHeight = -0.510066 + dui;
|
||||||
|
tetrisai_data->tetris.ai.fullLines = 0.760666 - dui;
|
||||||
|
tetrisai_data->tetris.ai.holes = -0.35663 + dui;
|
||||||
|
tetrisai_data->tetris.ai.bumpiness = -0.184483 + dui;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tetrisai_data->tetris.state == TetrisAIGame::ANIMATE_MOVE)
|
||||||
|
{
|
||||||
|
if (millis() - tetrisai_data->lastTime > msDelayMove)
|
||||||
|
{
|
||||||
|
drawGrid(&tetrisai_data->tetris, tetrisai_data);
|
||||||
|
tetrisai_data->lastTime = millis();
|
||||||
|
tetrisai_data->tetris.poll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tetrisai_data->tetris.state == TetrisAIGame::ANIMATE_GAME_OVER)
|
||||||
|
{
|
||||||
|
if (millis() - tetrisai_data->lastTime > msDelayGameOver)
|
||||||
|
{
|
||||||
|
drawGrid(&tetrisai_data->tetris, tetrisai_data);
|
||||||
|
tetrisai_data->lastTime = millis();
|
||||||
|
tetrisai_data->tetris.poll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tetrisai_data->tetris.state == TetrisAIGame::FIND_BEST_MOVE)
|
||||||
|
{
|
||||||
|
if (SEGMENT.check3)
|
||||||
|
{
|
||||||
|
if(tetrisai_data->mistaceCountdown == 0)
|
||||||
|
{
|
||||||
|
tetrisai_data->tetris.ai.findWorstMove = true;
|
||||||
|
tetrisai_data->tetris.poll();
|
||||||
|
tetrisai_data->tetris.ai.findWorstMove = false;
|
||||||
|
tetrisai_data->mistaceCountdown = SEGMENT.custom3;
|
||||||
|
}
|
||||||
|
tetrisai_data->mistaceCountdown--;
|
||||||
|
}
|
||||||
|
tetrisai_data->tetris.poll();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tetrisai_data->tetris.poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
return FRAMETIME;
|
||||||
|
} // mode_2DTetrisAI()
|
||||||
|
static const char _data_FX_MODE_2DTETRISAI[] PROGMEM = "Tetris AI@!,Look ahead,Intelligence,Rotate color,Mistake free,Show next,Border,Mistakes;Game Over,!,Border;!;2;sx=127,ix=64,c1=255,c2=0,c3=31,o1=1,o2=1,o3=0,pal=11";
|
||||||
|
|
||||||
|
class TetrisAIUsermod : public Usermod
|
||||||
|
{
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
strip.addEffect(255, &mode_2DTetrisAI, _data_FX_MODE_2DTETRISAI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getId()
|
||||||
|
{
|
||||||
|
return USERMOD_ID_TETRISAI;
|
||||||
|
}
|
||||||
|
};
|
@ -1,4 +1,4 @@
|
|||||||
# I2C 4 Line Display Usermod ALT
|
# I2C/SPI 4 Line Display Usermod ALT
|
||||||
|
|
||||||
Thank you to the authors of the original version of these usermods. It would not have been possible without them!
|
Thank you to the authors of the original version of these usermods. It would not have been possible without them!
|
||||||
"usermod_v2_four_line_display"
|
"usermod_v2_four_line_display"
|
||||||
@ -8,21 +8,20 @@ The core of these usermods are a copy of the originals. The main changes are to
|
|||||||
The display usermod UI has been completely changed.
|
The display usermod UI has been completely changed.
|
||||||
|
|
||||||
|
|
||||||
The changes made to the RotaryEncoder usermod were made to support the new UI in the display usermod.
|
The changes made to the RotaryEncoder usermod were made to support the new UI in the display usermod.
|
||||||
Without the display it, functions identical to the original.
|
Without the display, it functions identical to the original.
|
||||||
The original "usermod_v2_auto_save" will not work with the display just yet.
|
The original "usermod_v2_auto_save" will not work with the display just yet.
|
||||||
|
|
||||||
Press the encoder to cycle through the options:
|
Press the encoder to cycle through the options:
|
||||||
*Brightness
|
* Brightness
|
||||||
*Speed
|
* Speed
|
||||||
*Intensity
|
* Intensity
|
||||||
*Palette
|
* Palette
|
||||||
*Effect
|
* Effect
|
||||||
*Main Color (only if display is used)
|
* Main Color (only if display is used)
|
||||||
*Saturation (only if display is used)
|
* Saturation (only if display is used)
|
||||||
|
|
||||||
Press and hold the encoder to display Network Info
|
Press and hold the encoder to display Network Info. If AP is active, it will display AP, SSID and password
|
||||||
if AP is active, it will display AP, SSID and password
|
|
||||||
|
|
||||||
Also shows if the timer is enabled
|
Also shows if the timer is enabled
|
||||||
|
|
||||||
@ -30,11 +29,47 @@ Also shows if the timer is enabled
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Please refer to the original `usermod_v2_rotary_encoder_ui` readme for the main instructions
|
Please refer to the original `usermod_v2_rotary_encoder_ui` readme for the main instructions.
|
||||||
Then to activate this alternative usermod add `#define USE_ALT_DISPlAY` to the `usermods_list.cpp` file,
|
|
||||||
|
Copy the example `platformio_override.sample.ini` from the usermod_v2_rotary_encoder_ui_ALT folder to the root directory of your particular build and rename it to `platformio_override.ini`.
|
||||||
|
|
||||||
|
This file should be placed in the same directory as `platformio.ini`.
|
||||||
|
|
||||||
|
Then, to activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE SENSITIVE) to the `usermods_list.cpp` file,
|
||||||
or add `-D USE_ALT_DISPlAY` to the original `platformio_override.ini.sample` file
|
or add `-D USE_ALT_DISPlAY` to the original `platformio_override.ini.sample` file
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
These options are configurable in Config > Usermods
|
||||||
|
|
||||||
|
### Usermod Setup
|
||||||
|
|
||||||
|
* Global I2C GPIOs (HW) - Set the SDA and SCL pins
|
||||||
|
|
||||||
|
### 4LineDisplay
|
||||||
|
|
||||||
|
* `enabled` - enable/disable usermod
|
||||||
|
* `type` - display type in numeric format
|
||||||
|
* 1 = I2C SSD1306 128x32
|
||||||
|
* 2 = I2C SH1106 128x32
|
||||||
|
* 3 = I2C SSD1306 128x64 (4 double-height lines)
|
||||||
|
* 4 = I2C SSD1305 128x32
|
||||||
|
* 5 = I2C SSD1305 128x64 (4 double-height lines)
|
||||||
|
* 6 = SPI SSD1306 128x32
|
||||||
|
* 7 = SPI SSD1306 128x64 (4 double-height lines)
|
||||||
|
* 8 = SPI SSD1309 128x64 (4 double-height lines)
|
||||||
|
* 9 = I2C SSD1309 128x64 (4 double-height lines)
|
||||||
|
* `pin` - GPIO pins used for display; SPI displays can use SCK, MOSI, CS, DC & RST
|
||||||
|
* `flip` - flip/rotate display 180°
|
||||||
|
* `contrast` - set display contrast (higher contrast may reduce display lifetime)
|
||||||
|
* `screenTimeOutSec` - screen saver time-out in seconds
|
||||||
|
* `sleepMode` - enable/disable screen saver
|
||||||
|
* `clockMode` - enable/disable clock display in screen saver mode
|
||||||
|
* `showSeconds` - Show seconds on the clock display
|
||||||
|
* `i2c-freq-kHz` - I2C clock frequency in kHz (may help reduce dropped frames, range: 400-3400)
|
||||||
|
|
||||||
|
|
||||||
### PlatformIO requirements
|
### PlatformIO requirements
|
||||||
|
|
||||||
Note: the Four Line Display usermod requires the libraries `U8g2` and `Wire`.
|
Note: the Four Line Display usermod requires the libraries `U8g2` and `Wire`.
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
// for WLED.
|
// for WLED.
|
||||||
//
|
//
|
||||||
// Dependencies
|
// Dependencies
|
||||||
// * This Usermod works best, by far, when coupled
|
// * This Usermod works best, by far, when coupled
|
||||||
// with RotaryEncoderUI ALT Usermod.
|
// with RotaryEncoderUI ALT Usermod.
|
||||||
//
|
//
|
||||||
// Make sure to enable NTP and set your time zone in WLED Config | Time.
|
// Make sure to enable NTP and set your time zone in WLED Config | Time.
|
||||||
@ -89,7 +89,8 @@ typedef enum {
|
|||||||
SSD1305_64, // U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C
|
SSD1305_64, // U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C
|
||||||
SSD1306_SPI, // U8X8_SSD1306_128X32_NONAME_HW_SPI
|
SSD1306_SPI, // U8X8_SSD1306_128X32_NONAME_HW_SPI
|
||||||
SSD1306_SPI64, // U8X8_SSD1306_128X64_NONAME_HW_SPI
|
SSD1306_SPI64, // U8X8_SSD1306_128X64_NONAME_HW_SPI
|
||||||
SSD1309_SPI64 // U8X8_SSD1309_128X64_NONAME0_4W_HW_SPI
|
SSD1309_SPI64, // U8X8_SSD1309_128X64_NONAME0_4W_HW_SPI
|
||||||
|
SSD1309_64 // U8X8_SSD1309_128X64_NONAME0_HW_I2C
|
||||||
} DisplayType;
|
} DisplayType;
|
||||||
|
|
||||||
|
|
||||||
@ -235,7 +236,7 @@ class FourLineDisplayUsermod : public Usermod {
|
|||||||
void updateSpeed();
|
void updateSpeed();
|
||||||
void updateIntensity();
|
void updateIntensity();
|
||||||
void drawStatusIcons();
|
void drawStatusIcons();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* marks the position of the arrow showing
|
* marks the position of the arrow showing
|
||||||
* the current setting being changed
|
* the current setting being changed
|
||||||
@ -246,8 +247,8 @@ class FourLineDisplayUsermod : public Usermod {
|
|||||||
//Draw the arrow for the current setting being changed
|
//Draw the arrow for the current setting being changed
|
||||||
void drawArrow();
|
void drawArrow();
|
||||||
|
|
||||||
//Display the current effect or palette (desiredEntry)
|
//Display the current effect or palette (desiredEntry)
|
||||||
// on the appropriate line (row).
|
// on the appropriate line (row).
|
||||||
void showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row);
|
void showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -314,14 +315,14 @@ class FourLineDisplayUsermod : public Usermod {
|
|||||||
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
|
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
|
||||||
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
||||||
* If you want to force saving the current state, use serializeConfig() in your loop().
|
* If you want to force saving the current state, use serializeConfig() in your loop().
|
||||||
*
|
*
|
||||||
* CAUTION: serializeConfig() will initiate a filesystem write operation.
|
* CAUTION: serializeConfig() will initiate a filesystem write operation.
|
||||||
* It might cause the LEDs to stutter and will cause flash wear if called too often.
|
* It might cause the LEDs to stutter and will cause flash wear if called too often.
|
||||||
* Use it sparingly and always in the loop, never in network callbacks!
|
* Use it sparingly and always in the loop, never in network callbacks!
|
||||||
*
|
*
|
||||||
* addToConfig() will also not yet add your setting to one of the settings pages automatically.
|
* addToConfig() will also not yet add your setting to one of the settings pages automatically.
|
||||||
* To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually.
|
* To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually.
|
||||||
*
|
*
|
||||||
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
||||||
*/
|
*/
|
||||||
void addToConfig(JsonObject& root) override;
|
void addToConfig(JsonObject& root) override;
|
||||||
@ -329,7 +330,7 @@ class FourLineDisplayUsermod : public Usermod {
|
|||||||
/*
|
/*
|
||||||
* readFromConfig() can be used to read back the custom settings you added with addToConfig().
|
* readFromConfig() can be used to read back the custom settings you added with addToConfig().
|
||||||
* This is called by WLED when settings are loaded (currently this only happens once immediately after boot)
|
* This is called by WLED when settings are loaded (currently this only happens once immediately after boot)
|
||||||
*
|
*
|
||||||
* readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes),
|
* readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes),
|
||||||
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
|
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
|
||||||
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
|
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
|
||||||
@ -494,7 +495,7 @@ void FourLineDisplayUsermod::showTime() {
|
|||||||
}
|
}
|
||||||
if (knownHour != hourCurrent) {
|
if (knownHour != hourCurrent) {
|
||||||
// only update date when hour changes
|
// only update date when hour changes
|
||||||
sprintf_P(lineBuffer, PSTR("%s %2d "), monthShortStr(month(localTime)), day(localTime));
|
sprintf_P(lineBuffer, PSTR("%s %2d "), monthShortStr(month(localTime)), day(localTime));
|
||||||
draw2x2String(2, lineHeight==1 ? 0 : lineHeight, lineBuffer); // adjust for 8 line displays, draw month and day
|
draw2x2String(2, lineHeight==1 ? 0 : lineHeight, lineBuffer); // adjust for 8 line displays, draw month and day
|
||||||
}
|
}
|
||||||
sprintf_P(lineBuffer,PSTR("%2d:%02d"), (useAMPM ? AmPmHour : hourCurrent), minuteCurrent);
|
sprintf_P(lineBuffer,PSTR("%2d:%02d"), (useAMPM ? AmPmHour : hourCurrent), minuteCurrent);
|
||||||
@ -556,6 +557,7 @@ void FourLineDisplayUsermod::setup() {
|
|||||||
case SSD1306_64: u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_HW_I2C(); break;
|
case SSD1306_64: u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_HW_I2C(); break;
|
||||||
case SSD1305: u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C(); break;
|
case SSD1305: u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C(); break;
|
||||||
case SSD1305_64: u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C(); break;
|
case SSD1305_64: u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C(); break;
|
||||||
|
case SSD1309_64: u8x8 = (U8X8 *) new U8X8_SSD1309_128X64_NONAME0_HW_I2C(); break;
|
||||||
// U8X8 uses global SPI variable that is attached to VSPI bus on ESP32
|
// U8X8 uses global SPI variable that is attached to VSPI bus on ESP32
|
||||||
case SSD1306_SPI: u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_HW_SPI(ioPin[0], ioPin[1], ioPin[2]); break; // Pins are cs, dc, reset
|
case SSD1306_SPI: u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_HW_SPI(ioPin[0], ioPin[1], ioPin[2]); break; // Pins are cs, dc, reset
|
||||||
case SSD1306_SPI64: u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_HW_SPI(ioPin[0], ioPin[1], ioPin[2]); break; // Pins are cs, dc, reset
|
case SSD1306_SPI64: u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_HW_SPI(ioPin[0], ioPin[1], ioPin[2]); break; // Pins are cs, dc, reset
|
||||||
@ -581,7 +583,7 @@ void FourLineDisplayUsermod::setup() {
|
|||||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||||
// interfaces here
|
// interfaces here
|
||||||
void FourLineDisplayUsermod::connected() {
|
void FourLineDisplayUsermod::connected() {
|
||||||
knownSsid = WiFi.SSID(); //apActive ? apSSID : WiFi.SSID(); //apActive ? WiFi.softAPSSID() :
|
knownSsid = WiFi.SSID(); //apActive ? apSSID : WiFi.SSID(); //apActive ? WiFi.softAPSSID() :
|
||||||
knownIp = Network.localIP(); //apActive ? IPAddress(4, 3, 2, 1) : Network.localIP();
|
knownIp = Network.localIP(); //apActive ? IPAddress(4, 3, 2, 1) : Network.localIP();
|
||||||
networkOverlay(PSTR("NETWORK INFO"),7000);
|
networkOverlay(PSTR("NETWORK INFO"),7000);
|
||||||
}
|
}
|
||||||
@ -637,7 +639,7 @@ void FourLineDisplayUsermod::redraw(bool forceRedraw) {
|
|||||||
powerON = !powerON;
|
powerON = !powerON;
|
||||||
drawStatusIcons();
|
drawStatusIcons();
|
||||||
return;
|
return;
|
||||||
} else if (knownnightlight != nightlightActive) { //trigger moon icon
|
} else if (knownnightlight != nightlightActive) { //trigger moon icon
|
||||||
knownnightlight = nightlightActive;
|
knownnightlight = nightlightActive;
|
||||||
drawStatusIcons();
|
drawStatusIcons();
|
||||||
if (knownnightlight) {
|
if (knownnightlight) {
|
||||||
@ -652,7 +654,7 @@ void FourLineDisplayUsermod::redraw(bool forceRedraw) {
|
|||||||
return;
|
return;
|
||||||
} else if (knownMode != effectCurrent || knownPalette != effectPalette) {
|
} else if (knownMode != effectCurrent || knownPalette != effectPalette) {
|
||||||
if (displayTurnedOff) needRedraw = true;
|
if (displayTurnedOff) needRedraw = true;
|
||||||
else {
|
else {
|
||||||
if (knownPalette != effectPalette) { showCurrentEffectOrPalette(effectPalette, JSON_palette_names, 2); knownPalette = effectPalette; }
|
if (knownPalette != effectPalette) { showCurrentEffectOrPalette(effectPalette, JSON_palette_names, 2); knownPalette = effectPalette; }
|
||||||
if (knownMode != effectCurrent) { showCurrentEffectOrPalette(effectCurrent, JSON_mode_names, 3); knownMode = effectCurrent; }
|
if (knownMode != effectCurrent) { showCurrentEffectOrPalette(effectCurrent, JSON_mode_names, 3); knownMode = effectCurrent; }
|
||||||
lastRedraw = now;
|
lastRedraw = now;
|
||||||
@ -703,7 +705,7 @@ void FourLineDisplayUsermod::redraw(bool forceRedraw) {
|
|||||||
drawArrow();
|
drawArrow();
|
||||||
drawStatusIcons();
|
drawStatusIcons();
|
||||||
|
|
||||||
// Second row
|
// Second row
|
||||||
updateBrightness();
|
updateBrightness();
|
||||||
updateSpeed();
|
updateSpeed();
|
||||||
updateIntensity();
|
updateIntensity();
|
||||||
@ -805,8 +807,8 @@ void FourLineDisplayUsermod::drawArrow() {
|
|||||||
lockRedraw = false;
|
lockRedraw = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Display the current effect or palette (desiredEntry)
|
//Display the current effect or palette (desiredEntry)
|
||||||
// on the appropriate line (row).
|
// on the appropriate line (row).
|
||||||
void FourLineDisplayUsermod::showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row) {
|
void FourLineDisplayUsermod::showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row) {
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
@ -857,7 +859,7 @@ void FourLineDisplayUsermod::showCurrentEffectOrPalette(int inputEffPal, const c
|
|||||||
while (smallChars1 < (MAX_MODE_LINE_SPACE-1)) smallBuffer1[smallChars1++]=' ';
|
while (smallChars1 < (MAX_MODE_LINE_SPACE-1)) smallBuffer1[smallChars1++]=' ';
|
||||||
smallBuffer1[smallChars1] = 0;
|
smallBuffer1[smallChars1] = 0;
|
||||||
drawString(1, row*lineHeight, smallBuffer1, true);
|
drawString(1, row*lineHeight, smallBuffer1, true);
|
||||||
while (smallChars2 < (MAX_MODE_LINE_SPACE-1)) smallBuffer2[smallChars2++]=' ';
|
while (smallChars2 < (MAX_MODE_LINE_SPACE-1)) smallBuffer2[smallChars2++]=' ';
|
||||||
smallBuffer2[smallChars2] = 0;
|
smallBuffer2[smallChars2] = 0;
|
||||||
drawString(1, row*lineHeight+1, smallBuffer2, true);
|
drawString(1, row*lineHeight+1, smallBuffer2, true);
|
||||||
}
|
}
|
||||||
@ -1150,7 +1152,7 @@ void FourLineDisplayUsermod::onUpdateBegin(bool init) {
|
|||||||
xTaskCreatePinnedToCore(
|
xTaskCreatePinnedToCore(
|
||||||
[](void * par) { // Function to implement the task
|
[](void * par) { // Function to implement the task
|
||||||
// see https://www.freertos.org/vtaskdelayuntil.html
|
// see https://www.freertos.org/vtaskdelayuntil.html
|
||||||
const TickType_t xFrequency = REFRESH_RATE_MS * portTICK_PERIOD_MS / 2;
|
const TickType_t xFrequency = REFRESH_RATE_MS * portTICK_PERIOD_MS / 2;
|
||||||
TickType_t xLastWakeTime = xTaskGetTickCount();
|
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||||
for(;;) {
|
for(;;) {
|
||||||
delay(1); // DO NOT DELETE THIS LINE! It is needed to give the IDLE(0) task enough time and to keep the watchdog happy.
|
delay(1); // DO NOT DELETE THIS LINE! It is needed to give the IDLE(0) task enough time and to keep the watchdog happy.
|
||||||
@ -1205,6 +1207,7 @@ void FourLineDisplayUsermod::appendConfigData() {
|
|||||||
oappend(SET_F("addOption(dd,'SSD1306 128x64',3);"));
|
oappend(SET_F("addOption(dd,'SSD1306 128x64',3);"));
|
||||||
oappend(SET_F("addOption(dd,'SSD1305',4);"));
|
oappend(SET_F("addOption(dd,'SSD1305',4);"));
|
||||||
oappend(SET_F("addOption(dd,'SSD1305 128x64',5);"));
|
oappend(SET_F("addOption(dd,'SSD1305 128x64',5);"));
|
||||||
|
oappend(SET_F("addOption(dd,'SSD1309 128x64',9);"));
|
||||||
oappend(SET_F("addOption(dd,'SSD1306 SPI',6);"));
|
oappend(SET_F("addOption(dd,'SSD1306 SPI',6);"));
|
||||||
oappend(SET_F("addOption(dd,'SSD1306 SPI 128x64',7);"));
|
oappend(SET_F("addOption(dd,'SSD1306 SPI 128x64',7);"));
|
||||||
oappend(SET_F("addOption(dd,'SSD1309 SPI 128x64',8);"));
|
oappend(SET_F("addOption(dd,'SSD1309 SPI 128x64',8);"));
|
||||||
@ -1218,14 +1221,14 @@ void FourLineDisplayUsermod::appendConfigData() {
|
|||||||
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
|
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
|
||||||
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
||||||
* If you want to force saving the current state, use serializeConfig() in your loop().
|
* If you want to force saving the current state, use serializeConfig() in your loop().
|
||||||
*
|
*
|
||||||
* CAUTION: serializeConfig() will initiate a filesystem write operation.
|
* CAUTION: serializeConfig() will initiate a filesystem write operation.
|
||||||
* It might cause the LEDs to stutter and will cause flash wear if called too often.
|
* It might cause the LEDs to stutter and will cause flash wear if called too often.
|
||||||
* Use it sparingly and always in the loop, never in network callbacks!
|
* Use it sparingly and always in the loop, never in network callbacks!
|
||||||
*
|
*
|
||||||
* addToConfig() will also not yet add your setting to one of the settings pages automatically.
|
* addToConfig() will also not yet add your setting to one of the settings pages automatically.
|
||||||
* To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually.
|
* To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually.
|
||||||
*
|
*
|
||||||
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
||||||
*/
|
*/
|
||||||
void FourLineDisplayUsermod::addToConfig(JsonObject& root) {
|
void FourLineDisplayUsermod::addToConfig(JsonObject& root) {
|
||||||
@ -1252,7 +1255,7 @@ void FourLineDisplayUsermod::addToConfig(JsonObject& root) {
|
|||||||
/*
|
/*
|
||||||
* readFromConfig() can be used to read back the custom settings you added with addToConfig().
|
* readFromConfig() can be used to read back the custom settings you added with addToConfig().
|
||||||
* This is called by WLED when settings are loaded (currently this only happens once immediately after boot)
|
* This is called by WLED when settings are loaded (currently this only happens once immediately after boot)
|
||||||
*
|
*
|
||||||
* readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes),
|
* readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes),
|
||||||
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
|
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
|
||||||
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
|
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
|
||||||
@ -1346,6 +1349,10 @@ bool FourLineDisplayUsermod::readFromConfig(JsonObject& root) {
|
|||||||
u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1305_128x64_adafruit, u8x8_cad_ssd13xx_fast_i2c, u8x8_byte_arduino_hw_i2c, u8x8_gpio_and_delay_arduino);
|
u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1305_128x64_adafruit, u8x8_cad_ssd13xx_fast_i2c, u8x8_byte_arduino_hw_i2c, u8x8_gpio_and_delay_arduino);
|
||||||
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE);
|
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE);
|
||||||
break;
|
break;
|
||||||
|
case SSD1309_64:
|
||||||
|
u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1309_128x64_noname0, u8x8_cad_ssd13xx_fast_i2c, u8x8_byte_arduino_hw_i2c, u8x8_gpio_and_delay_arduino);
|
||||||
|
u8x8_SetPin_HW_I2C(u8x8->getU8x8(), U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE);
|
||||||
|
break;
|
||||||
case SSD1306_SPI:
|
case SSD1306_SPI:
|
||||||
u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1306_128x32_univision, u8x8_cad_001, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay_arduino);
|
u8x8_Setup(u8x8->getU8x8(), u8x8_d_ssd1306_128x32_univision, u8x8_cad_001, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay_arduino);
|
||||||
u8x8_SetPin_4Wire_HW_SPI(u8x8->getU8x8(), ioPin[0], ioPin[1], ioPin[2]); // Pins are cs, dc, reset
|
u8x8_SetPin_4Wire_HW_SPI(u8x8->getU8x8(), ioPin[0], ioPin[1], ioPin[2]); // Pins are cs, dc, reset
|
||||||
|
@ -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
|
||||||
|
|
@ -8,18 +8,18 @@ The core of these usermods are a copy of the originals. The main changes are to
|
|||||||
The display usermod UI has been completely changed.
|
The display usermod UI has been completely changed.
|
||||||
|
|
||||||
|
|
||||||
The changes made to the RotaryEncoder usermod were made to support the new UI in the display usermod.
|
The changes made to the RotaryEncoder usermod were made to support the new UI in the display usermod.
|
||||||
Without the display, it functions identical to the original.
|
Without the display, it functions identical to the original.
|
||||||
The original "usermod_v2_auto_save" will not work with the display just yet.
|
The original "usermod_v2_auto_save" will not work with the display just yet.
|
||||||
|
|
||||||
Press the encoder to cycle through the options:
|
Press the encoder to cycle through the options:
|
||||||
*Brightness
|
* Brightness
|
||||||
*Speed
|
* Speed
|
||||||
*Intensity
|
* Intensity
|
||||||
*Palette
|
* Palette
|
||||||
*Effect
|
* Effect
|
||||||
*Main Color (only if display is used)
|
* Main Color (only if display is used)
|
||||||
*Saturation (only if display is used)
|
* Saturation (only if display is used)
|
||||||
|
|
||||||
Press and hold the encoder to display Network Info
|
Press and hold the encoder to display Network Info
|
||||||
if AP is active, it will display the AP, SSID and Password
|
if AP is active, it will display the AP, SSID and Password
|
||||||
@ -30,10 +30,23 @@ Also shows if the timer is enabled.
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Please refer to the original `usermod_v2_rotary_encoder_ui` readme for the main instructions.<br/>
|
Copy the example `platformio_override.sample.ini` to the root directory of your particular build and rename it to `platformio_override.ini`.
|
||||||
To activate this alternative usermod, add `#define USE_ALT_DISPlAY` to the `usermods_list.cpp` file,
|
|
||||||
or add `-D USE_ALT_DISPlAY` to the original `platformio_override.ini.sample` file.
|
|
||||||
|
|
||||||
|
To activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE SENSITIVE) to the `usermods_list.cpp` file, or add `-D USE_ALT_DISPlAY` to your `platformio_override.ini` file
|
||||||
|
|
||||||
|
### Define Your Options
|
||||||
|
|
||||||
|
* `USERMOD_ROTARY_ENCODER_UI` - define this to have this user mod included wled00\usermods_list.cpp
|
||||||
|
* `USERMOD_FOUR_LINE_DISPLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp
|
||||||
|
also tells this usermod that the display is available
|
||||||
|
(see the Four Line Display usermod `readme.md` for more details)
|
||||||
|
* `USE_ALT_DISPlAY` - Mandatory to use Four Line Display
|
||||||
|
* `ENCODER_DT_PIN` - defaults to 18
|
||||||
|
* `ENCODER_CLK_PIN` - defaults to 5
|
||||||
|
* `ENCODER_SW_PIN` - defaults to 19
|
||||||
|
* `USERMOD_ROTARY_ENCODER_GPIO` - GPIO functionality:
|
||||||
|
`INPUT_PULLUP` to use internal pull-up
|
||||||
|
`INPUT` to use pull-up on the PCB
|
||||||
|
|
||||||
### PlatformIO requirements
|
### PlatformIO requirements
|
||||||
|
|
||||||
|
@ -392,26 +392,26 @@ byte RotaryEncoderUIUsermod::readPin(uint8_t pin) {
|
|||||||
* modes_alpha_indexes and palettes_alpha_indexes.
|
* modes_alpha_indexes and palettes_alpha_indexes.
|
||||||
*/
|
*/
|
||||||
void RotaryEncoderUIUsermod::sortModesAndPalettes() {
|
void RotaryEncoderUIUsermod::sortModesAndPalettes() {
|
||||||
DEBUG_PRINTLN(F("Sorting modes and palettes."));
|
DEBUG_PRINT(F("Sorting modes: ")); DEBUG_PRINTLN(strip.getModeCount());
|
||||||
//modes_qstrings = re_findModeStrings(JSON_mode_names, strip.getModeCount());
|
//modes_qstrings = re_findModeStrings(JSON_mode_names, strip.getModeCount());
|
||||||
modes_qstrings = strip.getModeDataSrc();
|
modes_qstrings = strip.getModeDataSrc();
|
||||||
modes_alpha_indexes = re_initIndexArray(strip.getModeCount());
|
modes_alpha_indexes = re_initIndexArray(strip.getModeCount());
|
||||||
re_sortModes(modes_qstrings, modes_alpha_indexes, strip.getModeCount(), MODE_SORT_SKIP_COUNT);
|
re_sortModes(modes_qstrings, modes_alpha_indexes, strip.getModeCount(), MODE_SORT_SKIP_COUNT);
|
||||||
|
|
||||||
palettes_qstrings = re_findModeStrings(JSON_palette_names, strip.getPaletteCount()+strip.customPalettes.size());
|
DEBUG_PRINT(F("Sorting palettes: ")); DEBUG_PRINT(strip.getPaletteCount()); DEBUG_PRINT('/'); DEBUG_PRINTLN(strip.customPalettes.size());
|
||||||
palettes_alpha_indexes = re_initIndexArray(strip.getPaletteCount()+strip.customPalettes.size());
|
palettes_qstrings = re_findModeStrings(JSON_palette_names, strip.getPaletteCount());
|
||||||
|
palettes_alpha_indexes = re_initIndexArray(strip.getPaletteCount());
|
||||||
if (strip.customPalettes.size()) {
|
if (strip.customPalettes.size()) {
|
||||||
for (int i=0; i<strip.customPalettes.size(); i++) {
|
for (int i=0; i<strip.customPalettes.size(); i++) {
|
||||||
palettes_alpha_indexes[strip.getPaletteCount()+i] = 255-i;
|
palettes_alpha_indexes[strip.getPaletteCount()-strip.customPalettes.size()+i] = 255-i;
|
||||||
palettes_qstrings[strip.getPaletteCount()+i] = PSTR("~Custom~");
|
palettes_qstrings[strip.getPaletteCount()-strip.customPalettes.size()+i] = PSTR("~Custom~");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// How many palette names start with '*' and should not be sorted?
|
// How many palette names start with '*' and should not be sorted?
|
||||||
// (Also skipping the first one, 'Default').
|
// (Also skipping the first one, 'Default').
|
||||||
int skipPaletteCount = 1;
|
int skipPaletteCount = 1;
|
||||||
while (pgm_read_byte_near(palettes_qstrings[skipPaletteCount++]) == '*') ;
|
while (pgm_read_byte_near(palettes_qstrings[skipPaletteCount]) == '*') skipPaletteCount++;
|
||||||
re_sortModes(palettes_qstrings, palettes_alpha_indexes, strip.getPaletteCount(), skipPaletteCount);
|
re_sortModes(palettes_qstrings, palettes_alpha_indexes, strip.getPaletteCount()-strip.customPalettes.size(), skipPaletteCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte *RotaryEncoderUIUsermod::re_initIndexArray(int numModes) {
|
byte *RotaryEncoderUIUsermod::re_initIndexArray(int numModes) {
|
||||||
|
@ -5011,21 +5011,25 @@ uint16_t mode_2DDrift() { // By: Stepko https://editor.soulmateli
|
|||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
const uint16_t cols = SEGMENT.virtualWidth();
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
|
const uint16_t colsCenter = (cols>>1) + (cols%2);
|
||||||
|
const uint16_t rowsCenter = (rows>>1) + (rows%2);
|
||||||
|
|
||||||
SEGMENT.fadeToBlackBy(128);
|
SEGMENT.fadeToBlackBy(128);
|
||||||
const uint16_t maxDim = MAX(cols, rows)/2;
|
const uint16_t maxDim = MAX(cols, rows)/2;
|
||||||
unsigned long t = strip.now / (32 - (SEGMENT.speed>>3));
|
unsigned long t = strip.now / (32 - (SEGMENT.speed>>3));
|
||||||
unsigned long t_20 = t/20; // softhack007: pre-calculating this gives about 10% speedup
|
unsigned long t_20 = t/20; // softhack007: pre-calculating this gives about 10% speedup
|
||||||
for (float i = 1; i < maxDim; i += 0.25) {
|
for (float i = 1.0f; i < maxDim; i += 0.25f) {
|
||||||
float angle = radians(t * (maxDim - i));
|
float angle = radians(t * (maxDim - i));
|
||||||
uint16_t myX = (cols>>1) + (uint16_t)(sin_t(angle) * i) + (cols%2);
|
int16_t mySin = sin_t(angle) * i;
|
||||||
uint16_t myY = (rows>>1) + (uint16_t)(cos_t(angle) * i) + (rows%2);
|
int16_t myCos = cos_t(angle) * i;
|
||||||
SEGMENT.setPixelColorXY(myX, myY, ColorFromPalette(SEGPALETTE, (i * 20) + t_20, 255, LINEARBLEND));
|
SEGMENT.setPixelColorXY(colsCenter + mySin, rowsCenter + myCos, ColorFromPalette(SEGPALETTE, (i * 20) + t_20, 255, LINEARBLEND));
|
||||||
|
if (SEGMENT.check1) SEGMENT.setPixelColorXY(colsCenter + myCos, rowsCenter + mySin, ColorFromPalette(SEGPALETTE, (i * 20) + t_20, 255, LINEARBLEND));
|
||||||
}
|
}
|
||||||
SEGMENT.blur(SEGMENT.intensity>>3);
|
SEGMENT.blur(SEGMENT.intensity>>3);
|
||||||
|
|
||||||
return FRAMETIME;
|
return FRAMETIME;
|
||||||
} // mode_2DDrift()
|
} // mode_2DDrift()
|
||||||
static const char _data_FX_MODE_2DDRIFT[] PROGMEM = "Drift@Rotation speed,Blur amount;;!;2";
|
static const char _data_FX_MODE_2DDRIFT[] PROGMEM = "Drift@Rotation speed,Blur amount,,,,Twin;;!;2";
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
@ -6198,8 +6202,9 @@ uint16_t mode_2Ddriftrose(void) {
|
|||||||
|
|
||||||
SEGMENT.fadeToBlackBy(32+(SEGMENT.speed>>3));
|
SEGMENT.fadeToBlackBy(32+(SEGMENT.speed>>3));
|
||||||
for (size_t i = 1; i < 37; i++) {
|
for (size_t i = 1; i < 37; i++) {
|
||||||
uint32_t x = (CX + (sin_t(radians(i * 10)) * (beatsin8(i, 0, L*2)-L))) * 255.f;
|
float angle = radians(i * 10);
|
||||||
uint32_t y = (CY + (cos_t(radians(i * 10)) * (beatsin8(i, 0, L*2)-L))) * 255.f;
|
uint32_t x = (CX + (sin_t(angle) * (beatsin8(i, 0, L*2)-L))) * 255.f;
|
||||||
|
uint32_t y = (CY + (cos_t(angle) * (beatsin8(i, 0, L*2)-L))) * 255.f;
|
||||||
SEGMENT.wu_pixel(x, y, CHSV(i * 10, 255, 255));
|
SEGMENT.wu_pixel(x, y, CHSV(i * 10, 255, 255));
|
||||||
}
|
}
|
||||||
SEGMENT.blur((SEGMENT.intensity>>4)+1);
|
SEGMENT.blur((SEGMENT.intensity>>4)+1);
|
||||||
|
11
wled00/FX.h
11
wled00/FX.h
@ -59,13 +59,12 @@
|
|||||||
/* Not used in all effects yet */
|
/* Not used in all effects yet */
|
||||||
#define WLED_FPS 42
|
#define WLED_FPS 42
|
||||||
#define FRAMETIME_FIXED (1000/WLED_FPS)
|
#define FRAMETIME_FIXED (1000/WLED_FPS)
|
||||||
//#define FRAMETIME _frametime
|
|
||||||
#define FRAMETIME strip.getFrameTime()
|
#define FRAMETIME strip.getFrameTime()
|
||||||
|
|
||||||
/* each segment uses 82 bytes of SRAM memory, so if you're application fails because of
|
/* each segment uses 82 bytes of SRAM memory, so if you're application fails because of
|
||||||
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
|
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
#define MAX_NUM_SEGMENTS 12
|
#define MAX_NUM_SEGMENTS 16
|
||||||
/* How much data bytes all segments combined may allocate */
|
/* How much data bytes all segments combined may allocate */
|
||||||
#define MAX_SEGMENT_DATA 5120
|
#define MAX_SEGMENT_DATA 5120
|
||||||
#else
|
#else
|
||||||
@ -73,11 +72,7 @@
|
|||||||
#define MAX_NUM_SEGMENTS 32
|
#define MAX_NUM_SEGMENTS 32
|
||||||
#endif
|
#endif
|
||||||
#if defined(ARDUINO_ARCH_ESP32S2)
|
#if defined(ARDUINO_ARCH_ESP32S2)
|
||||||
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
|
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*768 // 24k by default (S2 is short on free RAM)
|
||||||
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*1024 // 32k by default
|
|
||||||
#else
|
|
||||||
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*768 // 24k by default
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*1280 // 40k by default
|
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*1280 // 40k by default
|
||||||
#endif
|
#endif
|
||||||
@ -810,7 +805,7 @@ class WS2812FX { // 96 bytes
|
|||||||
inline uint8_t getSegmentsNum(void) { return _segments.size(); } // returns currently present segments
|
inline uint8_t getSegmentsNum(void) { return _segments.size(); } // returns currently present segments
|
||||||
inline uint8_t getCurrSegmentId(void) { return _segment_index; } // returns current segment index (only valid while strip.isServicing())
|
inline uint8_t getCurrSegmentId(void) { return _segment_index; } // returns current segment index (only valid while strip.isServicing())
|
||||||
inline uint8_t getMainSegmentId(void) { return _mainSegment; } // returns main segment index
|
inline uint8_t getMainSegmentId(void) { return _mainSegment; } // returns main segment index
|
||||||
inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count
|
inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT + customPalettes.size(); }
|
||||||
inline uint8_t getTargetFps() { return _targetFps; } // returns rough FPS value for las 2s interval
|
inline uint8_t getTargetFps() { return _targetFps; } // returns rough FPS value for las 2s interval
|
||||||
inline uint8_t getModeCount() { return _modeCount; } // returns number of registered modes/effects
|
inline uint8_t getModeCount() { return _modeCount; } // returns number of registered modes/effects
|
||||||
|
|
||||||
|
@ -1098,6 +1098,12 @@ void WS2812FX::finalizeInit(void) {
|
|||||||
uint16_t prevLen = 0;
|
uint16_t prevLen = 0;
|
||||||
for (int i = 0; i < defNumBusses && i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) {
|
for (int i = 0; i < defNumBusses && i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) {
|
||||||
uint8_t defPin[] = {defDataPins[i]};
|
uint8_t defPin[] = {defDataPins[i]};
|
||||||
|
// when booting without config (1st boot) we need to make sure GPIOs defined for LED output don't clash with hardware
|
||||||
|
// i.e. DEBUG (GPIO1), DMX (2), SPI RAM/FLASH (16&17 on ESP32-WROVER/PICO), etc
|
||||||
|
if (pinManager.isPinAllocated(defPin[0])) {
|
||||||
|
defPin[0] = 1; // start with GPIO1 and work upwards
|
||||||
|
while (pinManager.isPinAllocated(defPin[0]) && defPin[0] < WLED_NUM_PINS) defPin[0]++;
|
||||||
|
}
|
||||||
uint16_t start = prevLen;
|
uint16_t start = prevLen;
|
||||||
uint16_t count = defCounts[(i < defNumCounts) ? i : defNumCounts -1];
|
uint16_t count = defCounts[(i < defNumCounts) ? i : defNumCounts -1];
|
||||||
prevLen += count;
|
prevLen += count;
|
||||||
@ -1162,12 +1168,16 @@ void WS2812FX::service() {
|
|||||||
uint16_t delay = FRAMETIME;
|
uint16_t delay = FRAMETIME;
|
||||||
|
|
||||||
if (!seg.freeze) { //only run effect function if not frozen
|
if (!seg.freeze) { //only run effect function if not frozen
|
||||||
|
int16_t oldCCT = BusManager::getSegmentCCT(); // store original CCT value (actually it is not Segment based)
|
||||||
_virtualSegmentLength = seg.virtualLength(); //SEGLEN
|
_virtualSegmentLength = seg.virtualLength(); //SEGLEN
|
||||||
_colors_t[0] = gamma32(seg.currentColor(0));
|
_colors_t[0] = gamma32(seg.currentColor(0));
|
||||||
_colors_t[1] = gamma32(seg.currentColor(1));
|
_colors_t[1] = gamma32(seg.currentColor(1));
|
||||||
_colors_t[2] = gamma32(seg.currentColor(2));
|
_colors_t[2] = gamma32(seg.currentColor(2));
|
||||||
seg.currentPalette(_currentPalette, seg.palette); // we need to pass reference
|
seg.currentPalette(_currentPalette, seg.palette); // we need to pass reference
|
||||||
if (!cctFromRgb || correctWB) BusManager::setSegmentCCT(seg.currentBri(true), correctWB);
|
// when correctWB is true we need to correct/adjust RGB value according to desired CCT value, but it will also affect actual WW/CW ratio
|
||||||
|
// when cctFromRgb is true we implicitly calculate WW and CW from RGB values
|
||||||
|
if (cctFromRgb) BusManager::setSegmentCCT(-1);
|
||||||
|
else BusManager::setSegmentCCT(seg.currentBri(true), correctWB);
|
||||||
// Effect blending
|
// Effect blending
|
||||||
// When two effects are being blended, each may have different segment data, this
|
// When two effects are being blended, each may have different segment data, this
|
||||||
// data needs to be saved first and then restored before running previous mode.
|
// data needs to be saved first and then restored before running previous mode.
|
||||||
@ -1190,20 +1200,19 @@ void WS2812FX::service() {
|
|||||||
#endif
|
#endif
|
||||||
seg.call++;
|
seg.call++;
|
||||||
if (seg.isInTransition() && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition
|
if (seg.isInTransition() && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition
|
||||||
|
BusManager::setSegmentCCT(oldCCT); // restore old CCT for ABL adjustments
|
||||||
}
|
}
|
||||||
|
|
||||||
seg.next_time = nowUp + delay;
|
seg.next_time = nowUp + delay;
|
||||||
}
|
}
|
||||||
// if (_segment_index == _queuedChangesSegId) setUpSegmentFromQueuedChanges();
|
|
||||||
_segment_index++;
|
_segment_index++;
|
||||||
}
|
}
|
||||||
_virtualSegmentLength = 0;
|
_virtualSegmentLength = 0;
|
||||||
BusManager::setSegmentCCT(-1);
|
|
||||||
_isServicing = false;
|
_isServicing = false;
|
||||||
_triggered = false;
|
_triggered = false;
|
||||||
|
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
if (millis() - nowUp > _frametime) DEBUG_PRINTLN(F("Slow effects."));
|
if (millis() - nowUp > _frametime) DEBUG_PRINTF_P(PSTR("Slow effects %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime);
|
||||||
#endif
|
#endif
|
||||||
if (doShow) {
|
if (doShow) {
|
||||||
yield();
|
yield();
|
||||||
@ -1211,7 +1220,7 @@ void WS2812FX::service() {
|
|||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
if (millis() - nowUp > _frametime) DEBUG_PRINTLN(F("Slow strip."));
|
if (millis() - nowUp > _frametime) DEBUG_PRINTF_P(PSTR("Slow strip %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1390,11 +1399,7 @@ bool WS2812FX::hasCCTBus(void) {
|
|||||||
for (size_t b = 0; b < BusManager::getNumBusses(); b++) {
|
for (size_t b = 0; b < BusManager::getNumBusses(); b++) {
|
||||||
Bus *bus = BusManager::getBus(b);
|
Bus *bus = BusManager::getBus(b);
|
||||||
if (bus == nullptr || bus->getLength()==0) break;
|
if (bus == nullptr || bus->getLength()==0) break;
|
||||||
switch (bus->getType()) {
|
if (bus->hasCCT()) return true;
|
||||||
case TYPE_ANALOG_5CH:
|
|
||||||
case TYPE_ANALOG_2CH:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1425,31 +1430,12 @@ void WS2812FX::setSegment(uint8_t segId, uint16_t i1, uint16_t i2, uint8_t group
|
|||||||
appendSegment(Segment(0, strip.getLengthTotal()));
|
appendSegment(Segment(0, strip.getLengthTotal()));
|
||||||
segId = getSegmentsNum()-1; // segments are added at the end of list
|
segId = getSegmentsNum()-1; // segments are added at the end of list
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
if (_queuedChangesSegId == segId) _queuedChangesSegId = 255; // cancel queued change if already queued for this segment
|
|
||||||
|
|
||||||
if (segId < getMaxSegments() && segId == getCurrSegmentId() && isServicing()) { // queue change to prevent concurrent access
|
|
||||||
// queuing a change for a second segment will lead to the loss of the first change if not yet applied
|
|
||||||
// however this is not a problem as the queued change is applied immediately after the effect function in that segment returns
|
|
||||||
_qStart = i1; _qStop = i2; _qStartY = startY; _qStopY = stopY;
|
|
||||||
_qGrouping = grouping; _qSpacing = spacing; _qOffset = offset;
|
|
||||||
_queuedChangesSegId = segId;
|
|
||||||
DEBUG_PRINT(F("Segment queued: ")); DEBUG_PRINTLN(segId);
|
|
||||||
return; // queued changes are applied immediately after effect function returns
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
suspend();
|
suspend();
|
||||||
_segments[segId].setUp(i1, i2, grouping, spacing, offset, startY, stopY);
|
_segments[segId].setUp(i1, i2, grouping, spacing, offset, startY, stopY);
|
||||||
resume();
|
resume();
|
||||||
if (segId > 0 && segId == getSegmentsNum()-1 && i2 <= i1) _segments.pop_back(); // if last segment was deleted remove it from vector
|
if (segId > 0 && segId == getSegmentsNum()-1 && i2 <= i1) _segments.pop_back(); // if last segment was deleted remove it from vector
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
void WS2812FX::setUpSegmentFromQueuedChanges() {
|
|
||||||
if (_queuedChangesSegId >= getSegmentsNum()) return;
|
|
||||||
_segments[_queuedChangesSegId].setUp(_qStart, _qStop, _qGrouping, _qSpacing, _qOffset, _qStartY, _qStopY);
|
|
||||||
_queuedChangesSegId = 255;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
void WS2812FX::resetSegments() {
|
void WS2812FX::resetSegments() {
|
||||||
_segments.clear(); // destructs all Segment as part of clearing
|
_segments.clear(); // destructs all Segment as part of clearing
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
|
@ -9,9 +9,10 @@
|
|||||||
#include "bus_wrapper.h"
|
#include "bus_wrapper.h"
|
||||||
#include "bus_manager.h"
|
#include "bus_manager.h"
|
||||||
|
|
||||||
|
extern bool cctICused;
|
||||||
|
|
||||||
//colors.cpp
|
//colors.cpp
|
||||||
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
|
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
|
||||||
uint16_t approximateKelvinFromRGB(uint32_t rgb);
|
|
||||||
|
|
||||||
//udp.cpp
|
//udp.cpp
|
||||||
uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte *buffer, uint8_t bri=255, bool isRGBW=false);
|
uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte *buffer, uint8_t bri=255, bool isRGBW=false);
|
||||||
@ -122,13 +123,13 @@ BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com)
|
|||||||
}
|
}
|
||||||
_iType = PolyBus::getI(bc.type, _pins, nr);
|
_iType = PolyBus::getI(bc.type, _pins, nr);
|
||||||
if (_iType == I_NONE) return;
|
if (_iType == I_NONE) return;
|
||||||
if (bc.doubleBuffer && !allocData(bc.count * (Bus::hasWhite(_type) + 3*Bus::hasRGB(_type)))) return; //warning: hardcoded channel count
|
if (bc.doubleBuffer && !allocData(bc.count * Bus::getNumberOfChannels(bc.type))) return;
|
||||||
//_buffering = bc.doubleBuffer;
|
//_buffering = bc.doubleBuffer;
|
||||||
uint16_t lenToCreate = bc.count;
|
uint16_t lenToCreate = bc.count;
|
||||||
if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(bc.count); // only needs a third of "RGB" LEDs for NeoPixelBus
|
if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(bc.count); // only needs a third of "RGB" LEDs for NeoPixelBus
|
||||||
_busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr, _frequencykHz);
|
_busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr, _frequencykHz);
|
||||||
_valid = (_busPtr != nullptr);
|
_valid = (_busPtr != nullptr);
|
||||||
DEBUG_PRINTF("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u). mA=%d/%d\n", _valid?"S":"Uns", nr, bc.count, bc.type, _pins[0], _pins[1], _iType, _milliAmpsPerLed, _milliAmpsMax);
|
DEBUG_PRINTF_P(PSTR("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u). mA=%d/%d\n"), _valid?"S":"Uns", nr, bc.count, bc.type, _pins[0], IS_2PIN(bc.type)?_pins[1]:255, _iType, _milliAmpsPerLed, _milliAmpsMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
//fine tune power estimation constants for your setup
|
//fine tune power estimation constants for your setup
|
||||||
@ -205,13 +206,15 @@ void BusDigital::show() {
|
|||||||
_milliAmpsTotal = 0;
|
_milliAmpsTotal = 0;
|
||||||
if (!_valid) return;
|
if (!_valid) return;
|
||||||
|
|
||||||
|
uint8_t cctWW = 0, cctCW = 0;
|
||||||
uint8_t newBri = estimateCurrentAndLimitBri(); // will fill _milliAmpsTotal
|
uint8_t newBri = estimateCurrentAndLimitBri(); // will fill _milliAmpsTotal
|
||||||
if (newBri < _bri) PolyBus::setBrightness(_busPtr, _iType, newBri); // limit brightness to stay within current limits
|
if (newBri < _bri) PolyBus::setBrightness(_busPtr, _iType, newBri); // limit brightness to stay within current limits
|
||||||
|
|
||||||
if (_data) { // use _buffering this causes ~20% FPS drop
|
if (_data) {
|
||||||
size_t channels = Bus::hasWhite(_type) + 3*Bus::hasRGB(_type);
|
size_t channels = getNumberOfChannels();
|
||||||
|
int16_t oldCCT = Bus::_cct; // temporarily save bus CCT
|
||||||
for (size_t i=0; i<_len; i++) {
|
for (size_t i=0; i<_len; i++) {
|
||||||
size_t offset = i*channels;
|
size_t offset = i * channels;
|
||||||
uint8_t co = _colorOrderMap.getPixelColorOrder(i+_start, _colorOrder);
|
uint8_t co = _colorOrderMap.getPixelColorOrder(i+_start, _colorOrder);
|
||||||
uint32_t c;
|
uint32_t c;
|
||||||
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs (_len is always a multiple of 3)
|
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs (_len is always a multiple of 3)
|
||||||
@ -221,17 +224,26 @@ void BusDigital::show() {
|
|||||||
case 2: c = RGBW32(_data[offset-2], _data[offset-1], _data[offset] , 0); break;
|
case 2: c = RGBW32(_data[offset-2], _data[offset-1], _data[offset] , 0); break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c = RGBW32(_data[offset],_data[offset+1],_data[offset+2],(Bus::hasWhite(_type)?_data[offset+3]:0));
|
if (hasRGB()) c = RGBW32(_data[offset], _data[offset+1], _data[offset+2], hasWhite() ? _data[offset+3] : 0);
|
||||||
|
else c = RGBW32(0, 0, 0, _data[offset]);
|
||||||
|
}
|
||||||
|
if (hasCCT()) {
|
||||||
|
// unfortunately as a segment may span multiple buses or a bus may contain multiple segments and each segment may have different CCT
|
||||||
|
// we need to extract and appy CCT value for each pixel individually even though all buses share the same _cct variable
|
||||||
|
// TODO: there is an issue if CCT is calculated from RGB value (_cct==-1), we cannot do that with double buffer
|
||||||
|
Bus::_cct = _data[offset+channels-1];
|
||||||
|
Bus::calculateCCT(c, cctWW, cctCW);
|
||||||
}
|
}
|
||||||
uint16_t pix = i;
|
uint16_t pix = i;
|
||||||
if (_reversed) pix = _len - pix -1;
|
if (_reversed) pix = _len - pix -1;
|
||||||
pix += _skip;
|
pix += _skip;
|
||||||
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co);
|
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co, (cctCW<<8) | cctWW);
|
||||||
}
|
}
|
||||||
#if !defined(STATUSLED) || STATUSLED>=0
|
#if !defined(STATUSLED) || STATUSLED>=0
|
||||||
if (_skip) PolyBus::setPixelColor(_busPtr, _iType, 0, 0, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); // paint skipped pixels black
|
if (_skip) PolyBus::setPixelColor(_busPtr, _iType, 0, 0, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); // paint skipped pixels black
|
||||||
#endif
|
#endif
|
||||||
for (int i=1; i<_skip; i++) PolyBus::setPixelColor(_busPtr, _iType, i, 0, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); // paint skipped pixels black
|
for (int i=1; i<_skip; i++) PolyBus::setPixelColor(_busPtr, _iType, i, 0, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); // paint skipped pixels black
|
||||||
|
Bus::_cct = oldCCT;
|
||||||
} else {
|
} else {
|
||||||
if (newBri < _bri) {
|
if (newBri < _bri) {
|
||||||
uint16_t hwLen = _len;
|
uint16_t hwLen = _len;
|
||||||
@ -239,7 +251,8 @@ void BusDigital::show() {
|
|||||||
for (unsigned i = 0; i < hwLen; i++) {
|
for (unsigned i = 0; i < hwLen; i++) {
|
||||||
// use 0 as color order, actual order does not matter here as we just update the channel values as-is
|
// use 0 as color order, actual order does not matter here as we just update the channel values as-is
|
||||||
uint32_t c = restoreColorLossy(PolyBus::getPixelColor(_busPtr, _iType, i, 0), _bri);
|
uint32_t c = restoreColorLossy(PolyBus::getPixelColor(_busPtr, _iType, i, 0), _bri);
|
||||||
PolyBus::setPixelColor(_busPtr, _iType, i, c, 0); // repaint all pixels with new brightness
|
if (hasCCT()) Bus::calculateCCT(c, cctWW, cctCW); // this will unfortunately corrupt (segment) CCT data on every bus
|
||||||
|
PolyBus::setPixelColor(_busPtr, _iType, i, c, 0, (cctCW<<8) | cctWW); // repaint all pixels with new brightness
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -278,17 +291,20 @@ void BusDigital::setStatusPixel(uint32_t c) {
|
|||||||
|
|
||||||
void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) {
|
void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) {
|
||||||
if (!_valid) return;
|
if (!_valid) return;
|
||||||
if (Bus::hasWhite(_type)) c = autoWhiteCalc(c);
|
uint8_t cctWW = 0, cctCW = 0;
|
||||||
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
if (hasWhite()) c = autoWhiteCalc(c);
|
||||||
if (_data) { // use _buffering this causes ~20% FPS drop
|
if (Bus::_cct >= 1900) c = colorBalanceFromKelvin(Bus::_cct, c); //color correction from CCT
|
||||||
size_t channels = Bus::hasWhite(_type) + 3*Bus::hasRGB(_type);
|
if (_data) {
|
||||||
size_t offset = pix*channels;
|
size_t offset = pix * getNumberOfChannels();
|
||||||
if (Bus::hasRGB(_type)) {
|
if (hasRGB()) {
|
||||||
_data[offset++] = R(c);
|
_data[offset++] = R(c);
|
||||||
_data[offset++] = G(c);
|
_data[offset++] = G(c);
|
||||||
_data[offset++] = B(c);
|
_data[offset++] = B(c);
|
||||||
}
|
}
|
||||||
if (Bus::hasWhite(_type)) _data[offset] = W(c);
|
if (hasWhite()) _data[offset++] = W(c);
|
||||||
|
// unfortunately as a segment may span multiple buses or a bus may contain multiple segments and each segment may have different CCT
|
||||||
|
// we need to store CCT value for each pixel (if there is a color correction in play, convert K in CCT ratio)
|
||||||
|
if (hasCCT()) _data[offset] = Bus::_cct >= 1900 ? (Bus::_cct - 1900) >> 5 : (Bus::_cct < 0 ? 127 : Bus::_cct); // TODO: if _cct == -1 we simply ignore it
|
||||||
} else {
|
} else {
|
||||||
if (_reversed) pix = _len - pix -1;
|
if (_reversed) pix = _len - pix -1;
|
||||||
pix += _skip;
|
pix += _skip;
|
||||||
@ -303,21 +319,21 @@ void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) {
|
|||||||
case 2: c = RGBW32(R(cOld), G(cOld), W(c) , 0); break;
|
case 2: c = RGBW32(R(cOld), G(cOld), W(c) , 0); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co);
|
if (hasCCT()) Bus::calculateCCT(c, cctWW, cctCW);
|
||||||
|
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co, (cctCW<<8) | cctWW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns original color if global buffering is enabled, else returns lossly restored color from bus
|
// returns original color if global buffering is enabled, else returns lossly restored color from bus
|
||||||
uint32_t IRAM_ATTR BusDigital::getPixelColor(uint16_t pix) {
|
uint32_t IRAM_ATTR BusDigital::getPixelColor(uint16_t pix) {
|
||||||
if (!_valid) return 0;
|
if (!_valid) return 0;
|
||||||
if (_data) { // use _buffering this causes ~20% FPS drop
|
if (_data) {
|
||||||
size_t channels = Bus::hasWhite(_type) + 3*Bus::hasRGB(_type);
|
size_t offset = pix * getNumberOfChannels();
|
||||||
size_t offset = pix*channels;
|
|
||||||
uint32_t c;
|
uint32_t c;
|
||||||
if (!Bus::hasRGB(_type)) {
|
if (!hasRGB()) {
|
||||||
c = RGBW32(_data[offset], _data[offset], _data[offset], _data[offset]);
|
c = RGBW32(_data[offset], _data[offset], _data[offset], _data[offset]);
|
||||||
} else {
|
} else {
|
||||||
c = RGBW32(_data[offset], _data[offset+1], _data[offset+2], Bus::hasWhite(_type) ? _data[offset+3] : 0);
|
c = RGBW32(_data[offset], _data[offset+1], _data[offset+2], hasWhite() ? _data[offset+3] : 0);
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
} else {
|
} else {
|
||||||
@ -414,48 +430,31 @@ BusPwm::BusPwm(BusConfig &bc)
|
|||||||
void BusPwm::setPixelColor(uint16_t pix, uint32_t c) {
|
void BusPwm::setPixelColor(uint16_t pix, uint32_t c) {
|
||||||
if (pix != 0 || !_valid) return; //only react to first pixel
|
if (pix != 0 || !_valid) return; //only react to first pixel
|
||||||
if (_type != TYPE_ANALOG_3CH) c = autoWhiteCalc(c);
|
if (_type != TYPE_ANALOG_3CH) c = autoWhiteCalc(c);
|
||||||
if (_cct >= 1900 && (_type == TYPE_ANALOG_3CH || _type == TYPE_ANALOG_4CH)) {
|
if (Bus::_cct >= 1900 && (_type == TYPE_ANALOG_3CH || _type == TYPE_ANALOG_4CH)) {
|
||||||
c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
c = colorBalanceFromKelvin(Bus::_cct, c); //color correction from CCT
|
||||||
}
|
}
|
||||||
uint8_t r = R(c);
|
uint8_t r = R(c);
|
||||||
uint8_t g = G(c);
|
uint8_t g = G(c);
|
||||||
uint8_t b = B(c);
|
uint8_t b = B(c);
|
||||||
uint8_t w = W(c);
|
uint8_t w = W(c);
|
||||||
uint8_t cct = 0; //0 - full warm white, 255 - full cold white
|
|
||||||
if (_cct > -1) {
|
|
||||||
if (_cct >= 1900) cct = (_cct - 1900) >> 5;
|
|
||||||
else if (_cct < 256) cct = _cct;
|
|
||||||
} else {
|
|
||||||
cct = (approximateKelvinFromRGB(c) - 1900) >> 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t ww, cw;
|
|
||||||
#ifdef WLED_USE_IC_CCT
|
|
||||||
ww = w;
|
|
||||||
cw = cct;
|
|
||||||
#else
|
|
||||||
//0 - linear (CCT 127 = 50% warm, 50% cold), 127 - additive CCT blending (CCT 127 = 100% warm, 100% cold)
|
|
||||||
if (cct < _cctBlend) ww = 255;
|
|
||||||
else ww = ((255-cct) * 255) / (255 - _cctBlend);
|
|
||||||
|
|
||||||
if ((255-cct) < _cctBlend) cw = 255;
|
|
||||||
else cw = (cct * 255) / (255 - _cctBlend);
|
|
||||||
|
|
||||||
ww = (w * ww) / 255; //brightness scaling
|
|
||||||
cw = (w * cw) / 255;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case TYPE_ANALOG_1CH: //one channel (white), relies on auto white calculation
|
case TYPE_ANALOG_1CH: //one channel (white), relies on auto white calculation
|
||||||
_data[0] = w;
|
_data[0] = w;
|
||||||
break;
|
break;
|
||||||
case TYPE_ANALOG_2CH: //warm white + cold white
|
case TYPE_ANALOG_2CH: //warm white + cold white
|
||||||
_data[1] = cw;
|
if (cctICused) {
|
||||||
_data[0] = ww;
|
_data[0] = w;
|
||||||
|
_data[1] = Bus::_cct < 0 || Bus::_cct > 255 ? 127 : Bus::_cct;
|
||||||
|
} else {
|
||||||
|
Bus::calculateCCT(c, _data[0], _data[1]);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TYPE_ANALOG_5CH: //RGB + warm white + cold white
|
case TYPE_ANALOG_5CH: //RGB + warm white + cold white
|
||||||
_data[4] = cw;
|
if (cctICused)
|
||||||
w = ww;
|
_data[4] = Bus::_cct < 0 || Bus::_cct > 255 ? 127 : Bus::_cct;
|
||||||
|
else
|
||||||
|
Bus::calculateCCT(c, w, _data[4]);
|
||||||
case TYPE_ANALOG_4CH: //RGBW
|
case TYPE_ANALOG_4CH: //RGBW
|
||||||
_data[3] = w;
|
_data[3] = w;
|
||||||
case TYPE_ANALOG_3CH: //standard dumb RGB
|
case TYPE_ANALOG_3CH: //standard dumb RGB
|
||||||
@ -620,7 +619,7 @@ BusNetwork::BusNetwork(BusConfig &bc)
|
|||||||
void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
|
void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
|
||||||
if (!_valid || pix >= _len) return;
|
if (!_valid || pix >= _len) return;
|
||||||
if (_rgbw) c = autoWhiteCalc(c);
|
if (_rgbw) c = autoWhiteCalc(c);
|
||||||
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
if (Bus::_cct >= 1900) c = colorBalanceFromKelvin(Bus::_cct, c); //color correction from CCT
|
||||||
uint16_t offset = pix * _UDPchannels;
|
uint16_t offset = pix * _UDPchannels;
|
||||||
_data[offset] = R(c);
|
_data[offset] = R(c);
|
||||||
_data[offset+1] = G(c);
|
_data[offset+1] = G(c);
|
||||||
@ -660,25 +659,18 @@ uint32_t BusManager::memUsage(BusConfig &bc) {
|
|||||||
if (bc.type == TYPE_ONOFF || IS_PWM(bc.type)) return 5;
|
if (bc.type == TYPE_ONOFF || IS_PWM(bc.type)) return 5;
|
||||||
|
|
||||||
uint16_t len = bc.count + bc.skipAmount;
|
uint16_t len = bc.count + bc.skipAmount;
|
||||||
uint16_t channels = 3;
|
uint16_t channels = Bus::getNumberOfChannels(bc.type);
|
||||||
uint16_t multiplier = 1;
|
uint16_t multiplier = 1;
|
||||||
if (IS_DIGITAL(bc.type)) { // digital types
|
if (IS_DIGITAL(bc.type)) { // digital types
|
||||||
if (IS_16BIT(bc.type)) len *= 2; // 16-bit LEDs
|
if (IS_16BIT(bc.type)) len *= 2; // 16-bit LEDs
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
if (bc.type > 28) channels = 4; //RGBW
|
|
||||||
if (bc.pins[0] == 3) { //8266 DMA uses 5x the mem
|
if (bc.pins[0] == 3) { //8266 DMA uses 5x the mem
|
||||||
multiplier = 5;
|
multiplier = 5;
|
||||||
}
|
}
|
||||||
#else //ESP32 RMT uses double buffer, I2S uses 5x buffer
|
#else //ESP32 RMT uses double buffer, I2S uses 5x buffer
|
||||||
if (bc.type > 28) channels = 4; //RGBW
|
|
||||||
multiplier = 2;
|
multiplier = 2;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (IS_VIRTUAL(bc.type)) {
|
|
||||||
switch (bc.type) {
|
|
||||||
case TYPE_NET_DDP_RGBW: channels = 4; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return len * channels * multiplier; //RGB
|
return len * channels * multiplier; //RGB
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -740,7 +732,7 @@ void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) {
|
|||||||
if (cct >= 0) {
|
if (cct >= 0) {
|
||||||
//if white balance correction allowed, save as kelvin value instead of 0-255
|
//if white balance correction allowed, save as kelvin value instead of 0-255
|
||||||
if (allowWBCorrection) cct = 1900 + (cct << 5);
|
if (allowWBCorrection) cct = 1900 + (cct << 5);
|
||||||
} else cct = -1;
|
} else cct = -1; // will use kelvin approximation from RGB
|
||||||
Bus::setCCT(cct);
|
Bus::setCCT(cct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
|
|
||||||
#include "const.h"
|
#include "const.h"
|
||||||
|
|
||||||
|
//colors.cpp
|
||||||
|
uint16_t approximateKelvinFromRGB(uint32_t rgb);
|
||||||
|
|
||||||
#define GET_BIT(var,bit) (((var)>>(bit))&0x01)
|
#define GET_BIT(var,bit) (((var)>>(bit))&0x01)
|
||||||
#define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit)))
|
#define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit)))
|
||||||
#define UNSET_BIT(var,bit) ((var)&=(~(uint16_t)(0x0001<<(bit))))
|
#define UNSET_BIT(var,bit) ((var)&=(~(uint16_t)(0x0001<<(bit))))
|
||||||
@ -32,7 +35,7 @@ struct BusConfig {
|
|||||||
uint8_t skipAmount;
|
uint8_t skipAmount;
|
||||||
bool refreshReq;
|
bool refreshReq;
|
||||||
uint8_t autoWhite;
|
uint8_t autoWhite;
|
||||||
uint8_t pins[5] = {LEDPIN, 255, 255, 255, 255};
|
uint8_t pins[5] = {255, 255, 255, 255, 255};
|
||||||
uint16_t frequency;
|
uint16_t frequency;
|
||||||
bool doubleBuffer;
|
bool doubleBuffer;
|
||||||
uint8_t milliAmpsPerLed;
|
uint8_t milliAmpsPerLed;
|
||||||
@ -53,9 +56,9 @@ struct BusConfig {
|
|||||||
refreshReq = (bool) GET_BIT(busType,7);
|
refreshReq = (bool) GET_BIT(busType,7);
|
||||||
type = busType & 0x7F; // bit 7 may be/is hacked to include refresh info (1=refresh in off state, 0=no refresh)
|
type = busType & 0x7F; // bit 7 may be/is hacked to include refresh info (1=refresh in off state, 0=no refresh)
|
||||||
size_t nPins = 1;
|
size_t nPins = 1;
|
||||||
if (type >= TYPE_NET_DDP_RGB && type < 96) nPins = 4; //virtual network bus. 4 "pins" store IP address
|
if (IS_VIRTUAL(type)) nPins = 4; //virtual network bus. 4 "pins" store IP address
|
||||||
else if (type > 47) nPins = 2;
|
else if (IS_2PIN(type)) nPins = 2;
|
||||||
else if (type > 40 && type < 46) nPins = NUM_PWM_PINS(type);
|
else if (IS_PWM(type)) nPins = NUM_PWM_PINS(type);
|
||||||
for (size_t i = 0; i < nPins; i++) pins[i] = ppins[i];
|
for (size_t i = 0; i < nPins; i++) pins[i] = ppins[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +141,8 @@ class Bus {
|
|||||||
virtual uint16_t getLEDCurrent() { return 0; }
|
virtual uint16_t getLEDCurrent() { return 0; }
|
||||||
virtual uint16_t getUsedCurrent() { return 0; }
|
virtual uint16_t getUsedCurrent() { return 0; }
|
||||||
virtual uint16_t getMaxCurrent() { return 0; }
|
virtual uint16_t getMaxCurrent() { return 0; }
|
||||||
|
virtual uint8_t getNumberOfChannels() { return hasWhite(_type) + 3*hasRGB(_type) + hasCCT(_type); }
|
||||||
|
static inline uint8_t getNumberOfChannels(uint8_t type) { return hasWhite(type) + 3*hasRGB(type) + hasCCT(type); }
|
||||||
inline void setReversed(bool reversed) { _reversed = reversed; }
|
inline void setReversed(bool reversed) { _reversed = reversed; }
|
||||||
inline uint16_t getStart() { return _start; }
|
inline uint16_t getStart() { return _start; }
|
||||||
inline void setStart(uint16_t start) { _start = start; }
|
inline void setStart(uint16_t start) { _start = start; }
|
||||||
@ -154,18 +159,22 @@ class Bus {
|
|||||||
}
|
}
|
||||||
virtual bool hasWhite(void) { return Bus::hasWhite(_type); }
|
virtual bool hasWhite(void) { return Bus::hasWhite(_type); }
|
||||||
static bool hasWhite(uint8_t type) {
|
static bool hasWhite(uint8_t type) {
|
||||||
if ((type >= TYPE_WS2812_1CH && type <= TYPE_WS2812_WWA) || type == TYPE_SK6812_RGBW || type == TYPE_TM1814 || type == TYPE_UCS8904) return true; // digital types with white channel
|
if ((type >= TYPE_WS2812_1CH && type <= TYPE_WS2812_WWA) ||
|
||||||
|
type == TYPE_SK6812_RGBW || type == TYPE_TM1814 || type == TYPE_UCS8904 ||
|
||||||
|
type == TYPE_FW1906 || type == TYPE_WS2805) return true; // digital types with white channel
|
||||||
if (type > TYPE_ONOFF && type <= TYPE_ANALOG_5CH && type != TYPE_ANALOG_3CH) return true; // analog types with white channel
|
if (type > TYPE_ONOFF && type <= TYPE_ANALOG_5CH && type != TYPE_ANALOG_3CH) return true; // analog types with white channel
|
||||||
if (type == TYPE_NET_DDP_RGBW) return true; // network types with white channel
|
if (type == TYPE_NET_DDP_RGBW || type == TYPE_NET_ARTNET_RGBW) return true; // network types with white channel
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual bool hasCCT(void) { return Bus::hasCCT(_type); }
|
virtual bool hasCCT(void) { return Bus::hasCCT(_type); }
|
||||||
static bool hasCCT(uint8_t type) {
|
static bool hasCCT(uint8_t type) {
|
||||||
if (type == TYPE_WS2812_2CH_X3 || type == TYPE_WS2812_WWA ||
|
if (type == TYPE_WS2812_2CH_X3 || type == TYPE_WS2812_WWA ||
|
||||||
type == TYPE_ANALOG_2CH || type == TYPE_ANALOG_5CH) return true;
|
type == TYPE_ANALOG_2CH || type == TYPE_ANALOG_5CH ||
|
||||||
|
type == TYPE_FW1906 || type == TYPE_WS2805 ) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static void setCCT(uint16_t cct) {
|
static int16_t getCCT() { return _cct; }
|
||||||
|
static void setCCT(int16_t cct) {
|
||||||
_cct = cct;
|
_cct = cct;
|
||||||
}
|
}
|
||||||
static void setCCTBlend(uint8_t b) {
|
static void setCCTBlend(uint8_t b) {
|
||||||
@ -176,6 +185,26 @@ class Bus {
|
|||||||
if (_cctBlend > WLED_MAX_CCT_BLEND) _cctBlend = WLED_MAX_CCT_BLEND;
|
if (_cctBlend > WLED_MAX_CCT_BLEND) _cctBlend = WLED_MAX_CCT_BLEND;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
static void calculateCCT(uint32_t c, uint8_t &ww, uint8_t &cw) {
|
||||||
|
uint8_t cct = 0; //0 - full warm white, 255 - full cold white
|
||||||
|
uint8_t w = byte(c >> 24);
|
||||||
|
|
||||||
|
if (_cct > -1) {
|
||||||
|
if (_cct >= 1900) cct = (_cct - 1900) >> 5;
|
||||||
|
else if (_cct < 256) cct = _cct;
|
||||||
|
} else {
|
||||||
|
cct = (approximateKelvinFromRGB(c) - 1900) >> 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
//0 - linear (CCT 127 = 50% warm, 50% cold), 127 - additive CCT blending (CCT 127 = 100% warm, 100% cold)
|
||||||
|
if (cct < _cctBlend) ww = 255;
|
||||||
|
else ww = ((255-cct) * 255) / (255 - _cctBlend);
|
||||||
|
if ((255-cct) < _cctBlend) cw = 255;
|
||||||
|
else cw = (cct * 255) / (255 - _cctBlend);
|
||||||
|
|
||||||
|
ww = (w * ww) / 255; //brightness scaling
|
||||||
|
cw = (w * cw) / 255;
|
||||||
|
}
|
||||||
inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; }
|
inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; }
|
||||||
inline uint8_t getAutoWhiteMode() { return _autoWhiteMode; }
|
inline uint8_t getAutoWhiteMode() { return _autoWhiteMode; }
|
||||||
inline static void setGlobalAWMode(uint8_t m) { if (m < 5) _gAWM = m; else _gAWM = AW_GLOBAL_DISABLED; }
|
inline static void setGlobalAWMode(uint8_t m) { if (m < 5) _gAWM = m; else _gAWM = AW_GLOBAL_DISABLED; }
|
||||||
@ -191,8 +220,17 @@ class Bus {
|
|||||||
bool _needsRefresh;
|
bool _needsRefresh;
|
||||||
uint8_t _autoWhiteMode;
|
uint8_t _autoWhiteMode;
|
||||||
uint8_t *_data;
|
uint8_t *_data;
|
||||||
|
// global Auto White Calculation override
|
||||||
static uint8_t _gAWM;
|
static uint8_t _gAWM;
|
||||||
|
// _cct has the following menaings (see calculateCCT() & BusManager::setSegmentCCT()):
|
||||||
|
// -1 means to extract approximate CCT value in K from RGB (in calcualteCCT())
|
||||||
|
// [0,255] is the exact CCT value where 0 means warm and 255 cold
|
||||||
|
// [1900,10060] only for color correction expressed in K (colorBalanceFromKelvin())
|
||||||
static int16_t _cct;
|
static int16_t _cct;
|
||||||
|
// _cctBlend determines WW/CW blending:
|
||||||
|
// 0 - linear (CCT 127 => 50% warm, 50% cold)
|
||||||
|
// 63 - semi additive/nonlinear (CCT 127 => 66% warm, 66% cold)
|
||||||
|
// 127 - additive CCT blending (CCT 127 => 100% warm, 100% cold)
|
||||||
static uint8_t _cctBlend;
|
static uint8_t _cctBlend;
|
||||||
|
|
||||||
uint32_t autoWhiteCalc(uint32_t c);
|
uint32_t autoWhiteCalc(uint32_t c);
|
||||||
@ -334,9 +372,12 @@ class BusManager {
|
|||||||
static void setStatusPixel(uint32_t c);
|
static void setStatusPixel(uint32_t c);
|
||||||
static void setPixelColor(uint16_t pix, uint32_t c);
|
static void setPixelColor(uint16_t pix, uint32_t c);
|
||||||
static void setBrightness(uint8_t b);
|
static void setBrightness(uint8_t b);
|
||||||
|
// for setSegmentCCT(), cct can only be in [-1,255] range; allowWBCorrection will convert it to K
|
||||||
|
// WARNING: setSegmentCCT() is a misleading name!!! much better would be setGlobalCCT() or just setCCT()
|
||||||
static void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
|
static void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
|
||||||
static void setMilliampsMax(uint16_t max) { _milliAmpsMax = max;}
|
static void setMilliampsMax(uint16_t max) { _milliAmpsMax = max;}
|
||||||
static uint32_t getPixelColor(uint16_t pix);
|
static uint32_t getPixelColor(uint16_t pix);
|
||||||
|
static inline int16_t getSegmentCCT() { return Bus::getCCT(); }
|
||||||
|
|
||||||
static Bus* getBus(uint8_t busNr);
|
static Bus* getBus(uint8_t busNr);
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define BusWrapper_h
|
#define BusWrapper_h
|
||||||
|
|
||||||
#include "NeoPixelBusLg.h"
|
#include "NeoPixelBusLg.h"
|
||||||
|
#include "bus_manager.h"
|
||||||
|
|
||||||
// temporary - these defines should actually be set in platformio.ini
|
// temporary - these defines should actually be set in platformio.ini
|
||||||
// C3: I2S0 and I2S1 methods not supported (has one I2S bus)
|
// C3: I2S0 and I2S1 methods not supported (has one I2S bus)
|
||||||
@ -63,52 +64,64 @@
|
|||||||
#define I_8266_U1_UCS_4 54
|
#define I_8266_U1_UCS_4 54
|
||||||
#define I_8266_DM_UCS_4 55
|
#define I_8266_DM_UCS_4 55
|
||||||
#define I_8266_BB_UCS_4 56
|
#define I_8266_BB_UCS_4 56
|
||||||
|
//FW1906 GRBCW
|
||||||
|
#define I_8266_U0_FW6_5 66
|
||||||
|
#define I_8266_U1_FW6_5 67
|
||||||
|
#define I_8266_DM_FW6_5 68
|
||||||
|
#define I_8266_BB_FW6_5 69
|
||||||
//ESP8266 APA106
|
//ESP8266 APA106
|
||||||
#define I_8266_U0_APA106_3 81
|
#define I_8266_U0_APA106_3 81
|
||||||
#define I_8266_U1_APA106_3 82
|
#define I_8266_U1_APA106_3 82
|
||||||
#define I_8266_DM_APA106_3 83
|
#define I_8266_DM_APA106_3 83
|
||||||
#define I_8266_BB_APA106_3 84
|
#define I_8266_BB_APA106_3 84
|
||||||
|
//WS2805
|
||||||
|
#define I_8266_U0_2805_5 89
|
||||||
|
#define I_8266_U1_2805_5 90
|
||||||
|
#define I_8266_DM_2805_5 91
|
||||||
|
#define I_8266_BB_2805_5 92
|
||||||
|
|
||||||
/*** ESP32 Neopixel methods ***/
|
/*** ESP32 Neopixel methods ***/
|
||||||
//RGB
|
//RGB
|
||||||
#define I_32_RN_NEO_3 21
|
#define I_32_RN_NEO_3 21
|
||||||
#define I_32_I0_NEO_3 22
|
#define I_32_I0_NEO_3 22
|
||||||
#define I_32_I1_NEO_3 23
|
#define I_32_I1_NEO_3 23
|
||||||
#define I_32_BB_NEO_3 24 // bitbanging on ESP32 not recommended
|
|
||||||
//RGBW
|
//RGBW
|
||||||
#define I_32_RN_NEO_4 25
|
#define I_32_RN_NEO_4 25
|
||||||
#define I_32_I0_NEO_4 26
|
#define I_32_I0_NEO_4 26
|
||||||
#define I_32_I1_NEO_4 27
|
#define I_32_I1_NEO_4 27
|
||||||
#define I_32_BB_NEO_4 28 // bitbanging on ESP32 not recommended
|
|
||||||
//400Kbps
|
//400Kbps
|
||||||
#define I_32_RN_400_3 29
|
#define I_32_RN_400_3 29
|
||||||
#define I_32_I0_400_3 30
|
#define I_32_I0_400_3 30
|
||||||
#define I_32_I1_400_3 31
|
#define I_32_I1_400_3 31
|
||||||
#define I_32_BB_400_3 32 // bitbanging on ESP32 not recommended
|
|
||||||
//TM1814 (RGBW)
|
//TM1814 (RGBW)
|
||||||
#define I_32_RN_TM1_4 33
|
#define I_32_RN_TM1_4 33
|
||||||
#define I_32_I0_TM1_4 34
|
#define I_32_I0_TM1_4 34
|
||||||
#define I_32_I1_TM1_4 35
|
#define I_32_I1_TM1_4 35
|
||||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
|
||||||
//TM1829 (RGB)
|
//TM1829 (RGB)
|
||||||
#define I_32_RN_TM2_3 36
|
#define I_32_RN_TM2_3 36
|
||||||
#define I_32_I0_TM2_3 37
|
#define I_32_I0_TM2_3 37
|
||||||
#define I_32_I1_TM2_3 38
|
#define I_32_I1_TM2_3 38
|
||||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
|
||||||
//UCS8903 (RGB)
|
//UCS8903 (RGB)
|
||||||
#define I_32_RN_UCS_3 57
|
#define I_32_RN_UCS_3 57
|
||||||
#define I_32_I0_UCS_3 58
|
#define I_32_I0_UCS_3 58
|
||||||
#define I_32_I1_UCS_3 59
|
#define I_32_I1_UCS_3 59
|
||||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
|
||||||
//UCS8904 (RGBW)
|
//UCS8904 (RGBW)
|
||||||
#define I_32_RN_UCS_4 60
|
#define I_32_RN_UCS_4 60
|
||||||
#define I_32_I0_UCS_4 61
|
#define I_32_I0_UCS_4 61
|
||||||
#define I_32_I1_UCS_4 62
|
#define I_32_I1_UCS_4 62
|
||||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
//FW1906 GRBCW
|
||||||
|
#define I_32_RN_FW6_5 63
|
||||||
|
#define I_32_I0_FW6_5 64
|
||||||
|
#define I_32_I1_FW6_5 65
|
||||||
|
//APA106
|
||||||
#define I_32_RN_APA106_3 85
|
#define I_32_RN_APA106_3 85
|
||||||
#define I_32_I0_APA106_3 86
|
#define I_32_I0_APA106_3 86
|
||||||
#define I_32_I1_APA106_3 87
|
#define I_32_I1_APA106_3 87
|
||||||
#define I_32_BB_APA106_3 88 // bitbangging on ESP32 not recommended
|
//WS2805
|
||||||
|
#define I_32_RN_2805_5 93
|
||||||
|
#define I_32_I0_2805_5 94
|
||||||
|
#define I_32_I1_2805_5 95
|
||||||
|
|
||||||
|
|
||||||
//APA102
|
//APA102
|
||||||
#define I_HS_DOT_3 39 //hardware SPI
|
#define I_HS_DOT_3 39 //hardware SPI
|
||||||
@ -176,6 +189,16 @@
|
|||||||
#define B_8266_U1_APA106_3 NeoPixelBusLg<NeoRbgFeature, NeoEsp8266Uart1Apa106Method, NeoGammaNullMethod> //3 chan, esp8266, gpio2
|
#define B_8266_U1_APA106_3 NeoPixelBusLg<NeoRbgFeature, NeoEsp8266Uart1Apa106Method, NeoGammaNullMethod> //3 chan, esp8266, gpio2
|
||||||
#define B_8266_DM_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266DmaApa106Method, NeoGammaNullMethod> //3 chan, esp8266, gpio3
|
#define B_8266_DM_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266DmaApa106Method, NeoGammaNullMethod> //3 chan, esp8266, gpio3
|
||||||
#define B_8266_BB_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266BitBangApa106Method, NeoGammaNullMethod> //3 chan, esp8266, bb (any pin but 16)
|
#define B_8266_BB_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266BitBangApa106Method, NeoGammaNullMethod> //3 chan, esp8266, bb (any pin but 16)
|
||||||
|
//FW1906 GRBCW
|
||||||
|
#define B_8266_U0_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp8266Uart0Ws2813Method, NeoGammaNullMethod> //esp8266, gpio1
|
||||||
|
#define B_8266_U1_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp8266Uart1Ws2813Method, NeoGammaNullMethod> //esp8266, gpio2
|
||||||
|
#define B_8266_DM_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp8266Dma800KbpsMethod, NeoGammaNullMethod> //esp8266, gpio3
|
||||||
|
#define B_8266_BB_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp8266BitBang800KbpsMethod, NeoGammaNullMethod> //esp8266, bb
|
||||||
|
//WS2805 GRBCW
|
||||||
|
#define B_8266_U0_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp8266Uart0Ws2805Method, NeoGammaNullMethod> //esp8266, gpio1
|
||||||
|
#define B_8266_U1_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp8266Uart1Ws2805Method, NeoGammaNullMethod> //esp8266, gpio2
|
||||||
|
#define B_8266_DM_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp8266DmaWs2805Method, NeoGammaNullMethod> //esp8266, gpio3
|
||||||
|
#define B_8266_BB_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp8266BitBangWs2805Method, NeoGammaNullMethod> //esp8266, bb
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*** ESP32 Neopixel methods ***/
|
/*** ESP32 Neopixel methods ***/
|
||||||
@ -183,75 +206,102 @@
|
|||||||
//RGB
|
//RGB
|
||||||
#define B_32_RN_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
|
#define B_32_RN_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
#define B_32_I0_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod>
|
#define B_32_I0_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0Ws2812xMethod, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I0_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0X8Ws2812xMethod, NeoGammaNullMethod> // parallel I2S
|
||||||
#endif
|
#endif
|
||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
#define B_32_I1_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
|
#define B_32_I1_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1Ws2812xMethod, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I1_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1X8Ws2812xMethod, NeoGammaNullMethod> // parallel I2S
|
||||||
#endif
|
#endif
|
||||||
//#define B_32_BB_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32BitBang800KbpsMethod, NeoGammaNullMethod> // NeoEsp8266BitBang800KbpsMethod
|
|
||||||
//RGBW
|
//RGBW
|
||||||
#define B_32_RN_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
|
#define B_32_RN_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32RmtNSk6812Method, NeoGammaNullMethod>
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
#define B_32_I0_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod>
|
#define B_32_I0_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s0Sk6812Method, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I0_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s0X8Sk6812Method, NeoGammaNullMethod> // parallel I2S
|
||||||
#endif
|
#endif
|
||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
#define B_32_I1_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
|
#define B_32_I1_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s1Sk6812Method, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I1_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s1X8Sk6812Method, NeoGammaNullMethod> // parallel I2S
|
||||||
#endif
|
#endif
|
||||||
//#define B_32_BB_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32BitBang800KbpsMethod, NeoGammaNullMethod> // NeoEsp8266BitBang800KbpsMethod
|
|
||||||
//400Kbps
|
//400Kbps
|
||||||
#define B_32_RN_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtN400KbpsMethod, NeoGammaNullMethod>
|
#define B_32_RN_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtN400KbpsMethod, NeoGammaNullMethod>
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
#define B_32_I0_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0400KbpsMethod, NeoGammaNullMethod>
|
#define B_32_I0_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0400KbpsMethod, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I0_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0X8400KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||||
#endif
|
#endif
|
||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
#define B_32_I1_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1400KbpsMethod, NeoGammaNullMethod>
|
#define B_32_I1_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1400KbpsMethod, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I1_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1X8400KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||||
#endif
|
#endif
|
||||||
//#define B_32_BB_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32BitBang400KbpsMethod, NeoGammaNullMethod> // NeoEsp8266BitBang400KbpsMethod
|
|
||||||
//TM1814 (RGBW)
|
//TM1814 (RGBW)
|
||||||
#define B_32_RN_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32RmtNTm1814Method, NeoGammaNullMethod>
|
#define B_32_RN_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32RmtNTm1814Method, NeoGammaNullMethod>
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
#define B_32_I0_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s0Tm1814Method, NeoGammaNullMethod>
|
#define B_32_I0_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s0Tm1814Method, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I0_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s0X8Tm1814Method, NeoGammaNullMethod> // parallel I2S
|
||||||
#endif
|
#endif
|
||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
#define B_32_I1_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s1Tm1814Method, NeoGammaNullMethod>
|
#define B_32_I1_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s1Tm1814Method, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I1_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s1X8Tm1814Method, NeoGammaNullMethod> // parallel I2S
|
||||||
#endif
|
#endif
|
||||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
|
||||||
//TM1829 (RGB)
|
//TM1829 (RGB)
|
||||||
#define B_32_RN_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32RmtNTm1829Method, NeoGammaNullMethod>
|
#define B_32_RN_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32RmtNTm1829Method, NeoGammaNullMethod>
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
#define B_32_I0_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s0Tm1829Method, NeoGammaNullMethod>
|
#define B_32_I0_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s0Tm1829Method, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I0_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s0X8Tm1829Method, NeoGammaNullMethod> // parallel I2S
|
||||||
#endif
|
#endif
|
||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
#define B_32_I1_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s1Tm1829Method, NeoGammaNullMethod>
|
#define B_32_I1_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s1Tm1829Method, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I1_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s1X8Tm1829Method, NeoGammaNullMethod> // parallel I2S
|
||||||
#endif
|
#endif
|
||||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
|
||||||
//UCS8903
|
//UCS8903
|
||||||
#define B_32_RN_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
|
#define B_32_RN_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
#define B_32_I0_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod>
|
#define B_32_I0_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I0_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s0X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||||
#endif
|
#endif
|
||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
#define B_32_I1_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
|
#define B_32_I1_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I1_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s1X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||||
#endif
|
#endif
|
||||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
|
||||||
//UCS8904
|
//UCS8904
|
||||||
#define B_32_RN_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
|
#define B_32_RN_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
#define B_32_I0_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod>
|
#define B_32_I0_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I0_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s0X8800KbpsMethod, NeoGammaNullMethod>// parallel I2S
|
||||||
#endif
|
#endif
|
||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
#define B_32_I1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
|
#define B_32_I1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s1X8800KbpsMethod, NeoGammaNullMethod>// parallel I2S
|
||||||
#endif
|
#endif
|
||||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
|
||||||
#define B_32_RN_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtNApa106Method, NeoGammaNullMethod>
|
#define B_32_RN_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtNApa106Method, NeoGammaNullMethod>
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
#define B_32_I0_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0Apa106Method, NeoGammaNullMethod>
|
#define B_32_I0_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0Apa106Method, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I0_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0X8Apa106Method, NeoGammaNullMethod> // parallel I2S
|
||||||
#endif
|
#endif
|
||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
#define B_32_I1_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1Apa106Method, NeoGammaNullMethod>
|
#define B_32_I1_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1Apa106Method, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I1_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1X8Apa106Method, NeoGammaNullMethod> // parallel I2S
|
||||||
|
#endif
|
||||||
|
//FW1906 GRBCW
|
||||||
|
#define B_32_RN_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
#define B_32_I0_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32I2s0800KbpsMethod, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I0_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32I2s0X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
#define B_32_I1_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I1_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32I2s1X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||||
|
#endif
|
||||||
|
//WS2805 RGBWC
|
||||||
|
#define B_32_RN_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32RmtNWs2805Method, NeoGammaNullMethod>
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
#define B_32_I0_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32I2s0Ws2805Method, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I0_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32I2s0X8Ws2805Method, NeoGammaNullMethod> // parallel I2S
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
#define B_32_I1_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32I2s1Ws2805Method, NeoGammaNullMethod>
|
||||||
|
//#define B_32_I1_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32I2s1X8Ws2805Method, NeoGammaNullMethod> // parallel I2S
|
||||||
#endif
|
#endif
|
||||||
//#define B_32_BB_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266BitBangApa106Method, NeoGammaNullMethod> // NeoEsp8266BitBang800KbpsMethod
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//APA102
|
//APA102
|
||||||
@ -290,6 +340,7 @@
|
|||||||
//handles pointer type conversion for all possible bus types
|
//handles pointer type conversion for all possible bus types
|
||||||
class PolyBus {
|
class PolyBus {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// initialize SPI bus speed for DotStar methods
|
// initialize SPI bus speed for DotStar methods
|
||||||
template <class T>
|
template <class T>
|
||||||
static void beginDotStar(void* busPtr, int8_t sck, int8_t miso, int8_t mosi, int8_t ss, uint16_t clock_kHz = 0U) {
|
static void beginDotStar(void* busPtr, int8_t sck, int8_t miso, int8_t mosi, int8_t ss, uint16_t clock_kHz = 0U) {
|
||||||
@ -353,6 +404,14 @@ class PolyBus {
|
|||||||
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->Begin(); break;
|
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->Begin(); break;
|
||||||
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->Begin(); break;
|
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->Begin(); break;
|
||||||
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->Begin(); break;
|
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->Begin(); break;
|
||||||
|
case I_8266_U0_FW6_5: (static_cast<B_8266_U0_FW6_5*>(busPtr))->Begin(); break;
|
||||||
|
case I_8266_U1_FW6_5: (static_cast<B_8266_U1_FW6_5*>(busPtr))->Begin(); break;
|
||||||
|
case I_8266_DM_FW6_5: (static_cast<B_8266_DM_FW6_5*>(busPtr))->Begin(); break;
|
||||||
|
case I_8266_BB_FW6_5: (static_cast<B_8266_BB_FW6_5*>(busPtr))->Begin(); break;
|
||||||
|
case I_8266_U0_2805_5: (static_cast<B_8266_U0_2805_5*>(busPtr))->Begin(); break;
|
||||||
|
case I_8266_U1_2805_5: (static_cast<B_8266_U1_2805_5*>(busPtr))->Begin(); break;
|
||||||
|
case I_8266_DM_2805_5: (static_cast<B_8266_DM_2805_5*>(busPtr))->Begin(); break;
|
||||||
|
case I_8266_BB_2805_5: (static_cast<B_8266_BB_2805_5*>(busPtr))->Begin(); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Begin(); break;
|
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Begin(); break;
|
||||||
@ -362,7 +421,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->Begin(); break;
|
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->Begin(); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_3: (static_cast<B_32_BB_NEO_3*>(busPtr))->Begin(); break;
|
|
||||||
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->Begin(); break;
|
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->Begin(); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->Begin(); break;
|
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->Begin(); break;
|
||||||
@ -370,7 +428,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->Begin(); break;
|
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->Begin(); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_4: (static_cast<B_32_BB_NEO_4*>(busPtr))->Begin(); break;
|
|
||||||
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->Begin(); break;
|
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->Begin(); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->Begin(); break;
|
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->Begin(); break;
|
||||||
@ -378,7 +435,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Begin(); break;
|
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Begin(); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_400_3: (static_cast<B_32_BB_400_3*>(busPtr))->Begin(); break;
|
|
||||||
case I_32_RN_TM1_4: beginTM1814<B_32_RN_TM1_4*>(busPtr); break;
|
case I_32_RN_TM1_4: beginTM1814<B_32_RN_TM1_4*>(busPtr); break;
|
||||||
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->Begin(); break;
|
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->Begin(); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
@ -396,7 +452,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->Begin(); break;
|
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->Begin(); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_3: (static_cast<B_32_BB_UCS_3*>(busPtr))->Begin(); break;
|
|
||||||
case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->Begin(); break;
|
case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->Begin(); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->Begin(); break;
|
case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->Begin(); break;
|
||||||
@ -404,7 +459,13 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Begin(); break;
|
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Begin(); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->Begin(); break;
|
case I_32_RN_FW6_5: (static_cast<B_32_RN_FW6_5*>(busPtr))->Begin(); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_FW6_5: (static_cast<B_32_I0_FW6_5*>(busPtr))->Begin(); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_FW6_5: (static_cast<B_32_I1_FW6_5*>(busPtr))->Begin(); break;
|
||||||
|
#endif
|
||||||
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->Begin(); break;
|
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->Begin(); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->Begin(); break;
|
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->Begin(); break;
|
||||||
@ -412,7 +473,13 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->Begin(); break;
|
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->Begin(); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->Begin(); break;
|
case I_32_RN_2805_5: (static_cast<B_32_RN_2805_5*>(busPtr))->Begin(); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_2805_5: (static_cast<B_32_I0_2805_5*>(busPtr))->Begin(); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_2805_5: (static_cast<B_32_I1_2805_5*>(busPtr))->Begin(); break;
|
||||||
|
#endif
|
||||||
// ESP32 can (and should, to avoid inadvertantly driving the chip select signal) specify the pins used for SPI, but only in begin()
|
// ESP32 can (and should, to avoid inadvertantly driving the chip select signal) specify the pins used for SPI, but only in begin()
|
||||||
case I_HS_DOT_3: beginDotStar<B_HS_DOT_3*>(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break;
|
case I_HS_DOT_3: beginDotStar<B_HS_DOT_3*>(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break;
|
||||||
case I_HS_LPD_3: beginDotStar<B_HS_LPD_3*>(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break;
|
case I_HS_LPD_3: beginDotStar<B_HS_LPD_3*>(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break;
|
||||||
@ -465,6 +532,14 @@ class PolyBus {
|
|||||||
case I_8266_U1_APA106_3: busPtr = new B_8266_U1_APA106_3(len, pins[0]); break;
|
case I_8266_U1_APA106_3: busPtr = new B_8266_U1_APA106_3(len, pins[0]); break;
|
||||||
case I_8266_DM_APA106_3: busPtr = new B_8266_DM_APA106_3(len, pins[0]); break;
|
case I_8266_DM_APA106_3: busPtr = new B_8266_DM_APA106_3(len, pins[0]); break;
|
||||||
case I_8266_BB_APA106_3: busPtr = new B_8266_BB_APA106_3(len, pins[0]); break;
|
case I_8266_BB_APA106_3: busPtr = new B_8266_BB_APA106_3(len, pins[0]); break;
|
||||||
|
case I_8266_U0_FW6_5: busPtr = new B_8266_U0_FW6_5(len, pins[0]); break;
|
||||||
|
case I_8266_U1_FW6_5: busPtr = new B_8266_U1_FW6_5(len, pins[0]); break;
|
||||||
|
case I_8266_DM_FW6_5: busPtr = new B_8266_DM_FW6_5(len, pins[0]); break;
|
||||||
|
case I_8266_BB_FW6_5: busPtr = new B_8266_BB_FW6_5(len, pins[0]); break;
|
||||||
|
case I_8266_U0_2805_5: busPtr = new B_8266_U0_2805_5(len, pins[0]); break;
|
||||||
|
case I_8266_U1_2805_5: busPtr = new B_8266_U1_2805_5(len, pins[0]); break;
|
||||||
|
case I_8266_DM_2805_5: busPtr = new B_8266_DM_2805_5(len, pins[0]); break;
|
||||||
|
case I_8266_BB_2805_5: busPtr = new B_8266_BB_2805_5(len, pins[0]); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: busPtr = new B_32_RN_NEO_3(len, pins[0], (NeoBusChannel)channel); break;
|
case I_32_RN_NEO_3: busPtr = new B_32_RN_NEO_3(len, pins[0], (NeoBusChannel)channel); break;
|
||||||
@ -474,7 +549,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_3: busPtr = new B_32_I1_NEO_3(len, pins[0]); break;
|
case I_32_I1_NEO_3: busPtr = new B_32_I1_NEO_3(len, pins[0]); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_3: busPtr = new B_32_BB_NEO_3(len, pins[0], (NeoBusChannel)channel); break;
|
|
||||||
case I_32_RN_NEO_4: busPtr = new B_32_RN_NEO_4(len, pins[0], (NeoBusChannel)channel); break;
|
case I_32_RN_NEO_4: busPtr = new B_32_RN_NEO_4(len, pins[0], (NeoBusChannel)channel); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_NEO_4: busPtr = new B_32_I0_NEO_4(len, pins[0]); break;
|
case I_32_I0_NEO_4: busPtr = new B_32_I0_NEO_4(len, pins[0]); break;
|
||||||
@ -482,7 +556,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_4: busPtr = new B_32_I1_NEO_4(len, pins[0]); break;
|
case I_32_I1_NEO_4: busPtr = new B_32_I1_NEO_4(len, pins[0]); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_4: busPtr = new B_32_BB_NEO_4(len, pins[0], (NeoBusChannel)channel); break;
|
|
||||||
case I_32_RN_400_3: busPtr = new B_32_RN_400_3(len, pins[0], (NeoBusChannel)channel); break;
|
case I_32_RN_400_3: busPtr = new B_32_RN_400_3(len, pins[0], (NeoBusChannel)channel); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_400_3: busPtr = new B_32_I0_400_3(len, pins[0]); break;
|
case I_32_I0_400_3: busPtr = new B_32_I0_400_3(len, pins[0]); break;
|
||||||
@ -490,7 +563,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_400_3: busPtr = new B_32_I1_400_3(len, pins[0]); break;
|
case I_32_I1_400_3: busPtr = new B_32_I1_400_3(len, pins[0]); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_400_3: busPtr = new B_32_BB_400_3(len, pins[0], (NeoBusChannel)channel); break;
|
|
||||||
case I_32_RN_TM1_4: busPtr = new B_32_RN_TM1_4(len, pins[0], (NeoBusChannel)channel); break;
|
case I_32_RN_TM1_4: busPtr = new B_32_RN_TM1_4(len, pins[0], (NeoBusChannel)channel); break;
|
||||||
case I_32_RN_TM2_3: busPtr = new B_32_RN_TM2_3(len, pins[0], (NeoBusChannel)channel); break;
|
case I_32_RN_TM2_3: busPtr = new B_32_RN_TM2_3(len, pins[0], (NeoBusChannel)channel); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
@ -508,7 +580,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_3: busPtr = new B_32_I1_UCS_3(len, pins[0]); break;
|
case I_32_I1_UCS_3: busPtr = new B_32_I1_UCS_3(len, pins[0]); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_3: busPtr = new B_32_BB_UCS_3(len, pins[0], (NeoBusChannel)channel); break;
|
|
||||||
case I_32_RN_UCS_4: busPtr = new B_32_RN_UCS_4(len, pins[0], (NeoBusChannel)channel); break;
|
case I_32_RN_UCS_4: busPtr = new B_32_RN_UCS_4(len, pins[0], (NeoBusChannel)channel); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_UCS_4: busPtr = new B_32_I0_UCS_4(len, pins[0]); break;
|
case I_32_I0_UCS_4: busPtr = new B_32_I0_UCS_4(len, pins[0]); break;
|
||||||
@ -516,7 +587,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_4: busPtr = new B_32_I1_UCS_4(len, pins[0]); break;
|
case I_32_I1_UCS_4: busPtr = new B_32_I1_UCS_4(len, pins[0]); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: busPtr = new B_32_BB_UCS_4(len, pins[0], (NeoBusChannel)channel); break;
|
|
||||||
case I_32_RN_APA106_3: busPtr = new B_32_RN_APA106_3(len, pins[0], (NeoBusChannel)channel); break;
|
case I_32_RN_APA106_3: busPtr = new B_32_RN_APA106_3(len, pins[0], (NeoBusChannel)channel); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_APA106_3: busPtr = new B_32_I0_APA106_3(len, pins[0]); break;
|
case I_32_I0_APA106_3: busPtr = new B_32_I0_APA106_3(len, pins[0]); break;
|
||||||
@ -524,7 +594,20 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_APA106_3: busPtr = new B_32_I1_APA106_3(len, pins[0]); break;
|
case I_32_I1_APA106_3: busPtr = new B_32_I1_APA106_3(len, pins[0]); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_APA106_3: busPtr = new B_32_BB_APA106_3(len, pins[0], (NeoBusChannel)channel); break;
|
case I_32_RN_FW6_5: busPtr = new B_32_RN_FW6_5(len, pins[0], (NeoBusChannel)channel); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_FW6_5: busPtr = new B_32_I0_FW6_5(len, pins[0]); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_FW6_5: busPtr = new B_32_I1_FW6_5(len, pins[0]); break;
|
||||||
|
#endif
|
||||||
|
case I_32_RN_2805_5: busPtr = new B_32_RN_2805_5(len, pins[0], (NeoBusChannel)channel); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_2805_5: busPtr = new B_32_I0_2805_5(len, pins[0]); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_2805_5: busPtr = new B_32_I1_2805_5(len, pins[0]); break;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
// for 2-wire: pins[1] is clk, pins[0] is dat. begin expects (len, clk, dat)
|
// for 2-wire: pins[1] is clk, pins[0] is dat. begin expects (len, clk, dat)
|
||||||
case I_HS_DOT_3: busPtr = new B_HS_DOT_3(len, pins[1], pins[0]); break;
|
case I_HS_DOT_3: busPtr = new B_HS_DOT_3(len, pins[1], pins[0]); break;
|
||||||
@ -578,6 +661,14 @@ class PolyBus {
|
|||||||
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->Show(consistent); break;
|
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->Show(consistent); break;
|
||||||
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->Show(consistent); break;
|
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->Show(consistent); break;
|
||||||
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->Show(consistent); break;
|
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->Show(consistent); break;
|
||||||
|
case I_8266_U0_FW6_5: (static_cast<B_8266_U0_FW6_5*>(busPtr))->Show(consistent); break;
|
||||||
|
case I_8266_U1_FW6_5: (static_cast<B_8266_U1_FW6_5*>(busPtr))->Show(consistent); break;
|
||||||
|
case I_8266_DM_FW6_5: (static_cast<B_8266_DM_FW6_5*>(busPtr))->Show(consistent); break;
|
||||||
|
case I_8266_BB_FW6_5: (static_cast<B_8266_BB_FW6_5*>(busPtr))->Show(consistent); break;
|
||||||
|
case I_8266_U0_2805_5: (static_cast<B_8266_U0_2805_5*>(busPtr))->Show(consistent); break;
|
||||||
|
case I_8266_U1_2805_5: (static_cast<B_8266_U1_2805_5*>(busPtr))->Show(consistent); break;
|
||||||
|
case I_8266_DM_2805_5: (static_cast<B_8266_DM_2805_5*>(busPtr))->Show(consistent); break;
|
||||||
|
case I_8266_BB_2805_5: (static_cast<B_8266_BB_2805_5*>(busPtr))->Show(consistent); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Show(consistent); break;
|
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Show(consistent); break;
|
||||||
@ -587,7 +678,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->Show(consistent); break;
|
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->Show(consistent); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_3: (static_cast<B_32_BB_NEO_3*>(busPtr))->Show(consistent); break;
|
|
||||||
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->Show(consistent); break;
|
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->Show(consistent); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->Show(consistent); break;
|
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->Show(consistent); break;
|
||||||
@ -595,7 +685,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->Show(consistent); break;
|
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->Show(consistent); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_4: (static_cast<B_32_BB_NEO_4*>(busPtr))->Show(consistent); break;
|
|
||||||
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->Show(consistent); break;
|
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->Show(consistent); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->Show(consistent); break;
|
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->Show(consistent); break;
|
||||||
@ -603,7 +692,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Show(consistent); break;
|
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Show(consistent); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_400_3: (static_cast<B_32_BB_400_3*>(busPtr))->Show(consistent); break;
|
|
||||||
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->Show(consistent); break;
|
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->Show(consistent); break;
|
||||||
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->Show(consistent); break;
|
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->Show(consistent); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
@ -621,7 +709,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->Show(consistent); break;
|
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->Show(consistent); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_3: (static_cast<B_32_BB_NEO_3*>(busPtr))->Show(consistent); break;
|
|
||||||
case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->Show(consistent); break;
|
case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->Show(consistent); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->Show(consistent); break;
|
case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->Show(consistent); break;
|
||||||
@ -629,7 +716,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Show(consistent); break;
|
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Show(consistent); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->Show(consistent); break;
|
|
||||||
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->Show(consistent); break;
|
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->Show(consistent); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->Show(consistent); break;
|
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->Show(consistent); break;
|
||||||
@ -637,7 +723,20 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->Show(consistent); break;
|
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->Show(consistent); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->Show(consistent); break;
|
case I_32_RN_FW6_5: (static_cast<B_32_RN_FW6_5*>(busPtr))->Show(consistent); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_FW6_5: (static_cast<B_32_I0_FW6_5*>(busPtr))->Show(consistent); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_FW6_5: (static_cast<B_32_I1_FW6_5*>(busPtr))->Show(consistent); break;
|
||||||
|
#endif
|
||||||
|
case I_32_RN_2805_5: (static_cast<B_32_RN_2805_5*>(busPtr))->Show(consistent); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_2805_5: (static_cast<B_32_I0_2805_5*>(busPtr))->Show(consistent); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_2805_5: (static_cast<B_32_I1_2805_5*>(busPtr))->Show(consistent); break;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->Show(consistent); break;
|
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->Show(consistent); break;
|
||||||
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->Show(consistent); break;
|
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->Show(consistent); break;
|
||||||
@ -687,6 +786,14 @@ class PolyBus {
|
|||||||
case I_8266_U1_APA106_3: return (static_cast<B_8266_U1_APA106_3*>(busPtr))->CanShow(); break;
|
case I_8266_U1_APA106_3: return (static_cast<B_8266_U1_APA106_3*>(busPtr))->CanShow(); break;
|
||||||
case I_8266_DM_APA106_3: return (static_cast<B_8266_DM_APA106_3*>(busPtr))->CanShow(); break;
|
case I_8266_DM_APA106_3: return (static_cast<B_8266_DM_APA106_3*>(busPtr))->CanShow(); break;
|
||||||
case I_8266_BB_APA106_3: return (static_cast<B_8266_BB_APA106_3*>(busPtr))->CanShow(); break;
|
case I_8266_BB_APA106_3: return (static_cast<B_8266_BB_APA106_3*>(busPtr))->CanShow(); break;
|
||||||
|
case I_8266_U0_FW6_5: return (static_cast<B_8266_U0_FW6_5*>(busPtr))->CanShow(); break;
|
||||||
|
case I_8266_U1_FW6_5: return (static_cast<B_8266_U1_FW6_5*>(busPtr))->CanShow(); break;
|
||||||
|
case I_8266_DM_FW6_5: return (static_cast<B_8266_DM_FW6_5*>(busPtr))->CanShow(); break;
|
||||||
|
case I_8266_BB_FW6_5: return (static_cast<B_8266_BB_FW6_5*>(busPtr))->CanShow(); break;
|
||||||
|
case I_8266_U0_2805_5: return (static_cast<B_8266_U0_2805_5*>(busPtr))->CanShow(); break;
|
||||||
|
case I_8266_U1_2805_5: return (static_cast<B_8266_U1_2805_5*>(busPtr))->CanShow(); break;
|
||||||
|
case I_8266_DM_2805_5: return (static_cast<B_8266_DM_2805_5*>(busPtr))->CanShow(); break;
|
||||||
|
case I_8266_BB_2805_5: return (static_cast<B_8266_BB_2805_5*>(busPtr))->CanShow(); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: return (static_cast<B_32_RN_NEO_3*>(busPtr))->CanShow(); break;
|
case I_32_RN_NEO_3: return (static_cast<B_32_RN_NEO_3*>(busPtr))->CanShow(); break;
|
||||||
@ -696,7 +803,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_3: return (static_cast<B_32_I1_NEO_3*>(busPtr))->CanShow(); break;
|
case I_32_I1_NEO_3: return (static_cast<B_32_I1_NEO_3*>(busPtr))->CanShow(); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_3: return (static_cast<B_32_BB_NEO_3*>(busPtr))->CanShow(); break;
|
|
||||||
case I_32_RN_NEO_4: return (static_cast<B_32_RN_NEO_4*>(busPtr))->CanShow(); break;
|
case I_32_RN_NEO_4: return (static_cast<B_32_RN_NEO_4*>(busPtr))->CanShow(); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_NEO_4: return (static_cast<B_32_I0_NEO_4*>(busPtr))->CanShow(); break;
|
case I_32_I0_NEO_4: return (static_cast<B_32_I0_NEO_4*>(busPtr))->CanShow(); break;
|
||||||
@ -704,7 +810,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_4: return (static_cast<B_32_I1_NEO_4*>(busPtr))->CanShow(); break;
|
case I_32_I1_NEO_4: return (static_cast<B_32_I1_NEO_4*>(busPtr))->CanShow(); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_4: return (static_cast<B_32_BB_NEO_4*>(busPtr))->CanShow(); break;
|
|
||||||
case I_32_RN_400_3: return (static_cast<B_32_RN_400_3*>(busPtr))->CanShow(); break;
|
case I_32_RN_400_3: return (static_cast<B_32_RN_400_3*>(busPtr))->CanShow(); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_400_3: return (static_cast<B_32_I0_400_3*>(busPtr))->CanShow(); break;
|
case I_32_I0_400_3: return (static_cast<B_32_I0_400_3*>(busPtr))->CanShow(); break;
|
||||||
@ -712,7 +817,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_400_3: return (static_cast<B_32_I1_400_3*>(busPtr))->CanShow(); break;
|
case I_32_I1_400_3: return (static_cast<B_32_I1_400_3*>(busPtr))->CanShow(); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_400_3: return (static_cast<B_32_BB_400_3*>(busPtr))->CanShow(); break;
|
|
||||||
case I_32_RN_TM1_4: return (static_cast<B_32_RN_TM1_4*>(busPtr))->CanShow(); break;
|
case I_32_RN_TM1_4: return (static_cast<B_32_RN_TM1_4*>(busPtr))->CanShow(); break;
|
||||||
case I_32_RN_TM2_3: return (static_cast<B_32_RN_TM2_3*>(busPtr))->CanShow(); break;
|
case I_32_RN_TM2_3: return (static_cast<B_32_RN_TM2_3*>(busPtr))->CanShow(); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
@ -730,7 +834,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_3: return (static_cast<B_32_I1_UCS_3*>(busPtr))->CanShow(); break;
|
case I_32_I1_UCS_3: return (static_cast<B_32_I1_UCS_3*>(busPtr))->CanShow(); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_3: return (static_cast<B_32_BB_UCS_3*>(busPtr))->CanShow(); break;
|
|
||||||
case I_32_RN_UCS_4: return (static_cast<B_32_RN_UCS_4*>(busPtr))->CanShow(); break;
|
case I_32_RN_UCS_4: return (static_cast<B_32_RN_UCS_4*>(busPtr))->CanShow(); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_UCS_4: return (static_cast<B_32_I0_UCS_4*>(busPtr))->CanShow(); break;
|
case I_32_I0_UCS_4: return (static_cast<B_32_I0_UCS_4*>(busPtr))->CanShow(); break;
|
||||||
@ -738,7 +841,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_4: return (static_cast<B_32_I1_UCS_4*>(busPtr))->CanShow(); break;
|
case I_32_I1_UCS_4: return (static_cast<B_32_I1_UCS_4*>(busPtr))->CanShow(); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: return (static_cast<B_32_BB_UCS_4*>(busPtr))->CanShow(); break;
|
|
||||||
case I_32_RN_APA106_3: return (static_cast<B_32_RN_APA106_3*>(busPtr))->CanShow(); break;
|
case I_32_RN_APA106_3: return (static_cast<B_32_RN_APA106_3*>(busPtr))->CanShow(); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_APA106_3: return (static_cast<B_32_I0_APA106_3*>(busPtr))->CanShow(); break;
|
case I_32_I0_APA106_3: return (static_cast<B_32_I0_APA106_3*>(busPtr))->CanShow(); break;
|
||||||
@ -746,7 +848,20 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_APA106_3: return (static_cast<B_32_I1_APA106_3*>(busPtr))->CanShow(); break;
|
case I_32_I1_APA106_3: return (static_cast<B_32_I1_APA106_3*>(busPtr))->CanShow(); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_APA106_3: return (static_cast<B_32_BB_APA106_3*>(busPtr))->CanShow(); break;
|
case I_32_RN_FW6_5: return (static_cast<B_32_RN_FW6_5*>(busPtr))->CanShow(); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_FW6_5: return (static_cast<B_32_I0_FW6_5*>(busPtr))->CanShow(); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_FW6_5: return (static_cast<B_32_I1_FW6_5*>(busPtr))->CanShow(); break;
|
||||||
|
#endif
|
||||||
|
case I_32_RN_2805_5: return (static_cast<B_32_RN_2805_5*>(busPtr))->CanShow(); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_2805_5: return (static_cast<B_32_I0_2805_5*>(busPtr))->CanShow(); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_2805_5: return (static_cast<B_32_I1_2805_5*>(busPtr))->CanShow(); break;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
case I_HS_DOT_3: return (static_cast<B_HS_DOT_3*>(busPtr))->CanShow(); break;
|
case I_HS_DOT_3: return (static_cast<B_HS_DOT_3*>(busPtr))->CanShow(); break;
|
||||||
case I_SS_DOT_3: return (static_cast<B_SS_DOT_3*>(busPtr))->CanShow(); break;
|
case I_SS_DOT_3: return (static_cast<B_SS_DOT_3*>(busPtr))->CanShow(); break;
|
||||||
@ -762,12 +877,13 @@ class PolyBus {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setPixelColor(void* busPtr, uint8_t busType, uint16_t pix, uint32_t c, uint8_t co) {
|
static void setPixelColor(void* busPtr, uint8_t busType, uint16_t pix, uint32_t c, uint8_t co, uint16_t wwcw = 0) {
|
||||||
uint8_t r = c >> 16;
|
uint8_t r = c >> 16;
|
||||||
uint8_t g = c >> 8;
|
uint8_t g = c >> 8;
|
||||||
uint8_t b = c >> 0;
|
uint8_t b = c >> 0;
|
||||||
uint8_t w = c >> 24;
|
uint8_t w = c >> 24;
|
||||||
RgbwColor col;
|
RgbwColor col;
|
||||||
|
uint8_t cctWW = wwcw & 0xFF, cctCW = (wwcw>>8) & 0xFF;
|
||||||
|
|
||||||
// reorder channels to selected order
|
// reorder channels to selected order
|
||||||
switch (co & 0x0F) {
|
switch (co & 0x0F) {
|
||||||
@ -821,6 +937,14 @@ class PolyBus {
|
|||||||
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
|
case I_8266_U0_FW6_5: (static_cast<B_8266_U0_FW6_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
|
||||||
|
case I_8266_U1_FW6_5: (static_cast<B_8266_U1_FW6_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
|
||||||
|
case I_8266_DM_FW6_5: (static_cast<B_8266_DM_FW6_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
|
||||||
|
case I_8266_BB_FW6_5: (static_cast<B_8266_BB_FW6_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
|
||||||
|
case I_8266_U0_2805_5: (static_cast<B_8266_U0_2805_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
|
||||||
|
case I_8266_U1_2805_5: (static_cast<B_8266_U1_2805_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
|
||||||
|
case I_8266_DM_2805_5: (static_cast<B_8266_DM_2805_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
|
||||||
|
case I_8266_BB_2805_5: (static_cast<B_8266_BB_2805_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
@ -830,7 +954,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_3: (static_cast<B_32_BB_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
|
||||||
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
|
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
|
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||||
@ -838,7 +961,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
|
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_4: (static_cast<B_32_BB_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
|
|
||||||
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
@ -846,7 +968,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_400_3: (static_cast<B_32_BB_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(colB)); break;
|
|
||||||
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
|
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||||
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
@ -864,7 +985,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->SetPixelColor(pix, Rgb48Color(RgbColor(col))); break;
|
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->SetPixelColor(pix, Rgb48Color(RgbColor(col))); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_3: (static_cast<B_32_BB_UCS_3*>(busPtr))->SetPixelColor(pix, Rgb48Color(RgbColor(col))); break;
|
|
||||||
case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
||||||
@ -872,7 +992,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
|
||||||
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
@ -880,7 +999,20 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_32_RN_FW6_5: (static_cast<B_32_RN_FW6_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_FW6_5: (static_cast<B_32_I0_FW6_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_FW6_5: (static_cast<B_32_I1_FW6_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
|
||||||
|
#endif
|
||||||
|
case I_32_RN_2805_5: (static_cast<B_32_RN_2805_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_2805_5: (static_cast<B_32_I0_2805_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_2805_5: (static_cast<B_32_I1_2805_5*>(busPtr))->SetPixelColor(pix, RgbwwColor(col.R, col.G, col.B, cctWW, cctCW)); break;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
@ -931,6 +1063,14 @@ class PolyBus {
|
|||||||
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->SetLuminance(b); break;
|
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->SetLuminance(b); break;
|
||||||
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->SetLuminance(b); break;
|
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->SetLuminance(b); break;
|
||||||
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->SetLuminance(b); break;
|
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->SetLuminance(b); break;
|
||||||
|
case I_8266_U0_FW6_5: (static_cast<B_8266_U0_FW6_5*>(busPtr))->SetLuminance(b); break;
|
||||||
|
case I_8266_U1_FW6_5: (static_cast<B_8266_U1_FW6_5*>(busPtr))->SetLuminance(b); break;
|
||||||
|
case I_8266_DM_FW6_5: (static_cast<B_8266_DM_FW6_5*>(busPtr))->SetLuminance(b); break;
|
||||||
|
case I_8266_BB_FW6_5: (static_cast<B_8266_BB_FW6_5*>(busPtr))->SetLuminance(b); break;
|
||||||
|
case I_8266_U0_2805_5: (static_cast<B_8266_U0_2805_5*>(busPtr))->SetLuminance(b); break;
|
||||||
|
case I_8266_U1_2805_5: (static_cast<B_8266_U1_2805_5*>(busPtr))->SetLuminance(b); break;
|
||||||
|
case I_8266_DM_2805_5: (static_cast<B_8266_DM_2805_5*>(busPtr))->SetLuminance(b); break;
|
||||||
|
case I_8266_BB_2805_5: (static_cast<B_8266_BB_2805_5*>(busPtr))->SetLuminance(b); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetLuminance(b); break;
|
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetLuminance(b); break;
|
||||||
@ -940,7 +1080,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->SetLuminance(b); break;
|
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->SetLuminance(b); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_3: (static_cast<B_32_BB_NEO_3*>(busPtr))->SetLuminance(b); break;
|
|
||||||
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->SetLuminance(b); break;
|
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->SetLuminance(b); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->SetLuminance(b); break;
|
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->SetLuminance(b); break;
|
||||||
@ -948,7 +1087,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->SetLuminance(b); break;
|
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->SetLuminance(b); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_4: (static_cast<B_32_BB_NEO_4*>(busPtr))->SetLuminance(b); break;
|
|
||||||
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->SetLuminance(b); break;
|
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->SetLuminance(b); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->SetLuminance(b); break;
|
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->SetLuminance(b); break;
|
||||||
@ -956,7 +1094,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetLuminance(b); break;
|
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetLuminance(b); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_400_3: (static_cast<B_32_BB_400_3*>(busPtr))->SetLuminance(b); break;
|
|
||||||
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->SetLuminance(b); break;
|
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->SetLuminance(b); break;
|
||||||
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->SetLuminance(b); break;
|
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->SetLuminance(b); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
@ -974,7 +1111,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->SetLuminance(b); break;
|
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->SetLuminance(b); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_3: (static_cast<B_32_BB_UCS_3*>(busPtr))->SetLuminance(b); break;
|
|
||||||
case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->SetLuminance(b); break;
|
case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->SetLuminance(b); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->SetLuminance(b); break;
|
case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->SetLuminance(b); break;
|
||||||
@ -982,7 +1118,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetLuminance(b); break;
|
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetLuminance(b); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->SetLuminance(b); break;
|
|
||||||
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->SetLuminance(b); break;
|
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->SetLuminance(b); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->SetLuminance(b); break;
|
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->SetLuminance(b); break;
|
||||||
@ -990,7 +1125,20 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->SetLuminance(b); break;
|
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->SetLuminance(b); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->SetLuminance(b); break;
|
case I_32_RN_FW6_5: (static_cast<B_32_RN_FW6_5*>(busPtr))->SetLuminance(b); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_FW6_5: (static_cast<B_32_I0_FW6_5*>(busPtr))->SetLuminance(b); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_FW6_5: (static_cast<B_32_I1_FW6_5*>(busPtr))->SetLuminance(b); break;
|
||||||
|
#endif
|
||||||
|
case I_32_RN_2805_5: (static_cast<B_32_RN_2805_5*>(busPtr))->SetLuminance(b); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_2805_5: (static_cast<B_32_I0_2805_5*>(busPtr))->SetLuminance(b); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_2805_5: (static_cast<B_32_I1_2805_5*>(busPtr))->SetLuminance(b); break;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetLuminance(b); break;
|
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetLuminance(b); break;
|
||||||
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetLuminance(b); break;
|
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetLuminance(b); break;
|
||||||
@ -1042,6 +1190,14 @@ class PolyBus {
|
|||||||
case I_8266_U1_APA106_3: col = (static_cast<B_8266_U1_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_8266_U1_APA106_3: col = (static_cast<B_8266_U1_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
case I_8266_DM_APA106_3: col = (static_cast<B_8266_DM_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_8266_DM_APA106_3: col = (static_cast<B_8266_DM_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
case I_8266_BB_APA106_3: col = (static_cast<B_8266_BB_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_8266_BB_APA106_3: col = (static_cast<B_8266_BB_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
|
case I_8266_U0_FW6_5: { RgbwwColor c = (static_cast<B_8266_U0_FW6_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
|
||||||
|
case I_8266_U1_FW6_5: { RgbwwColor c = (static_cast<B_8266_U1_FW6_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
|
||||||
|
case I_8266_DM_FW6_5: { RgbwwColor c = (static_cast<B_8266_DM_FW6_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
|
||||||
|
case I_8266_BB_FW6_5: { RgbwwColor c = (static_cast<B_8266_BB_FW6_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
|
||||||
|
case I_8266_U0_2805_5: { RgbwwColor c = (static_cast<B_8266_U0_2805_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
|
||||||
|
case I_8266_U1_2805_5: { RgbwwColor c = (static_cast<B_8266_U1_2805_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
|
||||||
|
case I_8266_DM_2805_5: { RgbwwColor c = (static_cast<B_8266_DM_2805_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
|
||||||
|
case I_8266_BB_2805_5: { RgbwwColor c = (static_cast<B_8266_BB_2805_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: col = (static_cast<B_32_RN_NEO_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_RN_NEO_3: col = (static_cast<B_32_RN_NEO_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
@ -1051,7 +1207,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_3: col = (static_cast<B_32_I1_NEO_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_I1_NEO_3: col = (static_cast<B_32_I1_NEO_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_3: col = (static_cast<B_32_BB_NEO_3*>(busPtr))->GetPixelColor(pix); break;
|
|
||||||
case I_32_RN_NEO_4: col = (static_cast<B_32_RN_NEO_4*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_RN_NEO_4: col = (static_cast<B_32_RN_NEO_4*>(busPtr))->GetPixelColor(pix); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_NEO_4: col = (static_cast<B_32_I0_NEO_4*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_I0_NEO_4: col = (static_cast<B_32_I0_NEO_4*>(busPtr))->GetPixelColor(pix); break;
|
||||||
@ -1059,7 +1214,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_4: col = (static_cast<B_32_I1_NEO_4*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_I1_NEO_4: col = (static_cast<B_32_I1_NEO_4*>(busPtr))->GetPixelColor(pix); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_4: col = (static_cast<B_32_BB_NEO_4*>(busPtr))->GetPixelColor(pix); break;
|
|
||||||
case I_32_RN_400_3: col = (static_cast<B_32_RN_400_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_RN_400_3: col = (static_cast<B_32_RN_400_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_400_3: col = (static_cast<B_32_I0_400_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_I0_400_3: col = (static_cast<B_32_I0_400_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
@ -1067,7 +1221,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_400_3: col = (static_cast<B_32_I1_400_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_I1_400_3: col = (static_cast<B_32_I1_400_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_400_3: col = (static_cast<B_32_BB_400_3*>(busPtr))->GetPixelColor(pix); break;
|
|
||||||
case I_32_RN_TM1_4: col = (static_cast<B_32_RN_TM1_4*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_RN_TM1_4: col = (static_cast<B_32_RN_TM1_4*>(busPtr))->GetPixelColor(pix); break;
|
||||||
case I_32_RN_TM2_3: col = (static_cast<B_32_RN_TM2_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_RN_TM2_3: col = (static_cast<B_32_RN_TM2_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
@ -1085,7 +1238,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_3: { Rgb48Color c = (static_cast<B_32_I1_UCS_3*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,0); } break;
|
case I_32_I1_UCS_3: { Rgb48Color c = (static_cast<B_32_I1_UCS_3*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,0); } break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_3: col = (static_cast<B_32_BB_UCS_3*>(busPtr))->GetPixelColor(pix); break;
|
|
||||||
case I_32_RN_UCS_4: { Rgbw64Color c = (static_cast<B_32_RN_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
|
case I_32_RN_UCS_4: { Rgbw64Color c = (static_cast<B_32_RN_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_UCS_4: { Rgbw64Color c = (static_cast<B_32_I0_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
|
case I_32_I0_UCS_4: { Rgbw64Color c = (static_cast<B_32_I0_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
|
||||||
@ -1093,7 +1245,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_4: { Rgbw64Color c = (static_cast<B_32_I1_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
|
case I_32_I1_UCS_4: { Rgbw64Color c = (static_cast<B_32_I1_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: col = (static_cast<B_32_BB_UCS_4*>(busPtr))->GetPixelColor(pix); break;
|
|
||||||
case I_32_RN_APA106_3: col = (static_cast<B_32_RN_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_RN_APA106_3: col = (static_cast<B_32_RN_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_APA106_3: col = (static_cast<B_32_I0_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_I0_APA106_3: col = (static_cast<B_32_I0_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
@ -1101,7 +1252,20 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_APA106_3: col = (static_cast<B_32_I1_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_I1_APA106_3: col = (static_cast<B_32_I1_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_APA106_3: col = (static_cast<B_32_BB_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_RN_FW6_5: { RgbwwColor c = (static_cast<B_32_RN_FW6_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_FW6_5: { RgbwwColor c = (static_cast<B_32_I0_FW6_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_FW6_5: { RgbwwColor c = (static_cast<B_32_I1_FW6_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
|
||||||
|
#endif
|
||||||
|
case I_32_RN_2805_5: { RgbwwColor c = (static_cast<B_32_RN_2805_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_2805_5: { RgbwwColor c = (static_cast<B_32_I0_2805_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_2805_5: { RgbwwColor c = (static_cast<B_32_I1_2805_5*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R,c.G,c.B,max(c.WW,c.CW)); } break; // will not return original W
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
case I_HS_DOT_3: col = (static_cast<B_HS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_HS_DOT_3: col = (static_cast<B_HS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
case I_SS_DOT_3: col = (static_cast<B_SS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_SS_DOT_3: col = (static_cast<B_SS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
@ -1171,6 +1335,14 @@ class PolyBus {
|
|||||||
case I_8266_U1_APA106_3: delete (static_cast<B_8266_U1_APA106_3*>(busPtr)); break;
|
case I_8266_U1_APA106_3: delete (static_cast<B_8266_U1_APA106_3*>(busPtr)); break;
|
||||||
case I_8266_DM_APA106_3: delete (static_cast<B_8266_DM_APA106_3*>(busPtr)); break;
|
case I_8266_DM_APA106_3: delete (static_cast<B_8266_DM_APA106_3*>(busPtr)); break;
|
||||||
case I_8266_BB_APA106_3: delete (static_cast<B_8266_BB_APA106_3*>(busPtr)); break;
|
case I_8266_BB_APA106_3: delete (static_cast<B_8266_BB_APA106_3*>(busPtr)); break;
|
||||||
|
case I_8266_U0_FW6_5: delete (static_cast<B_8266_U0_FW6_5*>(busPtr)); break;
|
||||||
|
case I_8266_U1_FW6_5: delete (static_cast<B_8266_U1_FW6_5*>(busPtr)); break;
|
||||||
|
case I_8266_DM_FW6_5: delete (static_cast<B_8266_DM_FW6_5*>(busPtr)); break;
|
||||||
|
case I_8266_BB_FW6_5: delete (static_cast<B_8266_BB_FW6_5*>(busPtr)); break;
|
||||||
|
case I_8266_U0_2805_5: delete (static_cast<B_8266_U0_2805_5*>(busPtr)); break;
|
||||||
|
case I_8266_U1_2805_5: delete (static_cast<B_8266_U1_2805_5*>(busPtr)); break;
|
||||||
|
case I_8266_DM_2805_5: delete (static_cast<B_8266_DM_2805_5*>(busPtr)); break;
|
||||||
|
case I_8266_BB_2805_5: delete (static_cast<B_8266_BB_2805_5*>(busPtr)); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: delete (static_cast<B_32_RN_NEO_3*>(busPtr)); break;
|
case I_32_RN_NEO_3: delete (static_cast<B_32_RN_NEO_3*>(busPtr)); break;
|
||||||
@ -1180,7 +1352,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_3: delete (static_cast<B_32_I1_NEO_3*>(busPtr)); break;
|
case I_32_I1_NEO_3: delete (static_cast<B_32_I1_NEO_3*>(busPtr)); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_3: delete (static_cast<B_32_BB_NEO_3*>(busPtr)); break;
|
|
||||||
case I_32_RN_NEO_4: delete (static_cast<B_32_RN_NEO_4*>(busPtr)); break;
|
case I_32_RN_NEO_4: delete (static_cast<B_32_RN_NEO_4*>(busPtr)); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_NEO_4: delete (static_cast<B_32_I0_NEO_4*>(busPtr)); break;
|
case I_32_I0_NEO_4: delete (static_cast<B_32_I0_NEO_4*>(busPtr)); break;
|
||||||
@ -1188,7 +1359,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_NEO_4: delete (static_cast<B_32_I1_NEO_4*>(busPtr)); break;
|
case I_32_I1_NEO_4: delete (static_cast<B_32_I1_NEO_4*>(busPtr)); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_NEO_4: delete (static_cast<B_32_BB_NEO_4*>(busPtr)); break;
|
|
||||||
case I_32_RN_400_3: delete (static_cast<B_32_RN_400_3*>(busPtr)); break;
|
case I_32_RN_400_3: delete (static_cast<B_32_RN_400_3*>(busPtr)); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_400_3: delete (static_cast<B_32_I0_400_3*>(busPtr)); break;
|
case I_32_I0_400_3: delete (static_cast<B_32_I0_400_3*>(busPtr)); break;
|
||||||
@ -1196,7 +1366,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_400_3: delete (static_cast<B_32_I1_400_3*>(busPtr)); break;
|
case I_32_I1_400_3: delete (static_cast<B_32_I1_400_3*>(busPtr)); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_400_3: delete (static_cast<B_32_BB_400_3*>(busPtr)); break;
|
|
||||||
case I_32_RN_TM1_4: delete (static_cast<B_32_RN_TM1_4*>(busPtr)); break;
|
case I_32_RN_TM1_4: delete (static_cast<B_32_RN_TM1_4*>(busPtr)); break;
|
||||||
case I_32_RN_TM2_3: delete (static_cast<B_32_RN_TM2_3*>(busPtr)); break;
|
case I_32_RN_TM2_3: delete (static_cast<B_32_RN_TM2_3*>(busPtr)); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
@ -1214,7 +1383,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_3: delete (static_cast<B_32_I1_UCS_3*>(busPtr)); break;
|
case I_32_I1_UCS_3: delete (static_cast<B_32_I1_UCS_3*>(busPtr)); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_3: delete (static_cast<B_32_BB_UCS_3*>(busPtr)); break;
|
|
||||||
case I_32_RN_UCS_4: delete (static_cast<B_32_RN_UCS_4*>(busPtr)); break;
|
case I_32_RN_UCS_4: delete (static_cast<B_32_RN_UCS_4*>(busPtr)); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_UCS_4: delete (static_cast<B_32_I0_UCS_4*>(busPtr)); break;
|
case I_32_I0_UCS_4: delete (static_cast<B_32_I0_UCS_4*>(busPtr)); break;
|
||||||
@ -1222,7 +1390,6 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_UCS_4: delete (static_cast<B_32_I1_UCS_4*>(busPtr)); break;
|
case I_32_I1_UCS_4: delete (static_cast<B_32_I1_UCS_4*>(busPtr)); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: delete (static_cast<B_32_BB_UCS_4*>(busPtr)); break;
|
|
||||||
case I_32_RN_APA106_3: delete (static_cast<B_32_RN_APA106_3*>(busPtr)); break;
|
case I_32_RN_APA106_3: delete (static_cast<B_32_RN_APA106_3*>(busPtr)); break;
|
||||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
case I_32_I0_APA106_3: delete (static_cast<B_32_I0_APA106_3*>(busPtr)); break;
|
case I_32_I0_APA106_3: delete (static_cast<B_32_I0_APA106_3*>(busPtr)); break;
|
||||||
@ -1230,7 +1397,20 @@ class PolyBus {
|
|||||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
case I_32_I1_APA106_3: delete (static_cast<B_32_I1_APA106_3*>(busPtr)); break;
|
case I_32_I1_APA106_3: delete (static_cast<B_32_I1_APA106_3*>(busPtr)); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_APA106_3: delete (static_cast<B_32_BB_APA106_3*>(busPtr)); break;
|
case I_32_RN_FW6_5: delete (static_cast<B_32_RN_FW6_5*>(busPtr)); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_FW6_5: delete (static_cast<B_32_I0_FW6_5*>(busPtr)); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_FW6_5: delete (static_cast<B_32_I1_FW6_5*>(busPtr)); break;
|
||||||
|
#endif
|
||||||
|
case I_32_RN_2805_5: delete (static_cast<B_32_RN_2805_5*>(busPtr)); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_2805_5: delete (static_cast<B_32_I0_2805_5*>(busPtr)); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_2805_5: delete (static_cast<B_32_I1_2805_5*>(busPtr)); break;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
case I_HS_DOT_3: delete (static_cast<B_HS_DOT_3*>(busPtr)); break;
|
case I_HS_DOT_3: delete (static_cast<B_HS_DOT_3*>(busPtr)); break;
|
||||||
case I_SS_DOT_3: delete (static_cast<B_SS_DOT_3*>(busPtr)); break;
|
case I_SS_DOT_3: delete (static_cast<B_SS_DOT_3*>(busPtr)); break;
|
||||||
@ -1292,13 +1472,17 @@ class PolyBus {
|
|||||||
return I_8266_U0_UCS_4 + offset;
|
return I_8266_U0_UCS_4 + offset;
|
||||||
case TYPE_APA106:
|
case TYPE_APA106:
|
||||||
return I_8266_U0_APA106_3 + offset;
|
return I_8266_U0_APA106_3 + offset;
|
||||||
|
case TYPE_FW1906:
|
||||||
|
return I_8266_U0_FW6_5 + offset;
|
||||||
|
case TYPE_WS2805:
|
||||||
|
return I_8266_U0_2805_5 + offset;
|
||||||
}
|
}
|
||||||
#else //ESP32
|
#else //ESP32
|
||||||
uint8_t offset = 0; //0 = RMT (num 0-7) 8 = I2S0 9 = I2S1
|
uint8_t offset = 0; // 0 = RMT (num 1-8), 1 = I2S0 (used by Audioreactive), 2 = I2S1
|
||||||
#if defined(CONFIG_IDF_TARGET_ESP32S2)
|
#if defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
// ESP32-S2 only has 4 RMT channels
|
// ESP32-S2 only has 4 RMT channels
|
||||||
if (num > 4) return I_NONE;
|
if (num > 4) return I_NONE;
|
||||||
if (num > 3) offset = 1; // only one I2S
|
if (num > 3) offset = 1; // only one I2S (use last to allow Audioreactive)
|
||||||
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
// On ESP32-C3 only the first 2 RMT channels are usable for transmitting
|
// On ESP32-C3 only the first 2 RMT channels are usable for transmitting
|
||||||
if (num > 1) return I_NONE;
|
if (num > 1) return I_NONE;
|
||||||
@ -1310,7 +1494,8 @@ class PolyBus {
|
|||||||
#else
|
#else
|
||||||
// standard ESP32 has 8 RMT and 2 I2S channels
|
// standard ESP32 has 8 RMT and 2 I2S channels
|
||||||
if (num > 9) return I_NONE;
|
if (num > 9) return I_NONE;
|
||||||
if (num > 7) offset = num -7;
|
if (num > 8) offset = 1;
|
||||||
|
if (num == 0) offset = 2; // prefer I2S1 for 1st bus (less flickering but more RAM needed)
|
||||||
#endif
|
#endif
|
||||||
switch (busType) {
|
switch (busType) {
|
||||||
case TYPE_WS2812_1CH_X3:
|
case TYPE_WS2812_1CH_X3:
|
||||||
@ -1332,11 +1517,14 @@ class PolyBus {
|
|||||||
return I_32_RN_UCS_4 + offset;
|
return I_32_RN_UCS_4 + offset;
|
||||||
case TYPE_APA106:
|
case TYPE_APA106:
|
||||||
return I_32_RN_APA106_3 + offset;
|
return I_32_RN_APA106_3 + offset;
|
||||||
|
case TYPE_FW1906:
|
||||||
|
return I_32_RN_FW6_5 + offset;
|
||||||
|
case TYPE_WS2805:
|
||||||
|
return I_32_RN_2805_5 + offset;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return I_NONE;
|
return I_NONE;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
#endif
|
|
||||||
|
@ -21,7 +21,6 @@ void shortPressAction(uint8_t b)
|
|||||||
case 1: ++effectCurrent %= strip.getModeCount(); stateChanged = true; colorUpdated(CALL_MODE_BUTTON); break;
|
case 1: ++effectCurrent %= strip.getModeCount(); stateChanged = true; colorUpdated(CALL_MODE_BUTTON); break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unloadPlaylist(); // applying a preset unloads the playlist
|
|
||||||
applyPreset(macroButton[b], CALL_MODE_BUTTON_PRESET);
|
applyPreset(macroButton[b], CALL_MODE_BUTTON_PRESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +42,6 @@ void longPressAction(uint8_t b)
|
|||||||
case 1: bri += 8; stateUpdated(CALL_MODE_BUTTON); buttonPressedTime[b] = millis(); break; // repeatable action
|
case 1: bri += 8; stateUpdated(CALL_MODE_BUTTON); buttonPressedTime[b] = millis(); break; // repeatable action
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unloadPlaylist(); // applying a preset unloads the playlist
|
|
||||||
applyPreset(macroLongPress[b], CALL_MODE_BUTTON_PRESET);
|
applyPreset(macroLongPress[b], CALL_MODE_BUTTON_PRESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +63,6 @@ void doublePressAction(uint8_t b)
|
|||||||
case 1: ++effectPalette %= strip.getPaletteCount(); colorUpdated(CALL_MODE_BUTTON); break;
|
case 1: ++effectPalette %= strip.getPaletteCount(); colorUpdated(CALL_MODE_BUTTON); break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unloadPlaylist(); // applying a preset unloads the playlist
|
|
||||||
applyPreset(macroDoublePress[b], CALL_MODE_BUTTON_PRESET);
|
applyPreset(macroDoublePress[b], CALL_MODE_BUTTON_PRESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +110,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
Bus::setGlobalAWMode(hw_led[F("rgbwm")] | AW_GLOBAL_DISABLED);
|
Bus::setGlobalAWMode(hw_led[F("rgbwm")] | AW_GLOBAL_DISABLED);
|
||||||
CJSON(correctWB, hw_led["cct"]);
|
CJSON(correctWB, hw_led["cct"]);
|
||||||
CJSON(cctFromRgb, hw_led[F("cr")]);
|
CJSON(cctFromRgb, hw_led[F("cr")]);
|
||||||
|
CJSON(cctICused, hw_led[F("ic")]);
|
||||||
CJSON(strip.cctBlending, hw_led[F("cb")]);
|
CJSON(strip.cctBlending, hw_led[F("cb")]);
|
||||||
Bus::setCCTBlend(strip.cctBlending);
|
Bus::setCCTBlend(strip.cctBlending);
|
||||||
strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS
|
strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS
|
||||||
@ -185,7 +186,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
uint8_t maPerLed = elm[F("ledma")] | 55;
|
uint8_t maPerLed = elm[F("ledma")] | 55;
|
||||||
uint16_t maMax = elm[F("maxpwr")] | (ablMilliampsMax * length) / total; // rough (incorrect?) per strip ABL calculation when no config exists
|
uint16_t maMax = elm[F("maxpwr")] | (ablMilliampsMax * length) / total; // rough (incorrect?) per strip ABL calculation when no config exists
|
||||||
// To disable brightness limiter we either set output max current to 0 or single LED current to 0 (we choose output max current)
|
// To disable brightness limiter we either set output max current to 0 or single LED current to 0 (we choose output max current)
|
||||||
if ((ledType > TYPE_TM1814 && ledType < TYPE_WS2801) || ledType >= TYPE_NET_DDP_RGB) { // analog and virtual
|
if (IS_PWM(ledType) || IS_ONOFF(ledType) || IS_VIRTUAL(ledType)) { // analog and virtual
|
||||||
maPerLed = 0;
|
maPerLed = 0;
|
||||||
maMax = 0;
|
maMax = 0;
|
||||||
}
|
}
|
||||||
@ -632,12 +633,12 @@ static const char s_cfg_json[] PROGMEM = "/cfg.json";
|
|||||||
|
|
||||||
void deserializeConfigFromFS() {
|
void deserializeConfigFromFS() {
|
||||||
bool success = deserializeConfigSec();
|
bool success = deserializeConfigSec();
|
||||||
|
#ifdef WLED_ADD_EEPROM_SUPPORT
|
||||||
if (!success) { //if file does not exist, try reading from EEPROM
|
if (!success) { //if file does not exist, try reading from EEPROM
|
||||||
#ifdef WLED_ADD_EEPROM_SUPPORT
|
|
||||||
deEEPSettings();
|
deEEPSettings();
|
||||||
return;
|
return;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!requestJSONBufferLock(1)) return;
|
if (!requestJSONBufferLock(1)) return;
|
||||||
|
|
||||||
@ -767,6 +768,7 @@ void serializeConfig() {
|
|||||||
hw_led[F("ledma")] = 0; // no longer used
|
hw_led[F("ledma")] = 0; // no longer used
|
||||||
hw_led["cct"] = correctWB;
|
hw_led["cct"] = correctWB;
|
||||||
hw_led[F("cr")] = cctFromRgb;
|
hw_led[F("cr")] = cctFromRgb;
|
||||||
|
hw_led[F("ic")] = cctICused;
|
||||||
hw_led[F("cb")] = strip.cctBlending;
|
hw_led[F("cb")] = strip.cctBlending;
|
||||||
hw_led["fps"] = strip.getTargetFps();
|
hw_led["fps"] = strip.getTargetFps();
|
||||||
hw_led[F("rgbwm")] = Bus::getGlobalAWMode(); // global auto white mode override
|
hw_led[F("rgbwm")] = Bus::getGlobalAWMode(); // global auto white mode override
|
||||||
|
@ -53,24 +53,16 @@
|
|||||||
#define WLED_MAX_BUSSES 3 // will allow 2 digital & 1 analog (or the other way around)
|
#define WLED_MAX_BUSSES 3 // will allow 2 digital & 1 analog (or the other way around)
|
||||||
#define WLED_MIN_VIRTUAL_BUSSES 3
|
#define WLED_MIN_VIRTUAL_BUSSES 3
|
||||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2) // 4 RMT, 8 LEDC, only has 1 I2S bus, supported in NPB
|
#elif defined(CONFIG_IDF_TARGET_ESP32S2) // 4 RMT, 8 LEDC, only has 1 I2S bus, supported in NPB
|
||||||
#if defined(USERMOD_AUDIOREACTIVE) // requested by @softhack007 https://github.com/blazoncek/WLED/issues/33
|
// the 5th bus (I2S) will prevent Audioreactive usermod from functioning (it is last used though)
|
||||||
#define WLED_MAX_BUSSES 6 // will allow 4 digital & 2 analog
|
#define WLED_MAX_BUSSES 7 // will allow 5 digital & 2 analog
|
||||||
#define WLED_MIN_VIRTUAL_BUSSES 4
|
#define WLED_MIN_VIRTUAL_BUSSES 3
|
||||||
#else
|
|
||||||
#define WLED_MAX_BUSSES 7 // will allow 5 digital & 2 analog
|
|
||||||
#define WLED_MIN_VIRTUAL_BUSSES 3
|
|
||||||
#endif
|
|
||||||
#elif defined(CONFIG_IDF_TARGET_ESP32S3) // 4 RMT, 8 LEDC, has 2 I2S but NPB does not support them ATM
|
#elif defined(CONFIG_IDF_TARGET_ESP32S3) // 4 RMT, 8 LEDC, has 2 I2S but NPB does not support them ATM
|
||||||
#define WLED_MAX_BUSSES 6 // will allow 4 digital & 2 analog
|
#define WLED_MAX_BUSSES 6 // will allow 4 digital & 2 analog
|
||||||
#define WLED_MIN_VIRTUAL_BUSSES 4
|
#define WLED_MIN_VIRTUAL_BUSSES 4
|
||||||
#else
|
#else
|
||||||
#if defined(USERMOD_AUDIOREACTIVE) // requested by @softhack007 https://github.com/blazoncek/WLED/issues/33
|
// the 10th digital bus (I2S0) will prevent Audioreactive usermod from functioning (it is last used though)
|
||||||
#define WLED_MAX_BUSSES 8
|
#define WLED_MAX_BUSSES 10
|
||||||
#define WLED_MIN_VIRTUAL_BUSSES 2
|
#define WLED_MIN_VIRTUAL_BUSSES 0
|
||||||
#else
|
|
||||||
#define WLED_MAX_BUSSES 10
|
|
||||||
#define WLED_MIN_VIRTUAL_BUSSES 0
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
@ -180,7 +172,8 @@
|
|||||||
#define USERMOD_ID_STAIRWAY_WIPE 44 //Usermod "stairway-wipe-usermod-v2.h"
|
#define USERMOD_ID_STAIRWAY_WIPE 44 //Usermod "stairway-wipe-usermod-v2.h"
|
||||||
#define USERMOD_ID_ANIMARTRIX 45 //Usermod "usermod_v2_animartrix.h"
|
#define USERMOD_ID_ANIMARTRIX 45 //Usermod "usermod_v2_animartrix.h"
|
||||||
#define USERMOD_ID_HTTP_PULL_LIGHT_CONTROL 46 //usermod "usermod_v2_HttpPullLightControl.h"
|
#define USERMOD_ID_HTTP_PULL_LIGHT_CONTROL 46 //usermod "usermod_v2_HttpPullLightControl.h"
|
||||||
#define USERMOD_ID_MAX17048 47 //Usermod "usermod_max17048.h"
|
#define USERMOD_ID_TETRISAI 47 //Usermod "usermod_v2_tetris.h"
|
||||||
|
#define USERMOD_ID_MAX17048 48 //Usermod "usermod_max17048.h"
|
||||||
|
|
||||||
//Access point behavior
|
//Access point behavior
|
||||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||||
@ -270,9 +263,11 @@
|
|||||||
#define TYPE_TM1829 25
|
#define TYPE_TM1829 25
|
||||||
#define TYPE_UCS8903 26
|
#define TYPE_UCS8903 26
|
||||||
#define TYPE_APA106 27
|
#define TYPE_APA106 27
|
||||||
|
#define TYPE_FW1906 28 //RGB + CW + WW + unused channel (6 channels per IC)
|
||||||
#define TYPE_UCS8904 29 //first RGBW digital type (hardcoded in busmanager.cpp, memUsage())
|
#define TYPE_UCS8904 29 //first RGBW digital type (hardcoded in busmanager.cpp, memUsage())
|
||||||
#define TYPE_SK6812_RGBW 30
|
#define TYPE_SK6812_RGBW 30
|
||||||
#define TYPE_TM1814 31
|
#define TYPE_TM1814 31
|
||||||
|
#define TYPE_WS2805 32 //RGB + WW + CW
|
||||||
//"Analog" types (40-47)
|
//"Analog" types (40-47)
|
||||||
#define TYPE_ONOFF 40 //binary output (relays etc.; NOT PWM)
|
#define TYPE_ONOFF 40 //binary output (relays etc.; NOT PWM)
|
||||||
#define TYPE_ANALOG_1CH 41 //single channel PWM. Uses value of brightest RGBW channel
|
#define TYPE_ANALOG_1CH 41 //single channel PWM. Uses value of brightest RGBW channel
|
||||||
@ -297,6 +292,7 @@
|
|||||||
#define IS_DIGITAL(t) (((t) > 15 && (t) < 40) || ((t) > 47 && (t) < 64)) //digital are 16-39 and 48-63
|
#define IS_DIGITAL(t) (((t) > 15 && (t) < 40) || ((t) > 47 && (t) < 64)) //digital are 16-39 and 48-63
|
||||||
#define IS_2PIN(t) ((t) > 47 && (t) < 64)
|
#define IS_2PIN(t) ((t) > 47 && (t) < 64)
|
||||||
#define IS_16BIT(t) ((t) == TYPE_UCS8903 || (t) == TYPE_UCS8904)
|
#define IS_16BIT(t) ((t) == TYPE_UCS8903 || (t) == TYPE_UCS8904)
|
||||||
|
#define IS_ONOFF(t) ((t) == 40)
|
||||||
#define IS_PWM(t) ((t) > 40 && (t) < 46) //does not include on/Off type
|
#define IS_PWM(t) ((t) > 40 && (t) < 46) //does not include on/Off type
|
||||||
#define NUM_PWM_PINS(t) ((t) - 40) //for analog PWM 41-45 only
|
#define NUM_PWM_PINS(t) ((t) - 40) //for analog PWM 41-45 only
|
||||||
#define IS_VIRTUAL(t) ((t) >= 80 && (t) < 96) //this was a poor choice a better would be 96-111
|
#define IS_VIRTUAL(t) ((t) >= 80 && (t) < 96) //this was a poor choice a better would be 96-111
|
||||||
@ -374,6 +370,7 @@
|
|||||||
|
|
||||||
//Playlist option byte
|
//Playlist option byte
|
||||||
#define PL_OPTION_SHUFFLE 0x01
|
#define PL_OPTION_SHUFFLE 0x01
|
||||||
|
#define PL_OPTION_RESTORE 0x02
|
||||||
|
|
||||||
// Segment capability byte
|
// Segment capability byte
|
||||||
#define SEG_CAPABILITY_RGB 0x01
|
#define SEG_CAPABILITY_RGB 0x01
|
||||||
@ -511,11 +508,11 @@
|
|||||||
|
|
||||||
//this is merely a default now and can be changed at runtime
|
//this is merely a default now and can be changed at runtime
|
||||||
#ifndef LEDPIN
|
#ifndef LEDPIN
|
||||||
#if defined(ESP8266) || (defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32_PICO)
|
//#if defined(ESP8266) || (defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_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
|
#define LEDPIN 2 // GPIO2 (D4) on Wemos D1 mini compatible boards, safe to use on any board
|
||||||
#else
|
//#else
|
||||||
#define LEDPIN 16 // aligns with GPIO2 (D4) on Wemos D1 mini32 compatible boards
|
// #define LEDPIN 16 // aligns with GPIO2 (D4) on Wemos D1 mini32 compatible boards
|
||||||
#endif
|
//#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WLED_ENABLE_DMX
|
#ifdef WLED_ENABLE_DMX
|
||||||
|
@ -1290,6 +1290,7 @@ TD .checkmark, TD .radiomark {
|
|||||||
margin: 0 auto 12px;
|
margin: 0 auto 12px;
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
border: 1px solid var(--c-2);
|
border: 1px solid var(--c-2);
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Simplify segments */
|
/* Simplify segments */
|
||||||
|
@ -309,7 +309,7 @@
|
|||||||
<button class="btn infobtn" id="resetbtn" onclick="cnfReset()">Reboot WLED</button>
|
<button class="btn infobtn" id="resetbtn" onclick="cnfReset()">Reboot WLED</button>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<span class="h">Made with <span id="heart">❤︎</span> by <a href="https://github.com/Aircoookie/" target="_blank">Aircoookie</a> and the <a href="https://wled.discourse.group/" target="_blank">WLED community</a></span>
|
<span class="h">Made with <span id="heart">❤︎</span> by <a href="https://github.com/Aircoookie/" target="_blank">Aircoookie</a> and the <a href="https://wled.discourse.group/" target="_blank">WLED community</a></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="nodes" class="modal">
|
<div id="nodes" class="modal">
|
||||||
|
@ -618,7 +618,7 @@ function populatePresets(fromls)
|
|||||||
|
|
||||||
cn += `<div class="pres lstI" id="p${i}o">`;
|
cn += `<div class="pres lstI" id="p${i}o">`;
|
||||||
if (cfg.comp.pid) cn += `<div class="pid">${i}</div>`;
|
if (cfg.comp.pid) cn += `<div class="pid">${i}</div>`;
|
||||||
cn += `<div class="pname lstIname" onclick="setPreset(${i})">${isPlaylist(i)?"<i class='icons btn-icon'></i>":""}${pName(i)}
|
cn += `<div class="pname lstIname" onclick="setPreset(${i})">${i==lastinfo.leds.bootps?"<i class='icons btn-icon'></i>":""}${isPlaylist(i)?"<i class='icons btn-icon'></i>":""}${pName(i)}
|
||||||
<i class="icons edit-icon flr" id="p${i}nedit" onclick="tglSegn(${i+100})"></i></div>
|
<i class="icons edit-icon flr" id="p${i}nedit" onclick="tglSegn(${i+100})"></i></div>
|
||||||
<i class="icons e-icon flr" id="sege${i+100}" onclick="expand(${i+100})"></i>
|
<i class="icons e-icon flr" id="sege${i+100}" onclick="expand(${i+100})"></i>
|
||||||
<div class="presin lstIcontent" id="seg${i+100}"></div>
|
<div class="presin lstIcontent" id="seg${i+100}"></div>
|
||||||
@ -1959,6 +1959,7 @@ function plR(p)
|
|||||||
function makeP(i,pl)
|
function makeP(i,pl)
|
||||||
{
|
{
|
||||||
var content = "";
|
var content = "";
|
||||||
|
const bps = lastinfo.leds.bootps;
|
||||||
if (pl) {
|
if (pl) {
|
||||||
if (i===0) plJson[0] = {
|
if (i===0) plJson[0] = {
|
||||||
ps: [1],
|
ps: [1],
|
||||||
@ -1983,7 +1984,7 @@ function makeP(i,pl)
|
|||||||
<div class="sel">End preset:<br>
|
<div class="sel">End preset:<br>
|
||||||
<div class="sel-p"><select class="sel-ple" id="pl${i}selEnd" onchange="plR(${i})" data-val=${plJson[i].end?plJson[i].end:0}>
|
<div class="sel-p"><select class="sel-ple" id="pl${i}selEnd" onchange="plR(${i})" data-val=${plJson[i].end?plJson[i].end:0}>
|
||||||
<option value="0">None</option>
|
<option value="0">None</option>
|
||||||
<option value="255">Restore preset</option>
|
<option value="255" ${plJson[i].end && plJson[i].end==255?"selected":""}>Restore preset</option>
|
||||||
${makePlSel(plJson[i].end?plJson[i].end:0, true)}
|
${makePlSel(plJson[i].end?plJson[i].end:0, true)}
|
||||||
</select></div></div>
|
</select></div></div>
|
||||||
</div>
|
</div>
|
||||||
@ -2024,6 +2025,11 @@ ${makePlSel(plJson[i].end?plJson[i].end:0, true)}
|
|||||||
</div>
|
</div>
|
||||||
<div class="po2" id="p${i}o2">API command<br><textarea class="apitxt" id="p${i}api"></textarea></div>
|
<div class="po2" id="p${i}o2">API command<br><textarea class="apitxt" id="p${i}api"></textarea></div>
|
||||||
<div class="po1" id="p${i}o1">${content}</div>
|
<div class="po1" id="p${i}o1">${content}</div>
|
||||||
|
<label class="check revchkl">
|
||||||
|
<span class="lstIname">Apply at boot</span>
|
||||||
|
<input type="checkbox" id="p${i}bps" ${i==bps?"checked":""}>
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
</label>
|
||||||
<div class="c m6">Save to ID <input id="p${i}id" type="number" oninput="checkUsed(${i})" max=250 min=1 value=${(i>0)?i:getLowestUnusedP()}></div>
|
<div class="c m6">Save to ID <input id="p${i}id" type="number" oninput="checkUsed(${i})" max=250 min=1 value=${(i>0)?i:getLowestUnusedP()}></div>
|
||||||
<div class="c">
|
<div class="c">
|
||||||
<button class="btn btn-p" onclick="saveP(${i},${pl})"><i class="icons btn-icon"></i>Save</button>
|
<button class="btn btn-p" onclick="saveP(${i},${pl})"><i class="icons btn-icon"></i>Save</button>
|
||||||
@ -2445,8 +2451,9 @@ function saveP(i,pl)
|
|||||||
if (gId(`p${i}lmp`) && gId(`p${i}lmp`).value!=="") obj.ledmap = parseInt(gId(`p${i}lmp`).value);
|
if (gId(`p${i}lmp`) && gId(`p${i}lmp`).value!=="") obj.ledmap = parseInt(gId(`p${i}lmp`).value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (gId(`p${i}bps`).checked) obj.bootps = pI;
|
||||||
obj.psave = pI; obj.n = pN;
|
obj.psave = pI;
|
||||||
|
obj.n = pN;
|
||||||
var pQN = gId(`p${i}ql`).value;
|
var pQN = gId(`p${i}ql`).value;
|
||||||
if (pQN.length > 0) obj.ql = pQN;
|
if (pQN.length > 0) obj.ql = pQN;
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
function isD2P(t) { return t > 47 && t < 64; } // is digital 2 pin type
|
function isD2P(t) { return t > 47 && t < 64; } // is digital 2 pin type
|
||||||
function is16b(t) { return t == 26 || t == 29 } // is digital 16 bit type
|
function is16b(t) { return t == 26 || t == 29 } // is digital 16 bit type
|
||||||
function isVir(t) { return t >= 80 && t < 96; } // is virtual type
|
function isVir(t) { return t >= 80 && t < 96; } // is virtual type
|
||||||
|
function hasW(t) { return (t >= 18 && t <= 21) || (t >= 28 && t <= 32) || (t >= 44 && t <= 45) || (t >= 88 && t <= 89); }
|
||||||
|
function hasCCT(t) { return t == 20 || t == 21 || t == 42 || t == 45 || t == 28 || t == 32; }
|
||||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||||
function loadJS(FILE_URL, async = true) {
|
function loadJS(FILE_URL, async = true) {
|
||||||
let scE = d.createElement("script");
|
let scE = d.createElement("script");
|
||||||
@ -188,6 +190,7 @@
|
|||||||
if (isDig(t)) {
|
if (isDig(t)) {
|
||||||
if (is16b(t)) len *= 2; // 16 bit LEDs
|
if (is16b(t)) len *= 2; // 16 bit LEDs
|
||||||
if (t > 28 && t < 40) ch = 4; //RGBW
|
if (t > 28 && t < 40) ch = 4; //RGBW
|
||||||
|
if (t == 28) ch = 5; //GRBCW
|
||||||
if (maxM < 10000 && d.getElementsByName("L0"+n)[0].value == 3) { //8266 DMA uses 5x the mem
|
if (maxM < 10000 && d.getElementsByName("L0"+n)[0].value == 3) { //8266 DMA uses 5x the mem
|
||||||
mul = 5;
|
mul = 5;
|
||||||
}
|
}
|
||||||
@ -202,7 +205,7 @@
|
|||||||
|
|
||||||
function UI(change=false)
|
function UI(change=false)
|
||||||
{
|
{
|
||||||
let isRGBW = false, gRGBW = false, memu = 0;
|
let gRGBW = false, memu = 0;
|
||||||
let busMA = 0;
|
let busMA = 0;
|
||||||
let sLC = 0, sPC = 0, sDI = 0, maxLC = 0;
|
let sLC = 0, sPC = 0, sDI = 0, maxLC = 0;
|
||||||
const ablEN = d.Sf.ABL.checked;
|
const ablEN = d.Sf.ABL.checked;
|
||||||
@ -242,15 +245,15 @@
|
|||||||
d.Sf["MA"+n].min = (isVir(t) || isAna(t)) ? 0 : 250;
|
d.Sf["MA"+n].min = (isVir(t) || isAna(t)) ? 0 : 250;
|
||||||
}
|
}
|
||||||
gId("rf"+n).onclick = (t == 31) ? (()=>{return false}) : (()=>{}); // prevent change for TM1814
|
gId("rf"+n).onclick = (t == 31) ? (()=>{return false}) : (()=>{}); // prevent change for TM1814
|
||||||
gRGBW |= isRGBW = ((t > 17 && t < 22) || (t > 28 && t < 32) || (t > 40 && t < 46 && t != 43) || t == 88); // RGBW checkbox, TYPE_xxxx values from const.h
|
gRGBW |= hasW(t); // RGBW checkbox, TYPE_xxxx values from const.h
|
||||||
gId("co"+n).style.display = (isVir(t) || isAna(t)) ? "none":"inline"; // hide color order for PWM
|
gId("co"+n).style.display = (isVir(t) || isAna(t)) ? "none":"inline"; // hide color order for PWM
|
||||||
gId("dig"+n+"w").style.display = (isDig(t) && isRGBW) ? "inline":"none"; // show swap channels dropdown
|
gId("dig"+n+"w").style.display = (isDig(t) && hasW(t)) ? "inline":"none"; // show swap channels dropdown
|
||||||
if (!(isDig(t) && isRGBW)) d.Sf["WO"+n].value = 0; // reset swapping
|
if (!(isDig(t) && hasW(t))) d.Sf["WO"+n].value = 0; // reset swapping
|
||||||
gId("dig"+n+"c").style.display = (isAna(t)) ? "none":"inline"; // hide count for analog
|
gId("dig"+n+"c").style.display = (isAna(t)) ? "none":"inline"; // hide count for analog
|
||||||
gId("dig"+n+"r").style.display = (isVir(t)) ? "none":"inline"; // hide reversed for virtual
|
gId("dig"+n+"r").style.display = (isVir(t)) ? "none":"inline"; // hide reversed for virtual
|
||||||
gId("dig"+n+"s").style.display = (isVir(t) || isAna(t)) ? "none":"inline"; // hide skip 1st for virtual & analog
|
gId("dig"+n+"s").style.display = (isVir(t) || isAna(t)) ? "none":"inline"; // hide skip 1st for virtual & analog
|
||||||
gId("dig"+n+"f").style.display = (isDig(t)) ? "inline":"none"; // hide refresh
|
gId("dig"+n+"f").style.display = (isDig(t)) ? "inline":"none"; // hide refresh
|
||||||
gId("dig"+n+"a").style.display = (isRGBW) ? "inline":"none"; // auto calculate white
|
gId("dig"+n+"a").style.display = (hasW(t)) ? "inline":"none"; // auto calculate white
|
||||||
gId("dig"+n+"l").style.display = (isD2P(t) || isPWM(t)) ? "inline":"none"; // bus clock speed / PWM speed (relative) (not On/Off)
|
gId("dig"+n+"l").style.display = (isD2P(t) || isPWM(t)) ? "inline":"none"; // bus clock speed / PWM speed (relative) (not On/Off)
|
||||||
gId("rev"+n).innerHTML = isAna(t) ? "Inverted output":"Reversed (rotated 180°)"; // change reverse text for analog
|
gId("rev"+n).innerHTML = isAna(t) ? "Inverted output":"Reversed (rotated 180°)"; // change reverse text for analog
|
||||||
//gId("psd"+n).innerHTML = isAna(t) ? "Index:":"Start:"; // change analog start description
|
//gId("psd"+n).innerHTML = isAna(t) ? "Index:":"Start:"; // change analog start description
|
||||||
@ -383,7 +386,9 @@ ${i+1}:
|
|||||||
<option value="25">TM1829</option>\
|
<option value="25">TM1829</option>\
|
||||||
<option value="26">UCS8903</option>\
|
<option value="26">UCS8903</option>\
|
||||||
<option value="27">APA106/PL9823</option>\
|
<option value="27">APA106/PL9823</option>\
|
||||||
|
<option value="28">FW1906 GRBCW</option>\
|
||||||
<option value="29">UCS8904 RGBW</option>\
|
<option value="29">UCS8904 RGBW</option>\
|
||||||
|
<option value="32">WS2805 RGBCW</option>\
|
||||||
<option value="50">WS2801</option>\
|
<option value="50">WS2801</option>\
|
||||||
<option value="51">APA102</option>\
|
<option value="51">APA102</option>\
|
||||||
<option value="52">LPD8806</option>\
|
<option value="52">LPD8806</option>\
|
||||||
@ -861,6 +866,7 @@ Swap: <select id="xw${i}" name="XW${i}">
|
|||||||
</select>
|
</select>
|
||||||
<br>
|
<br>
|
||||||
Calculate CCT from RGB: <input type="checkbox" name="CR"><br>
|
Calculate CCT from RGB: <input type="checkbox" name="CR"><br>
|
||||||
|
CCT IC used (Athom 15W): <input type="checkbox" name="IC"><br>
|
||||||
CCT additive blending: <input type="number" class="s" min="0" max="100" name="CB" required> %
|
CCT additive blending: <input type="number" class="s" min="0" max="100" name="CB" required> %
|
||||||
</div>
|
</div>
|
||||||
<h3>Advanced</h3>
|
<h3>Advanced</h3>
|
||||||
|
@ -133,11 +133,11 @@
|
|||||||
<div>Restore configuration<br><input type="file" name="data2" accept=".json"> <button type="button" onclick="uploadFile(d.Sf.data2,'/cfg.json');">Upload</button><br></div>
|
<div>Restore configuration<br><input type="file" name="data2" accept=".json"> <button type="button" onclick="uploadFile(d.Sf.data2,'/cfg.json');">Upload</button><br></div>
|
||||||
<hr>
|
<hr>
|
||||||
<h3>About</h3>
|
<h3>About</h3>
|
||||||
<a href="https://github.com/Aircoookie/WLED/" target="_blank">WLED</a> version ##VERSION##<!-- Autoreplaced from package.json --><br><br>
|
<a href="https://github.com/Aircoookie/WLED/" target="_blank">WLED</a> version ##VERSION##<!-- Autoreplaced from package.json --><br><br>
|
||||||
<a href="https://github.com/Aircoookie/WLED/wiki/Contributors-and-credits" target="_blank">Contributors, dependencies and special thanks</a><br>
|
<a href="https://github.com/Aircoookie/WLED/wiki/Contributors-and-credits" target="_blank">Contributors, dependencies and special thanks</a><br>
|
||||||
A huge thank you to everyone who helped me create WLED!<br><br>
|
A huge thank you to everyone who helped me create WLED!<br><br>
|
||||||
(c) 2016-2023 Christian Schwinne <br>
|
(c) 2016-2024 Christian Schwinne <br>
|
||||||
<i>Licensed under the <a href="https://github.com/Aircoookie/WLED/blob/master/LICENSE" target="_blank">MIT license</a></i><br><br>
|
<i>Licensed under the <a href="https://github.com/Aircoookie/WLED/blob/master/LICENSE" target="_blank">MIT license</a></i><br><br>
|
||||||
Server message: <span class="sip"> Response error! </span><hr>
|
Server message: <span class="sip"> Response error! </span><hr>
|
||||||
<div id="toast"></div>
|
<div id="toast"></div>
|
||||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||||
|
@ -84,7 +84,7 @@
|
|||||||
option.textContent = "Other network...";
|
option.textContent = "Other network...";
|
||||||
select.appendChild(option);
|
select.appendChild(option);
|
||||||
|
|
||||||
if (input.value === "" || found) input.replaceWith(select);
|
if (input.value === "" || input.value === "Your_Network" || found) input.replaceWith(select);
|
||||||
else select.remove();
|
else select.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
//DDP protocol support, called by handleE131Packet
|
//DDP protocol support, called by handleE131Packet
|
||||||
//handles RGB data only
|
//handles RGB data only
|
||||||
void handleDDPPacket(e131_packet_t* p) {
|
void handleDDPPacket(e131_packet_t* p) {
|
||||||
|
static bool ddpSeenPush = false; // have we seen a push yet?
|
||||||
int lastPushSeq = e131LastSequenceNumber[0];
|
int lastPushSeq = e131LastSequenceNumber[0];
|
||||||
|
|
||||||
//reject late packets belonging to previous frame (assuming 4 packets max. before push)
|
//reject late packets belonging to previous frame (assuming 4 packets max. before push)
|
||||||
@ -34,6 +35,7 @@ void handleDDPPacket(e131_packet_t* p) {
|
|||||||
uint16_t c = 0;
|
uint16_t c = 0;
|
||||||
if (p->flags & DDP_TIMECODE_FLAG) c = 4; //packet has timecode flag, we do not support it, but data starts 4 bytes later
|
if (p->flags & DDP_TIMECODE_FLAG) c = 4; //packet has timecode flag, we do not support it, but data starts 4 bytes later
|
||||||
|
|
||||||
|
if (realtimeMode != REALTIME_MODE_DDP) ddpSeenPush = false; // just starting, no push yet
|
||||||
realtimeLock(realtimeTimeoutMs, REALTIME_MODE_DDP);
|
realtimeLock(realtimeTimeoutMs, REALTIME_MODE_DDP);
|
||||||
|
|
||||||
if (!realtimeOverride || (realtimeMode && useMainSegmentOnly)) {
|
if (!realtimeOverride || (realtimeMode && useMainSegmentOnly)) {
|
||||||
@ -44,7 +46,8 @@ void handleDDPPacket(e131_packet_t* p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool push = p->flags & DDP_PUSH_FLAG;
|
bool push = p->flags & DDP_PUSH_FLAG;
|
||||||
if (push) {
|
ddpSeenPush |= push;
|
||||||
|
if (!ddpSeenPush || push) { // if we've never seen a push, or this is one, render display
|
||||||
e131NewData = true;
|
e131NewData = true;
|
||||||
byte sn = p->sequenceNum & 0xF;
|
byte sn = p->sequenceNum & 0xF;
|
||||||
if (sn) e131LastSequenceNumber[0] = sn;
|
if (sn) e131LastSequenceNumber[0] = sn;
|
||||||
@ -184,7 +187,6 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){
|
|||||||
// only apply preset if not in playlist, or playlist changed
|
// only apply preset if not in playlist, or playlist changed
|
||||||
(currentPlaylist < 0 || dmxValPreset != currentPlaylist)) {
|
(currentPlaylist < 0 || dmxValPreset != currentPlaylist)) {
|
||||||
presetCycCurr = dmxValPreset;
|
presetCycCurr = dmxValPreset;
|
||||||
unloadPlaylist(); // applying a preset unloads the playlist
|
|
||||||
applyPreset(dmxValPreset, CALL_MODE_NOTIFICATION);
|
applyPreset(dmxValPreset, CALL_MODE_NOTIFICATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,6 +233,7 @@ const char *getPresetsFileName(bool persistent = true);
|
|||||||
void initPresetsFile();
|
void initPresetsFile();
|
||||||
void handlePresets();
|
void handlePresets();
|
||||||
bool applyPreset(byte index, byte callMode = CALL_MODE_DIRECT_CHANGE);
|
bool applyPreset(byte index, byte callMode = CALL_MODE_DIRECT_CHANGE);
|
||||||
|
bool applyPresetFromPlaylist(byte index);
|
||||||
void applyPresetWithFallback(uint8_t presetID, uint8_t callMode, uint8_t effectID = 0, uint8_t paletteID = 0);
|
void applyPresetWithFallback(uint8_t presetID, uint8_t callMode, uint8_t effectID = 0, uint8_t paletteID = 0);
|
||||||
inline bool applyTemporaryPreset() {return applyPreset(255);};
|
inline bool applyTemporaryPreset() {return applyPreset(255);};
|
||||||
void savePreset(byte index, const char* pname = nullptr, JsonObject saveobj = JsonObject());
|
void savePreset(byte index, const char* pname = nullptr, JsonObject saveobj = JsonObject());
|
||||||
@ -434,7 +435,6 @@ void handleSerial();
|
|||||||
void updateBaudRate(uint32_t rate);
|
void updateBaudRate(uint32_t rate);
|
||||||
|
|
||||||
//wled_server.cpp
|
//wled_server.cpp
|
||||||
String getFileContentType(String &filename);
|
|
||||||
void createEditHandler(bool enable);
|
void createEditHandler(bool enable);
|
||||||
void initServer();
|
void initServer();
|
||||||
void serveMessage(AsyncWebServerRequest* request, uint16_t code, const String& headl, const String& subl="", byte optionT=255);
|
void serveMessage(AsyncWebServerRequest* request, uint16_t code, const String& headl, const String& subl="", byte optionT=255);
|
||||||
|
@ -375,20 +375,16 @@ void updateFSInfo() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
|
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
// caching presets in PSRAM may prevent occasional flashes seen when HomeAssitant polls WLED
|
// caching presets in PSRAM may prevent occasional flashes seen when HomeAssitant polls WLED
|
||||||
// original idea by @akaricchi (https://github.com/Akaricchi)
|
// original idea by @akaricchi (https://github.com/Akaricchi)
|
||||||
// returns a pointer to the PSRAM buffer updates size parameter
|
// returns a pointer to the PSRAM buffer, updates size parameter
|
||||||
static const uint8_t *getPresetCache(size_t &size) {
|
static const uint8_t *getPresetCache(size_t &size) {
|
||||||
static unsigned long presetsCachedTime;
|
static unsigned long presetsCachedTime;
|
||||||
static uint8_t *presetsCached;
|
static uint8_t *presetsCached;
|
||||||
static size_t presetsCachedSize;
|
static size_t presetsCachedSize;
|
||||||
|
|
||||||
if (!psramFound()) {
|
|
||||||
size = 0;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (presetsModifiedTime != presetsCachedTime) {
|
if (presetsModifiedTime != presetsCachedTime) {
|
||||||
if (presetsCached) {
|
if (presetsCached) {
|
||||||
free(presetsCached);
|
free(presetsCached);
|
||||||
@ -420,26 +416,19 @@ bool handleFileRead(AsyncWebServerRequest* request, String path){
|
|||||||
DEBUG_PRINT(F("WS FileRead: ")); DEBUG_PRINTLN(path);
|
DEBUG_PRINT(F("WS FileRead: ")); DEBUG_PRINTLN(path);
|
||||||
if(path.endsWith("/")) path += "index.htm";
|
if(path.endsWith("/")) path += "index.htm";
|
||||||
if(path.indexOf(F("sec")) > -1) return false;
|
if(path.indexOf(F("sec")) > -1) return false;
|
||||||
String contentType = getFileContentType(path);
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
if(request->hasArg(F("download"))) contentType = F("application/octet-stream");
|
if (psramSafe && psramFound() && path.endsWith(FPSTR(getPresetsFileName()))) {
|
||||||
/*String pathWithGz = path + ".gz";
|
|
||||||
if(WLED_FS.exists(pathWithGz)){
|
|
||||||
request->send(WLED_FS, pathWithGz, contentType);
|
|
||||||
return true;
|
|
||||||
}*/
|
|
||||||
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
|
|
||||||
if (path.endsWith(FPSTR(getPresetsFileName()))) {
|
|
||||||
size_t psize;
|
size_t psize;
|
||||||
const uint8_t *presets = getPresetCache(psize);
|
const uint8_t *presets = getPresetCache(psize);
|
||||||
if (presets) {
|
if (presets) {
|
||||||
AsyncWebServerResponse *response = request->beginResponse_P(200, contentType, presets, psize);
|
AsyncWebServerResponse *response = request->beginResponse_P(200, FPSTR(CONTENT_TYPE_JSON), presets, psize);
|
||||||
request->send(response);
|
request->send(response);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(WLED_FS.exists(path)) {
|
if(WLED_FS.exists(path) || WLED_FS.exists(path + ".gz")) {
|
||||||
request->send(WLED_FS, path, contentType);
|
request->send(WLED_FS, path, String(), request->hasArg(F("download")));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -210,7 +210,7 @@ void sendImprovInfoResponse() {
|
|||||||
//Use serverDescription if it has been changed from the default "WLED", else mDNS name
|
//Use serverDescription if it has been changed from the default "WLED", else mDNS name
|
||||||
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
|
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
|
||||||
char vString[20];
|
char vString[20];
|
||||||
sprintf_P(vString, PSTR("0.15.0-b1/%i"), VERSION);
|
sprintf_P(vString, PSTR("0.15.0-b2/%i"), VERSION);
|
||||||
const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription};
|
const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription};
|
||||||
|
|
||||||
sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str);
|
sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str);
|
||||||
|
@ -142,28 +142,42 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
{
|
{
|
||||||
if (seg.getLightCapabilities() & 3) {
|
if (seg.getLightCapabilities() & 3) {
|
||||||
// segment has RGB or White
|
// segment has RGB or White
|
||||||
for (size_t i = 0; i < 3; i++)
|
for (size_t i = 0; i < NUM_COLORS; i++) {
|
||||||
{
|
// JSON "col" array can contain the following values for each of segment's colors (primary, background, custom):
|
||||||
|
// "col":[int|string|object|array, int|string|object|array, int|string|object|array]
|
||||||
|
// int = Kelvin temperature or 0 for black
|
||||||
|
// string = hex representation of [WW]RRGGBB
|
||||||
|
// object = individual channel control {"r":0,"g":127,"b":255,"w":255}, each being optional (valid to send {})
|
||||||
|
// array = direct channel values [r,g,b,w] (w element being optional)
|
||||||
int rgbw[] = {0,0,0,0};
|
int rgbw[] = {0,0,0,0};
|
||||||
bool colValid = false;
|
bool colValid = false;
|
||||||
JsonArray colX = colarr[i];
|
JsonArray colX = colarr[i];
|
||||||
if (colX.isNull()) {
|
if (colX.isNull()) {
|
||||||
byte brgbw[] = {0,0,0,0};
|
JsonObject oCol = colarr[i];
|
||||||
const char* hexCol = colarr[i];
|
if (!oCol.isNull()) {
|
||||||
if (hexCol == nullptr) { //Kelvin color temperature (or invalid), e.g 2400
|
// we have a JSON object for color {"w":123,"r":123,...}; allows individual channel control
|
||||||
int kelvin = colarr[i] | -1;
|
rgbw[0] = oCol["r"] | R(seg.colors[i]);
|
||||||
if (kelvin < 0) continue;
|
rgbw[1] = oCol["g"] | G(seg.colors[i]);
|
||||||
if (kelvin == 0) seg.setColor(i, 0);
|
rgbw[2] = oCol["b"] | B(seg.colors[i]);
|
||||||
if (kelvin > 0) colorKtoRGB(kelvin, brgbw);
|
rgbw[3] = oCol["w"] | W(seg.colors[i]);
|
||||||
colValid = true;
|
colValid = true;
|
||||||
} else { //HEX string, e.g. "FFAA00"
|
} else {
|
||||||
colValid = colorFromHexString(brgbw, hexCol);
|
byte brgbw[] = {0,0,0,0};
|
||||||
|
const char* hexCol = colarr[i];
|
||||||
|
if (hexCol == nullptr) { //Kelvin color temperature (or invalid), e.g 2400
|
||||||
|
int kelvin = colarr[i] | -1;
|
||||||
|
if (kelvin < 0) continue;
|
||||||
|
if (kelvin == 0) seg.setColor(i, 0);
|
||||||
|
if (kelvin > 0) colorKtoRGB(kelvin, brgbw);
|
||||||
|
colValid = true;
|
||||||
|
} else { //HEX string, e.g. "FFAA00"
|
||||||
|
colValid = colorFromHexString(brgbw, hexCol);
|
||||||
|
}
|
||||||
|
for (size_t c = 0; c < 4; c++) rgbw[c] = brgbw[c];
|
||||||
}
|
}
|
||||||
for (size_t c = 0; c < 4; c++) rgbw[c] = brgbw[c];
|
|
||||||
} else { //Array of ints (RGB or RGBW color), e.g. [255,160,0]
|
} else { //Array of ints (RGB or RGBW color), e.g. [255,160,0]
|
||||||
byte sz = colX.size();
|
byte sz = colX.size();
|
||||||
if (sz == 0) continue; //do nothing on empty array
|
if (sz == 0) continue; //do nothing on empty array
|
||||||
|
|
||||||
copyArray(colX, rgbw, 4);
|
copyArray(colX, rgbw, 4);
|
||||||
colValid = true;
|
colValid = true;
|
||||||
}
|
}
|
||||||
@ -226,14 +240,19 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
getVal(elem["ix"], &seg.intensity);
|
getVal(elem["ix"], &seg.intensity);
|
||||||
|
|
||||||
uint8_t pal = seg.palette;
|
uint8_t pal = seg.palette;
|
||||||
|
last = strip.getPaletteCount();
|
||||||
|
if (!elem["pal"].isNull() && elem["pal"].is<const char*>()) {
|
||||||
|
const char *tmp = elem["pal"].as<const char *>();
|
||||||
|
if (strlen(tmp) > 3 && (strchr(tmp,'r') || strchr(tmp,'~') != strrchr(tmp,'~'))) last = 0; // we have "X~Y(r|[w]~[-])" form
|
||||||
|
}
|
||||||
if (seg.getLightCapabilities() & 1) { // ignore palette for White and On/Off segments
|
if (seg.getLightCapabilities() & 1) { // ignore palette for White and On/Off segments
|
||||||
if (getVal(elem["pal"], &pal)) seg.setPalette(pal);
|
if (getVal(elem["pal"], &pal, 0, last)) seg.setPalette(pal);
|
||||||
}
|
}
|
||||||
|
|
||||||
getVal(elem["c1"], &seg.custom1);
|
getVal(elem["c1"], &seg.custom1);
|
||||||
getVal(elem["c2"], &seg.custom2);
|
getVal(elem["c2"], &seg.custom2);
|
||||||
uint8_t cust3 = seg.custom3;
|
uint8_t cust3 = seg.custom3;
|
||||||
getVal(elem["c3"], &cust3); // we can't pass reference to bitfield
|
getVal(elem["c3"], &cust3, 0, 31); // we can't pass reference to bitfield
|
||||||
seg.custom3 = constrain(cust3, 0, 31);
|
seg.custom3 = constrain(cust3, 0, 31);
|
||||||
|
|
||||||
seg.check1 = getBoolVal(elem["o1"], seg.check1);
|
seg.check1 = getBoolVal(elem["o1"], seg.check1);
|
||||||
@ -298,7 +317,7 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// deserializes WLED state (fileDoc points to doc object if called from web server)
|
// deserializes WLED state
|
||||||
// presetId is non-0 if called from handlePreset()
|
// presetId is non-0 if called from handlePreset()
|
||||||
bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
||||||
{
|
{
|
||||||
@ -442,13 +461,11 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
|||||||
currentPreset = root[F("pd")] | currentPreset;
|
currentPreset = root[F("pd")] | currentPreset;
|
||||||
if (root["win"].isNull()) presetCycCurr = currentPreset; // otherwise it was set in handleSet() [set.cpp]
|
if (root["win"].isNull()) presetCycCurr = currentPreset; // otherwise it was set in handleSet() [set.cpp]
|
||||||
presetToRestore = currentPreset; // stateUpdated() will clear the preset, so we need to restore it after
|
presetToRestore = currentPreset; // stateUpdated() will clear the preset, so we need to restore it after
|
||||||
//unloadPlaylist(); // applying a preset unloads the playlist, may be needed here too?
|
|
||||||
} else if (!root["ps"].isNull()) {
|
} else if (!root["ps"].isNull()) {
|
||||||
ps = presetCycCurr;
|
ps = presetCycCurr;
|
||||||
if (root["win"].isNull() && getVal(root["ps"], &ps, 0, 0) && ps > 0 && ps < 251 && ps != currentPreset) {
|
if (root["win"].isNull() && getVal(root["ps"], &ps, 0, 0) && ps > 0 && ps < 251 && ps != currentPreset) {
|
||||||
// b) preset ID only or preset that does not change state (use embedded cycling limits if they exist in getVal())
|
// b) preset ID only or preset that does not change state (use embedded cycling limits if they exist in getVal())
|
||||||
presetCycCurr = ps;
|
presetCycCurr = ps;
|
||||||
unloadPlaylist(); // applying a preset unloads the playlist
|
|
||||||
applyPreset(ps, callMode); // async load from file system (only preset ID was specified)
|
applyPreset(ps, callMode); // async load from file system (only preset ID was specified)
|
||||||
return stateResponse;
|
return stateResponse;
|
||||||
}
|
}
|
||||||
@ -628,6 +645,7 @@ void serializeInfo(JsonObject root)
|
|||||||
leds[F("maxseg")] = strip.getMaxSegments();
|
leds[F("maxseg")] = strip.getMaxSegments();
|
||||||
//leds[F("actseg")] = strip.getActiveSegmentsNum();
|
//leds[F("actseg")] = strip.getActiveSegmentsNum();
|
||||||
//leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config
|
//leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config
|
||||||
|
leds[F("bootps")] = bootPreset;
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
if (strip.isMatrix) {
|
if (strip.isMatrix) {
|
||||||
@ -748,8 +766,8 @@ void serializeInfo(JsonObject root)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
root[F("freeheap")] = ESP.getFreeHeap();
|
root[F("freeheap")] = ESP.getFreeHeap();
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
if (psramFound()) root[F("psram")] = ESP.getFreePsram();
|
if (psramSafe && psramFound()) root[F("psram")] = ESP.getFreePsram();
|
||||||
#endif
|
#endif
|
||||||
root[F("uptime")] = millis()/1000 + rolloverMillis*4294967;
|
root[F("uptime")] = millis()/1000 + rolloverMillis*4294967;
|
||||||
|
|
||||||
@ -851,8 +869,8 @@ void serializePalettes(JsonObject root, int page)
|
|||||||
int itemPerPage = 8;
|
int itemPerPage = 8;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int palettesCount = strip.getPaletteCount();
|
|
||||||
int customPalettes = strip.customPalettes.size();
|
int customPalettes = strip.customPalettes.size();
|
||||||
|
int palettesCount = strip.getPaletteCount() - customPalettes;
|
||||||
|
|
||||||
int maxPage = (palettesCount + customPalettes -1) / itemPerPage;
|
int maxPage = (palettesCount + customPalettes -1) / itemPerPage;
|
||||||
if (page > maxPage) page = maxPage;
|
if (page > maxPage) page = maxPage;
|
||||||
@ -1064,7 +1082,7 @@ void serveJson(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (url.indexOf("pal") > 0) {
|
else if (url.indexOf("pal") > 0) {
|
||||||
request->send_P(200, "application/json", JSON_palette_names); // contentType defined in AsyncJson-v6.h
|
request->send_P(200, FPSTR(CONTENT_TYPE_JSON), JSON_palette_names);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (url.indexOf(F("cfg")) > 0 && handleFileRead(request, F("/cfg.json"))) {
|
else if (url.indexOf(F("cfg")) > 0 && handleFileRead(request, F("/cfg.json"))) {
|
||||||
@ -1151,10 +1169,10 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char buffer[2048]; // shoud be enough for 256 LEDs [RRGGBB] + all other text (9+25)
|
DynamicBuffer buffer(9 + (9*(1+(used/n))) + 7 + 5 + 6 + 5 + 6 + 5 + 2);
|
||||||
strcpy_P(buffer, PSTR("{\"leds\":["));
|
char* buf = buffer.data(); // assign buffer for oappnd() functions
|
||||||
obuf = buffer; // assign buffer for oappnd() functions
|
strncpy_P(buffer.data(), PSTR("{\"leds\":["), buffer.size());
|
||||||
olen = 9;
|
buf += 9; // sizeof(PSTR()) from last line
|
||||||
|
|
||||||
for (size_t i = 0; i < used; i += n)
|
for (size_t i = 0; i < used; i += n)
|
||||||
{
|
{
|
||||||
@ -1169,29 +1187,27 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
|
|||||||
r = scale8(qadd8(w, r), strip.getBrightness()); //R, add white channel to RGB channels as a simple RGBW -> RGB map
|
r = scale8(qadd8(w, r), strip.getBrightness()); //R, add white channel to RGB channels as a simple RGBW -> RGB map
|
||||||
g = scale8(qadd8(w, g), strip.getBrightness()); //G
|
g = scale8(qadd8(w, g), strip.getBrightness()); //G
|
||||||
b = scale8(qadd8(w, b), strip.getBrightness()); //B
|
b = scale8(qadd8(w, b), strip.getBrightness()); //B
|
||||||
olen += sprintf_P(obuf + olen, PSTR("\"%06X\","), RGBW32(r,g,b,0));
|
buf += sprintf_P(buf, PSTR("\"%06X\","), RGBW32(r,g,b,0));
|
||||||
}
|
}
|
||||||
olen -= 1;
|
buf--; // remove last comma
|
||||||
oappend((const char*)F("],\"n\":"));
|
buf += sprintf_P(buf, PSTR("],\"n\":%d"), n);
|
||||||
oappendi(n);
|
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
if (strip.isMatrix) {
|
if (strip.isMatrix) {
|
||||||
oappend((const char*)F(",\"w\":"));
|
buf += sprintf_P(buf, PSTR(",\"w\":%d"), Segment::maxWidth/n);
|
||||||
oappendi(Segment::maxWidth/n);
|
buf += sprintf_P(buf, PSTR(",\"h\":%d"), Segment::maxHeight/n);
|
||||||
oappend((const char*)F(",\"h\":"));
|
|
||||||
oappendi(Segment::maxHeight/n);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
oappend("}");
|
(*buf++) = '}';
|
||||||
|
(*buf++) = 0;
|
||||||
|
|
||||||
if (request) {
|
if (request) {
|
||||||
request->send(200, "application/json", buffer); // contentType defined in AsyncJson-v6.h
|
request->send(200, FPSTR(CONTENT_TYPE_JSON), toString(std::move(buffer)));
|
||||||
}
|
}
|
||||||
#ifdef WLED_ENABLE_WEBSOCKETS
|
#ifdef WLED_ENABLE_WEBSOCKETS
|
||||||
else {
|
else {
|
||||||
wsc->text(obuf, olen);
|
wsc->text(toString(std::move(buffer)));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
obuf = nullptr;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -172,7 +172,9 @@ void updateInterfaces(uint8_t callMode)
|
|||||||
espalexaDevice->setColor(col[0], col[1], col[2]);
|
espalexaDevice->setColor(col[0], col[1], col[2]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
doPublishMqtt = true;
|
#ifndef WLED_DISABLE_MQTT
|
||||||
|
publishMqtt();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -180,9 +182,6 @@ void handleTransitions()
|
|||||||
{
|
{
|
||||||
//handle still pending interface update
|
//handle still pending interface update
|
||||||
updateInterfaces(interfaceUpdateCallMode);
|
updateInterfaces(interfaceUpdateCallMode);
|
||||||
#ifndef WLED_DISABLE_MQTT
|
|
||||||
if (doPublishMqtt) publishMqtt();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (transitionActive && strip.getTransition() > 0) {
|
if (transitionActive && strip.getTransition() > 0) {
|
||||||
float tper = (millis() - transitionStartTime)/(float)strip.getTransition();
|
float tper = (millis() - transitionStartTime)/(float)strip.getTransition();
|
||||||
|
395
wled00/mqtt.cpp
395
wled00/mqtt.cpp
@ -1,198 +1,197 @@
|
|||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MQTT communication protocol for home automation
|
* MQTT communication protocol for home automation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef WLED_ENABLE_MQTT
|
#ifdef WLED_ENABLE_MQTT
|
||||||
#define MQTT_KEEP_ALIVE_TIME 60 // contact the MQTT broker every 60 seconds
|
#define MQTT_KEEP_ALIVE_TIME 60 // contact the MQTT broker every 60 seconds
|
||||||
|
|
||||||
void parseMQTTBriPayload(char* payload)
|
void parseMQTTBriPayload(char* payload)
|
||||||
{
|
{
|
||||||
if (strstr(payload, "ON") || strstr(payload, "on") || strstr(payload, "true")) {bri = briLast; stateUpdated(CALL_MODE_DIRECT_CHANGE);}
|
if (strstr(payload, "ON") || strstr(payload, "on") || strstr(payload, "true")) {bri = briLast; stateUpdated(CALL_MODE_DIRECT_CHANGE);}
|
||||||
else if (strstr(payload, "T" ) || strstr(payload, "t" )) {toggleOnOff(); stateUpdated(CALL_MODE_DIRECT_CHANGE);}
|
else if (strstr(payload, "T" ) || strstr(payload, "t" )) {toggleOnOff(); stateUpdated(CALL_MODE_DIRECT_CHANGE);}
|
||||||
else {
|
else {
|
||||||
uint8_t in = strtoul(payload, NULL, 10);
|
uint8_t in = strtoul(payload, NULL, 10);
|
||||||
if (in == 0 && bri > 0) briLast = bri;
|
if (in == 0 && bri > 0) briLast = bri;
|
||||||
bri = in;
|
bri = in;
|
||||||
stateUpdated(CALL_MODE_DIRECT_CHANGE);
|
stateUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void onMqttConnect(bool sessionPresent)
|
void onMqttConnect(bool sessionPresent)
|
||||||
{
|
{
|
||||||
//(re)subscribe to required topics
|
//(re)subscribe to required topics
|
||||||
char subuf[38];
|
char subuf[38];
|
||||||
|
|
||||||
if (mqttDeviceTopic[0] != 0) {
|
if (mqttDeviceTopic[0] != 0) {
|
||||||
strlcpy(subuf, mqttDeviceTopic, 33);
|
strlcpy(subuf, mqttDeviceTopic, 33);
|
||||||
mqtt->subscribe(subuf, 0);
|
mqtt->subscribe(subuf, 0);
|
||||||
strcat_P(subuf, PSTR("/col"));
|
strcat_P(subuf, PSTR("/col"));
|
||||||
mqtt->subscribe(subuf, 0);
|
mqtt->subscribe(subuf, 0);
|
||||||
strlcpy(subuf, mqttDeviceTopic, 33);
|
strlcpy(subuf, mqttDeviceTopic, 33);
|
||||||
strcat_P(subuf, PSTR("/api"));
|
strcat_P(subuf, PSTR("/api"));
|
||||||
mqtt->subscribe(subuf, 0);
|
mqtt->subscribe(subuf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mqttGroupTopic[0] != 0) {
|
if (mqttGroupTopic[0] != 0) {
|
||||||
strlcpy(subuf, mqttGroupTopic, 33);
|
strlcpy(subuf, mqttGroupTopic, 33);
|
||||||
mqtt->subscribe(subuf, 0);
|
mqtt->subscribe(subuf, 0);
|
||||||
strcat_P(subuf, PSTR("/col"));
|
strcat_P(subuf, PSTR("/col"));
|
||||||
mqtt->subscribe(subuf, 0);
|
mqtt->subscribe(subuf, 0);
|
||||||
strlcpy(subuf, mqttGroupTopic, 33);
|
strlcpy(subuf, mqttGroupTopic, 33);
|
||||||
strcat_P(subuf, PSTR("/api"));
|
strcat_P(subuf, PSTR("/api"));
|
||||||
mqtt->subscribe(subuf, 0);
|
mqtt->subscribe(subuf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
usermods.onMqttConnect(sessionPresent);
|
usermods.onMqttConnect(sessionPresent);
|
||||||
|
|
||||||
doPublishMqtt = true;
|
DEBUG_PRINTLN(F("MQTT ready"));
|
||||||
DEBUG_PRINTLN(F("MQTT ready"));
|
publishMqtt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
|
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
|
||||||
static char *payloadStr;
|
static char *payloadStr;
|
||||||
|
|
||||||
DEBUG_PRINT(F("MQTT msg: "));
|
DEBUG_PRINT(F("MQTT msg: "));
|
||||||
DEBUG_PRINTLN(topic);
|
DEBUG_PRINTLN(topic);
|
||||||
|
|
||||||
// paranoia check to avoid npe if no payload
|
// paranoia check to avoid npe if no payload
|
||||||
if (payload==nullptr) {
|
if (payload==nullptr) {
|
||||||
DEBUG_PRINTLN(F("no payload -> leave"));
|
DEBUG_PRINTLN(F("no payload -> leave"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 0) { // start (1st partial packet or the only packet)
|
if (index == 0) { // start (1st partial packet or the only packet)
|
||||||
if (payloadStr) delete[] payloadStr; // fail-safe: release buffer
|
if (payloadStr) delete[] payloadStr; // fail-safe: release buffer
|
||||||
payloadStr = new char[total+1]; // allocate new buffer
|
payloadStr = new char[total+1]; // allocate new buffer
|
||||||
}
|
}
|
||||||
if (payloadStr == nullptr) return; // buffer not allocated
|
if (payloadStr == nullptr) return; // buffer not allocated
|
||||||
|
|
||||||
// copy (partial) packet to buffer and 0-terminate it if it is last packet
|
// copy (partial) packet to buffer and 0-terminate it if it is last packet
|
||||||
char* buff = payloadStr + index;
|
char* buff = payloadStr + index;
|
||||||
memcpy(buff, payload, len);
|
memcpy(buff, payload, len);
|
||||||
if (index + len >= total) { // at end
|
if (index + len >= total) { // at end
|
||||||
payloadStr[total] = '\0'; // terminate c style string
|
payloadStr[total] = '\0'; // terminate c style string
|
||||||
} else {
|
} else {
|
||||||
DEBUG_PRINTLN(F("Partial packet received."));
|
DEBUG_PRINTLN(F("MQTT partial packet received."));
|
||||||
return; // process next packet
|
return; // process next packet
|
||||||
}
|
}
|
||||||
DEBUG_PRINTLN(payloadStr);
|
DEBUG_PRINTLN(payloadStr);
|
||||||
|
|
||||||
size_t topicPrefixLen = strlen(mqttDeviceTopic);
|
size_t topicPrefixLen = strlen(mqttDeviceTopic);
|
||||||
if (strncmp(topic, mqttDeviceTopic, topicPrefixLen) == 0) {
|
if (strncmp(topic, mqttDeviceTopic, topicPrefixLen) == 0) {
|
||||||
topic += topicPrefixLen;
|
topic += topicPrefixLen;
|
||||||
} else {
|
} else {
|
||||||
topicPrefixLen = strlen(mqttGroupTopic);
|
topicPrefixLen = strlen(mqttGroupTopic);
|
||||||
if (strncmp(topic, mqttGroupTopic, topicPrefixLen) == 0) {
|
if (strncmp(topic, mqttGroupTopic, topicPrefixLen) == 0) {
|
||||||
topic += topicPrefixLen;
|
topic += topicPrefixLen;
|
||||||
} else {
|
} else {
|
||||||
// Non-Wled Topic used here. Probably a usermod subscribed to this topic.
|
// Non-Wled Topic used here. Probably a usermod subscribed to this topic.
|
||||||
usermods.onMqttMessage(topic, payloadStr);
|
usermods.onMqttMessage(topic, payloadStr);
|
||||||
delete[] payloadStr;
|
delete[] payloadStr;
|
||||||
payloadStr = nullptr;
|
payloadStr = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Prefix is stripped from the topic at this point
|
//Prefix is stripped from the topic at this point
|
||||||
|
|
||||||
if (strcmp_P(topic, PSTR("/col")) == 0) {
|
if (strcmp_P(topic, PSTR("/col")) == 0) {
|
||||||
colorFromDecOrHexString(col, payloadStr);
|
colorFromDecOrHexString(col, payloadStr);
|
||||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||||
} else if (strcmp_P(topic, PSTR("/api")) == 0) {
|
} else if (strcmp_P(topic, PSTR("/api")) == 0) {
|
||||||
if (!requestJSONBufferLock(15)) {
|
if (!requestJSONBufferLock(15)) {
|
||||||
delete[] payloadStr;
|
delete[] payloadStr;
|
||||||
payloadStr = nullptr;
|
payloadStr = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (payloadStr[0] == '{') { //JSON API
|
if (payloadStr[0] == '{') { //JSON API
|
||||||
deserializeJson(*pDoc, payloadStr);
|
deserializeJson(*pDoc, payloadStr);
|
||||||
deserializeState(pDoc->as<JsonObject>());
|
deserializeState(pDoc->as<JsonObject>());
|
||||||
} else { //HTTP API
|
} else { //HTTP API
|
||||||
String apireq = "win"; apireq += '&'; // reduce flash string usage
|
String apireq = "win"; apireq += '&'; // reduce flash string usage
|
||||||
apireq += payloadStr;
|
apireq += payloadStr;
|
||||||
handleSet(nullptr, apireq);
|
handleSet(nullptr, apireq);
|
||||||
}
|
}
|
||||||
releaseJSONBufferLock();
|
releaseJSONBufferLock();
|
||||||
} else if (strlen(topic) != 0) {
|
} else if (strlen(topic) != 0) {
|
||||||
// non standard topic, check with usermods
|
// non standard topic, check with usermods
|
||||||
usermods.onMqttMessage(topic, payloadStr);
|
usermods.onMqttMessage(topic, payloadStr);
|
||||||
} else {
|
} else {
|
||||||
// topmost topic (just wled/MAC)
|
// topmost topic (just wled/MAC)
|
||||||
parseMQTTBriPayload(payloadStr);
|
parseMQTTBriPayload(payloadStr);
|
||||||
}
|
}
|
||||||
delete[] payloadStr;
|
delete[] payloadStr;
|
||||||
payloadStr = nullptr;
|
payloadStr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void publishMqtt()
|
void publishMqtt()
|
||||||
{
|
{
|
||||||
doPublishMqtt = false;
|
if (!WLED_MQTT_CONNECTED) return;
|
||||||
if (!WLED_MQTT_CONNECTED) return;
|
DEBUG_PRINTLN(F("Publish MQTT"));
|
||||||
DEBUG_PRINTLN(F("Publish MQTT"));
|
|
||||||
|
#ifndef USERMOD_SMARTNEST
|
||||||
#ifndef USERMOD_SMARTNEST
|
char s[10];
|
||||||
char s[10];
|
char subuf[48];
|
||||||
char subuf[38];
|
|
||||||
|
sprintf_P(s, PSTR("%u"), bri);
|
||||||
sprintf_P(s, PSTR("%u"), bri);
|
strlcpy(subuf, mqttDeviceTopic, 33);
|
||||||
strlcpy(subuf, mqttDeviceTopic, 33);
|
strcat_P(subuf, PSTR("/g"));
|
||||||
strcat_P(subuf, PSTR("/g"));
|
mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263)
|
||||||
mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263)
|
|
||||||
|
sprintf_P(s, PSTR("#%06X"), (col[3] << 24) | (col[0] << 16) | (col[1] << 8) | (col[2]));
|
||||||
sprintf_P(s, PSTR("#%06X"), (col[3] << 24) | (col[0] << 16) | (col[1] << 8) | (col[2]));
|
strlcpy(subuf, mqttDeviceTopic, 33);
|
||||||
strlcpy(subuf, mqttDeviceTopic, 33);
|
strcat_P(subuf, PSTR("/c"));
|
||||||
strcat_P(subuf, PSTR("/c"));
|
mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263)
|
||||||
mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263)
|
|
||||||
|
strlcpy(subuf, mqttDeviceTopic, 33);
|
||||||
strlcpy(subuf, mqttDeviceTopic, 33);
|
strcat_P(subuf, PSTR("/status"));
|
||||||
strcat_P(subuf, PSTR("/status"));
|
mqtt->publish(subuf, 0, true, "online"); // retain message for a LWT
|
||||||
mqtt->publish(subuf, 0, true, "online"); // retain message for a LWT
|
|
||||||
|
char apires[1024]; // allocating 1024 bytes from stack can be risky
|
||||||
char apires[1024]; // allocating 1024 bytes from stack can be risky
|
XML_response(nullptr, apires);
|
||||||
XML_response(nullptr, apires);
|
strlcpy(subuf, mqttDeviceTopic, 33);
|
||||||
strlcpy(subuf, mqttDeviceTopic, 33);
|
strcat_P(subuf, PSTR("/v"));
|
||||||
strcat_P(subuf, PSTR("/v"));
|
mqtt->publish(subuf, 0, retainMqttMsg, apires); // optionally retain message (#2263)
|
||||||
mqtt->publish(subuf, 0, retainMqttMsg, apires); // optionally retain message (#2263)
|
#endif
|
||||||
#endif
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
//HA autodiscovery was removed in favor of the native integration in HA v0.102.0
|
||||||
//HA autodiscovery was removed in favor of the native integration in HA v0.102.0
|
|
||||||
|
bool initMqtt()
|
||||||
bool initMqtt()
|
{
|
||||||
{
|
if (!mqttEnabled || mqttServer[0] == 0 || !WLED_CONNECTED) return false;
|
||||||
if (!mqttEnabled || mqttServer[0] == 0 || !WLED_CONNECTED) return false;
|
|
||||||
|
if (mqtt == nullptr) {
|
||||||
if (mqtt == nullptr) {
|
mqtt = new AsyncMqttClient();
|
||||||
mqtt = new AsyncMqttClient();
|
mqtt->onMessage(onMqttMessage);
|
||||||
mqtt->onMessage(onMqttMessage);
|
mqtt->onConnect(onMqttConnect);
|
||||||
mqtt->onConnect(onMqttConnect);
|
}
|
||||||
}
|
if (mqtt->connected()) return true;
|
||||||
if (mqtt->connected()) return true;
|
|
||||||
|
DEBUG_PRINTLN(F("Reconnecting MQTT"));
|
||||||
DEBUG_PRINTLN(F("Reconnecting MQTT"));
|
IPAddress mqttIP;
|
||||||
IPAddress mqttIP;
|
if (mqttIP.fromString(mqttServer)) //see if server is IP or domain
|
||||||
if (mqttIP.fromString(mqttServer)) //see if server is IP or domain
|
{
|
||||||
{
|
mqtt->setServer(mqttIP, mqttPort);
|
||||||
mqtt->setServer(mqttIP, mqttPort);
|
} else {
|
||||||
} else {
|
mqtt->setServer(mqttServer, mqttPort);
|
||||||
mqtt->setServer(mqttServer, mqttPort);
|
}
|
||||||
}
|
mqtt->setClientId(mqttClientID);
|
||||||
mqtt->setClientId(mqttClientID);
|
if (mqttUser[0] && mqttPass[0]) mqtt->setCredentials(mqttUser, mqttPass);
|
||||||
if (mqttUser[0] && mqttPass[0]) mqtt->setCredentials(mqttUser, mqttPass);
|
|
||||||
|
#ifndef USERMOD_SMARTNEST
|
||||||
#ifndef USERMOD_SMARTNEST
|
strlcpy(mqttStatusTopic, mqttDeviceTopic, 33);
|
||||||
strlcpy(mqttStatusTopic, mqttDeviceTopic, 33);
|
strcat_P(mqttStatusTopic, PSTR("/status"));
|
||||||
strcat_P(mqttStatusTopic, PSTR("/status"));
|
mqtt->setWill(mqttStatusTopic, 0, true, "offline"); // LWT message
|
||||||
mqtt->setWill(mqttStatusTopic, 0, true, "offline"); // LWT message
|
#endif
|
||||||
#endif
|
mqtt->setKeepAlive(MQTT_KEEP_ALIVE_TIME);
|
||||||
mqtt->setKeepAlive(MQTT_KEEP_ALIVE_TIME);
|
mqtt->connect();
|
||||||
mqtt->connect();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
#endif
|
||||||
#endif
|
|
||||||
|
@ -399,7 +399,6 @@ void checkTimers()
|
|||||||
&& isTodayInDateRange(((timerMonth[i] >> 4) & 0x0F), timerDay[i], timerMonth[i] & 0x0F, timerDayEnd[i])
|
&& isTodayInDateRange(((timerMonth[i] >> 4) & 0x0F), timerDay[i], timerMonth[i] & 0x0F, timerDayEnd[i])
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
unloadPlaylist();
|
|
||||||
applyPreset(timerMacro[i]);
|
applyPreset(timerMacro[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -413,7 +412,6 @@ void checkTimers()
|
|||||||
&& (timerWeekday[8] & 0x01) //timer is enabled
|
&& (timerWeekday[8] & 0x01) //timer is enabled
|
||||||
&& ((timerWeekday[8] >> weekdayMondayFirst()) & 0x01)) //timer should activate at current day of week
|
&& ((timerWeekday[8] >> weekdayMondayFirst()) & 0x01)) //timer should activate at current day of week
|
||||||
{
|
{
|
||||||
unloadPlaylist();
|
|
||||||
applyPreset(timerMacro[8]);
|
applyPreset(timerMacro[8]);
|
||||||
DEBUG_PRINTF_P(PSTR("Sunrise macro %d triggered."),timerMacro[8]);
|
DEBUG_PRINTF_P(PSTR("Sunrise macro %d triggered."),timerMacro[8]);
|
||||||
}
|
}
|
||||||
@ -428,7 +426,6 @@ void checkTimers()
|
|||||||
&& (timerWeekday[9] & 0x01) //timer is enabled
|
&& (timerWeekday[9] & 0x01) //timer is enabled
|
||||||
&& ((timerWeekday[9] >> weekdayMondayFirst()) & 0x01)) //timer should activate at current day of week
|
&& ((timerWeekday[9] >> weekdayMondayFirst()) & 0x01)) //timer should activate at current day of week
|
||||||
{
|
{
|
||||||
unloadPlaylist();
|
|
||||||
applyPreset(timerMacro[9]);
|
applyPreset(timerMacro[9]);
|
||||||
DEBUG_PRINTF_P(PSTR("Sunset macro %d triggered."),timerMacro[9]);
|
DEBUG_PRINTF_P(PSTR("Sunset macro %d triggered."),timerMacro[9]);
|
||||||
}
|
}
|
||||||
|
@ -209,11 +209,10 @@ bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag)
|
|||||||
|
|
||||||
// if tag is set to PinOwner::None, checks for ANY owner of the pin.
|
// if tag is set to PinOwner::None, checks for ANY owner of the pin.
|
||||||
// if tag is set to any other value, checks if that tag is the current owner of the pin.
|
// if tag is set to any other value, checks if that tag is the current owner of the pin.
|
||||||
bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag)
|
bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag) const
|
||||||
{
|
{
|
||||||
if (!isPinOk(gpio, false)) return true;
|
if (!isPinOk(gpio, false)) return true;
|
||||||
if ((tag != PinOwner::None) && (ownerTag[gpio] != tag)) return false;
|
if ((tag != PinOwner::None) && (ownerTag[gpio] != tag)) return false;
|
||||||
if (gpio >= WLED_NUM_PINS) return false; // catch error case, to avoid array out-of-bounds access
|
|
||||||
byte by = gpio >> 3;
|
byte by = gpio >> 3;
|
||||||
byte bi = gpio - (by<<3);
|
byte bi = gpio - (by<<3);
|
||||||
return bitRead(pinAlloc[by], bi);
|
return bitRead(pinAlloc[by], bi);
|
||||||
@ -236,8 +235,9 @@ bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Check if supplied GPIO is ok to use
|
// Check if supplied GPIO is ok to use
|
||||||
bool PinManagerClass::isPinOk(byte gpio, bool output)
|
bool PinManagerClass::isPinOk(byte gpio, bool output) const
|
||||||
{
|
{
|
||||||
|
if (gpio >= WLED_NUM_PINS) return false; // catch error case, to avoid array out-of-bounds access
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
if (digitalPinIsValid(gpio)) {
|
if (digitalPinIsValid(gpio)) {
|
||||||
#if defined(CONFIG_IDF_TARGET_ESP32C3)
|
#if defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
@ -257,9 +257,7 @@ bool PinManagerClass::isPinOk(byte gpio, bool output)
|
|||||||
// GPIO46 is input only and pulled down
|
// GPIO46 is input only and pulled down
|
||||||
#else
|
#else
|
||||||
if (gpio > 5 && gpio < 12) return false; //SPI flash pins
|
if (gpio > 5 && gpio < 12) return false; //SPI flash pins
|
||||||
#ifdef BOARD_HAS_PSRAM
|
if (gpio == 16 || gpio == 17) return !psramFound(); //PSRAM pins on ESP32 (these are IO)
|
||||||
if (gpio == 16 || gpio == 17) return false; //PSRAM pins
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
if (output) return digitalPinCanOutput(gpio);
|
if (output) return digitalPinCanOutput(gpio);
|
||||||
else return true;
|
else return true;
|
||||||
@ -272,8 +270,8 @@ bool PinManagerClass::isPinOk(byte gpio, bool output)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PinOwner PinManagerClass::getPinOwner(byte gpio) {
|
PinOwner PinManagerClass::getPinOwner(byte gpio) const
|
||||||
if (gpio >= WLED_NUM_PINS) return PinOwner::None; // catch error case, to avoid array out-of-bounds access
|
{
|
||||||
if (!isPinOk(gpio, false)) return PinOwner::None;
|
if (!isPinOk(gpio, false)) return PinOwner::None;
|
||||||
return ownerTag[gpio];
|
return ownerTag[gpio];
|
||||||
}
|
}
|
||||||
|
@ -109,11 +109,11 @@ class PinManagerClass {
|
|||||||
inline void deallocatePin(byte gpio) { deallocatePin(gpio, PinOwner::None); }
|
inline void deallocatePin(byte gpio) { deallocatePin(gpio, PinOwner::None); }
|
||||||
|
|
||||||
// will return true for reserved pins
|
// will return true for reserved pins
|
||||||
bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None);
|
bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None) const;
|
||||||
// will return false for reserved pins
|
// will return false for reserved pins
|
||||||
bool isPinOk(byte gpio, bool output = true);
|
bool isPinOk(byte gpio, bool output = true) const;
|
||||||
|
|
||||||
PinOwner getPinOwner(byte gpio);
|
PinOwner getPinOwner(byte gpio) const;
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
byte allocateLedc(byte channels);
|
byte allocateLedc(byte channels);
|
||||||
|
@ -109,7 +109,10 @@ int16_t loadPlaylist(JsonObject playlistObj, byte presetId) {
|
|||||||
if (playlistRepeat > 0) playlistRepeat++; //add one extra repetition immediately since it will be deducted on first start
|
if (playlistRepeat > 0) playlistRepeat++; //add one extra repetition immediately since it will be deducted on first start
|
||||||
playlistEndPreset = playlistObj["end"] | 0;
|
playlistEndPreset = playlistObj["end"] | 0;
|
||||||
// if end preset is 255 restore original preset (if any running) upon playlist end
|
// if end preset is 255 restore original preset (if any running) upon playlist end
|
||||||
if (playlistEndPreset == 255 && currentPreset > 0) playlistEndPreset = currentPreset;
|
if (playlistEndPreset == 255 && currentPreset > 0) {
|
||||||
|
playlistEndPreset = currentPreset;
|
||||||
|
playlistOptions |= PL_OPTION_RESTORE; // for async save operation
|
||||||
|
}
|
||||||
if (playlistEndPreset > 250) playlistEndPreset = 0;
|
if (playlistEndPreset > 250) playlistEndPreset = 0;
|
||||||
shuffle = shuffle || playlistObj["r"];
|
shuffle = shuffle || playlistObj["r"];
|
||||||
if (shuffle) playlistOptions |= PL_OPTION_SHUFFLE;
|
if (shuffle) playlistOptions |= PL_OPTION_SHUFFLE;
|
||||||
@ -122,8 +125,7 @@ int16_t loadPlaylist(JsonObject playlistObj, byte presetId) {
|
|||||||
|
|
||||||
void handlePlaylist() {
|
void handlePlaylist() {
|
||||||
static unsigned long presetCycledTime = 0;
|
static unsigned long presetCycledTime = 0;
|
||||||
// if fileDoc is not null JSON buffer is in use so just quit
|
if (currentPlaylist < 0 || playlistEntries == nullptr) return;
|
||||||
if (currentPlaylist < 0 || playlistEntries == nullptr || fileDoc != nullptr) return;
|
|
||||||
|
|
||||||
if (millis() - presetCycledTime > (100*playlistEntryDur)) {
|
if (millis() - presetCycledTime > (100*playlistEntryDur)) {
|
||||||
presetCycledTime = millis();
|
presetCycledTime = millis();
|
||||||
@ -135,7 +137,7 @@ void handlePlaylist() {
|
|||||||
if (!playlistIndex) {
|
if (!playlistIndex) {
|
||||||
if (playlistRepeat == 1) { //stop if all repetitions are done
|
if (playlistRepeat == 1) { //stop if all repetitions are done
|
||||||
unloadPlaylist();
|
unloadPlaylist();
|
||||||
if (playlistEndPreset) applyPreset(playlistEndPreset);
|
if (playlistEndPreset) applyPresetFromPlaylist(playlistEndPreset);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (playlistRepeat > 1) playlistRepeat--; // decrease repeat count on each index reset if not an endless playlist
|
if (playlistRepeat > 1) playlistRepeat--; // decrease repeat count on each index reset if not an endless playlist
|
||||||
@ -146,7 +148,7 @@ void handlePlaylist() {
|
|||||||
jsonTransitionOnce = true;
|
jsonTransitionOnce = true;
|
||||||
strip.setTransition(fadeTransition ? playlistEntries[playlistIndex].tr * 100 : 0);
|
strip.setTransition(fadeTransition ? playlistEntries[playlistIndex].tr * 100 : 0);
|
||||||
playlistEntryDur = playlistEntries[playlistIndex].dur;
|
playlistEntryDur = playlistEntries[playlistIndex].dur;
|
||||||
applyPreset(playlistEntries[playlistIndex].preset);
|
applyPresetFromPlaylist(playlistEntries[playlistIndex].preset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +159,7 @@ void serializePlaylist(JsonObject sObj) {
|
|||||||
JsonArray dur = playlist.createNestedArray("dur");
|
JsonArray dur = playlist.createNestedArray("dur");
|
||||||
JsonArray transition = playlist.createNestedArray(F("transition"));
|
JsonArray transition = playlist.createNestedArray(F("transition"));
|
||||||
playlist[F("repeat")] = (playlistIndex < 0 && playlistRepeat > 0) ? playlistRepeat - 1 : playlistRepeat; // remove added repetition count (if not yet running)
|
playlist[F("repeat")] = (playlistIndex < 0 && playlistRepeat > 0) ? playlistRepeat - 1 : playlistRepeat; // remove added repetition count (if not yet running)
|
||||||
playlist["end"] = playlistEndPreset;
|
playlist["end"] = playlistOptions & PL_OPTION_RESTORE ? 255 : playlistEndPreset;
|
||||||
playlist["r"] = playlistOptions & PL_OPTION_SHUFFLE;
|
playlist["r"] = playlistOptions & PL_OPTION_SHUFFLE;
|
||||||
for (int i=0; i<playlistLen; i++) {
|
for (int i=0; i<playlistLen; i++) {
|
||||||
ps.add(playlistEntries[i].preset);
|
ps.add(playlistEntries[i].preset);
|
||||||
|
@ -27,7 +27,7 @@ static void doSaveState() {
|
|||||||
|
|
||||||
unsigned long start = millis();
|
unsigned long start = millis();
|
||||||
while (strip.isUpdating() && millis()-start < (2*FRAMETIME_FIXED)+1) yield(); // wait 2 frames
|
while (strip.isUpdating() && millis()-start < (2*FRAMETIME_FIXED)+1) yield(); // wait 2 frames
|
||||||
if (!requestJSONBufferLock(10)) return; // will set fileDoc
|
if (!requestJSONBufferLock(10)) return;
|
||||||
|
|
||||||
initPresetsFile(); // just in case if someone deleted presets.json using /edit
|
initPresetsFile(); // just in case if someone deleted presets.json using /edit
|
||||||
JsonObject sObj = pDoc->to<JsonObject>();
|
JsonObject sObj = pDoc->to<JsonObject>();
|
||||||
@ -53,23 +53,21 @@ static void doSaveState() {
|
|||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
if (!persist) {
|
if (!persist) {
|
||||||
if (tmpRAMbuffer!=nullptr) free(tmpRAMbuffer);
|
if (tmpRAMbuffer!=nullptr) free(tmpRAMbuffer);
|
||||||
size_t len = measureJson(*fileDoc) + 1;
|
size_t len = measureJson(*pDoc) + 1;
|
||||||
DEBUG_PRINTLN(len);
|
DEBUG_PRINTLN(len);
|
||||||
// if possible use SPI RAM on ESP32
|
// if possible use SPI RAM on ESP32
|
||||||
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
|
if (psramSafe && psramFound())
|
||||||
if (psramFound())
|
|
||||||
tmpRAMbuffer = (char*) ps_malloc(len);
|
tmpRAMbuffer = (char*) ps_malloc(len);
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
tmpRAMbuffer = (char*) malloc(len);
|
tmpRAMbuffer = (char*) malloc(len);
|
||||||
if (tmpRAMbuffer!=nullptr) {
|
if (tmpRAMbuffer!=nullptr) {
|
||||||
serializeJson(*fileDoc, tmpRAMbuffer, len);
|
serializeJson(*pDoc, tmpRAMbuffer, len);
|
||||||
} else {
|
} else {
|
||||||
writeObjectToFileUsingId(getPresetsFileName(persist), presetToSave, fileDoc);
|
writeObjectToFileUsingId(getPresetsFileName(persist), presetToSave, pDoc);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
writeObjectToFileUsingId(getPresetsFileName(persist), presetToSave, fileDoc);
|
writeObjectToFileUsingId(getPresetsFileName(persist), presetToSave, pDoc);
|
||||||
|
|
||||||
if (persist) presetsModifiedTime = toki.second(); //unix time
|
if (persist) presetsModifiedTime = toki.second(); //unix time
|
||||||
releaseJSONBufferLock();
|
releaseJSONBufferLock();
|
||||||
@ -117,8 +115,18 @@ void initPresetsFile()
|
|||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool applyPresetFromPlaylist(byte index)
|
||||||
|
{
|
||||||
|
DEBUG_PRINT(F("Request to apply preset: "));
|
||||||
|
DEBUG_PRINTLN(index);
|
||||||
|
presetToApply = index;
|
||||||
|
callModeToApply = CALL_MODE_DIRECT_CHANGE;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool applyPreset(byte index, byte callMode)
|
bool applyPreset(byte index, byte callMode)
|
||||||
{
|
{
|
||||||
|
unloadPlaylist(); // applying a preset unloads the playlist (#3827)
|
||||||
DEBUG_PRINT(F("Request to apply preset: "));
|
DEBUG_PRINT(F("Request to apply preset: "));
|
||||||
DEBUG_PRINTLN(index);
|
DEBUG_PRINTLN(index);
|
||||||
presetToApply = index;
|
presetToApply = index;
|
||||||
@ -144,7 +152,7 @@ void handlePresets()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (presetToApply == 0 || fileDoc) return; // no preset waiting to apply, or JSON buffer is already allocated, return to loop until free
|
if (presetToApply == 0 || !requestJSONBufferLock(9)) return; // no preset waiting to apply, or JSON buffer is already allocated, return to loop until free
|
||||||
|
|
||||||
bool changePreset = false;
|
bool changePreset = false;
|
||||||
uint8_t tmpPreset = presetToApply; // store temporary since deserializeState() may call applyPreset()
|
uint8_t tmpPreset = presetToApply; // store temporary since deserializeState() may call applyPreset()
|
||||||
@ -152,9 +160,6 @@ void handlePresets()
|
|||||||
|
|
||||||
JsonObject fdo;
|
JsonObject fdo;
|
||||||
|
|
||||||
// allocate buffer
|
|
||||||
if (!requestJSONBufferLock(9)) return; // will also assign fileDoc
|
|
||||||
|
|
||||||
presetToApply = 0; //clear request for preset
|
presetToApply = 0; //clear request for preset
|
||||||
callModeToApply = 0;
|
callModeToApply = 0;
|
||||||
|
|
||||||
@ -163,14 +168,14 @@ void handlePresets()
|
|||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
if (tmpPreset==255 && tmpRAMbuffer!=nullptr) {
|
if (tmpPreset==255 && tmpRAMbuffer!=nullptr) {
|
||||||
deserializeJson(*fileDoc,tmpRAMbuffer);
|
deserializeJson(*pDoc,tmpRAMbuffer);
|
||||||
errorFlag = ERR_NONE;
|
errorFlag = ERR_NONE;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
errorFlag = readObjectFromFileUsingId(getPresetsFileName(tmpPreset < 255), tmpPreset, fileDoc) ? ERR_NONE : ERR_FS_PLOAD;
|
errorFlag = readObjectFromFileUsingId(getPresetsFileName(tmpPreset < 255), tmpPreset, pDoc) ? ERR_NONE : ERR_FS_PLOAD;
|
||||||
}
|
}
|
||||||
fdo = fileDoc->as<JsonObject>();
|
fdo = pDoc->as<JsonObject>();
|
||||||
|
|
||||||
//HTTP API commands
|
//HTTP API commands
|
||||||
const char* httpwin = fdo["win"];
|
const char* httpwin = fdo["win"];
|
||||||
@ -197,13 +202,13 @@ void handlePresets()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
releaseJSONBufferLock(); // will also clear fileDoc
|
releaseJSONBufferLock();
|
||||||
if (changePreset) notify(tmpMode); // force UDP notification
|
if (changePreset) notify(tmpMode); // force UDP notification
|
||||||
stateUpdated(tmpMode); // was colorUpdated() if anything breaks
|
stateUpdated(tmpMode); // was colorUpdated() if anything breaks
|
||||||
updateInterfaces(tmpMode);
|
updateInterfaces(tmpMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
//called from handleSet(PS=) [network callback (fileDoc==nullptr), IR (irrational), deserializeState, UDP] and deserializeState() [network callback (filedoc!=nullptr)]
|
//called from handleSet(PS=) [network callback (sObj is empty), IR (irrational), deserializeState, UDP] and deserializeState() [network callback (filedoc!=nullptr)]
|
||||||
void savePreset(byte index, const char* pname, JsonObject sObj)
|
void savePreset(byte index, const char* pname, JsonObject sObj)
|
||||||
{
|
{
|
||||||
if (!saveName) saveName = new char[33];
|
if (!saveName) saveName = new char[33];
|
||||||
@ -224,6 +229,13 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
|
|||||||
if (sObj[F("ql")].is<const char*>()) strlcpy(quickLoad, sObj[F("ql")].as<const char*>(), 9); // client limits QL to 2 chars, buffer for 8 bytes to allow unicode
|
if (sObj[F("ql")].is<const char*>()) strlcpy(quickLoad, sObj[F("ql")].as<const char*>(), 9); // client limits QL to 2 chars, buffer for 8 bytes to allow unicode
|
||||||
else quickLoad[0] = 0;
|
else quickLoad[0] = 0;
|
||||||
|
|
||||||
|
const char *bootPS = PSTR("bootps");
|
||||||
|
if (!sObj[FPSTR(bootPS)].isNull()) {
|
||||||
|
bootPreset = sObj[FPSTR(bootPS)] | bootPreset;
|
||||||
|
sObj.remove(FPSTR(bootPS));
|
||||||
|
doSerializeConfig = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (sObj.size()==0 || sObj["o"].isNull()) { // no "o" means not a playlist or custom API call, saving of state is async (not immediately)
|
if (sObj.size()==0 || sObj["o"].isNull()) { // no "o" means not a playlist or custom API call, saving of state is async (not immediately)
|
||||||
includeBri = sObj["ib"].as<bool>() || sObj.size()==0 || index==255; // temporary preset needs brightness
|
includeBri = sObj["ib"].as<bool>() || sObj.size()==0 || index==255; // temporary preset needs brightness
|
||||||
segBounds = sObj["sb"].as<bool>() || sObj.size()==0 || index==255; // temporary preset needs bounds
|
segBounds = sObj["sb"].as<bool>() || sObj.size()==0 || index==255; // temporary preset needs bounds
|
||||||
@ -234,7 +246,7 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
|
|||||||
if (sObj[F("playlist")].isNull()) {
|
if (sObj[F("playlist")].isNull()) {
|
||||||
// we will save API call immediately (often causes presets.json corruption)
|
// we will save API call immediately (often causes presets.json corruption)
|
||||||
presetToSave = 0;
|
presetToSave = 0;
|
||||||
if (index <= 250 && fileDoc) { // cannot save API calls to temporary preset (255)
|
if (index <= 250) { // cannot save API calls to temporary preset (255)
|
||||||
sObj.remove("o");
|
sObj.remove("o");
|
||||||
sObj.remove("v");
|
sObj.remove("v");
|
||||||
sObj.remove("time");
|
sObj.remove("time");
|
||||||
@ -242,7 +254,7 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
|
|||||||
sObj.remove(F("psave"));
|
sObj.remove(F("psave"));
|
||||||
if (sObj["n"].isNull()) sObj["n"] = saveName;
|
if (sObj["n"].isNull()) sObj["n"] = saveName;
|
||||||
initPresetsFile(); // just in case if someone deleted presets.json using /edit
|
initPresetsFile(); // just in case if someone deleted presets.json using /edit
|
||||||
writeObjectToFileUsingId(getPresetsFileName(), index, fileDoc);
|
writeObjectToFileUsingId(getPresetsFileName(), index, pDoc);
|
||||||
presetsModifiedTime = toki.second(); //unix time
|
presetsModifiedTime = toki.second(); //unix time
|
||||||
updateFSInfo();
|
updateFSInfo();
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,6 @@ static void setOff() {
|
|||||||
|
|
||||||
void presetWithFallback(uint8_t presetID, uint8_t effectID, uint8_t paletteID) {
|
void presetWithFallback(uint8_t presetID, uint8_t effectID, uint8_t paletteID) {
|
||||||
resetNightMode();
|
resetNightMode();
|
||||||
unloadPlaylist();
|
|
||||||
applyPresetWithFallback(presetID, CALL_MODE_BUTTON_PRESET, effectID, paletteID);
|
applyPresetWithFallback(presetID, CALL_MODE_BUTTON_PRESET, effectID, paletteID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
wled00/set.cpp
Executable file → Normal file
2
wled00/set.cpp
Executable file → Normal file
@ -123,6 +123,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
autoSegments = request->hasArg(F("MS"));
|
autoSegments = request->hasArg(F("MS"));
|
||||||
correctWB = request->hasArg(F("CCT"));
|
correctWB = request->hasArg(F("CCT"));
|
||||||
cctFromRgb = request->hasArg(F("CR"));
|
cctFromRgb = request->hasArg(F("CR"));
|
||||||
|
cctICused = request->hasArg(F("IC"));
|
||||||
strip.cctBlending = request->arg(F("CB")).toInt();
|
strip.cctBlending = request->arg(F("CB")).toInt();
|
||||||
Bus::setCCTBlend(strip.cctBlending);
|
Bus::setCCTBlend(strip.cctBlending);
|
||||||
Bus::setGlobalAWMode(request->arg(F("AW")).toInt());
|
Bus::setGlobalAWMode(request->arg(F("AW")).toInt());
|
||||||
@ -883,7 +884,6 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
|
|
||||||
//apply preset
|
//apply preset
|
||||||
if (updateVal(req.c_str(), "PL=", &presetCycCurr, presetCycMin, presetCycMax)) {
|
if (updateVal(req.c_str(), "PL=", &presetCycCurr, presetCycMin, presetCycMax)) {
|
||||||
unloadPlaylist();
|
|
||||||
applyPreset(presetCycCurr);
|
applyPreset(presetCycCurr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,8 +21,6 @@
|
|||||||
#define DYNAMIC_JSON_DOCUMENT_SIZE 16384
|
#define DYNAMIC_JSON_DOCUMENT_SIZE 16384
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr const char* JSON_MIMETYPE = "application/json";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Json Response
|
* Json Response
|
||||||
* */
|
* */
|
||||||
@ -66,7 +64,7 @@ class AsyncJsonResponse: public AsyncAbstractResponse {
|
|||||||
|
|
||||||
AsyncJsonResponse(JsonDocument *ref, bool isArray=false) : _jsonBuffer(1), _isValid{false} {
|
AsyncJsonResponse(JsonDocument *ref, bool isArray=false) : _jsonBuffer(1), _isValid{false} {
|
||||||
_code = 200;
|
_code = 200;
|
||||||
_contentType = JSON_MIMETYPE;
|
_contentType = FPSTR(CONTENT_TYPE_JSON);
|
||||||
if(isArray)
|
if(isArray)
|
||||||
_root = ref->to<JsonArray>();
|
_root = ref->to<JsonArray>();
|
||||||
else
|
else
|
||||||
@ -75,7 +73,7 @@ class AsyncJsonResponse: public AsyncAbstractResponse {
|
|||||||
|
|
||||||
AsyncJsonResponse(size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE, bool isArray=false) : _jsonBuffer(maxJsonBufferSize), _isValid{false} {
|
AsyncJsonResponse(size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE, bool isArray=false) : _jsonBuffer(maxJsonBufferSize), _isValid{false} {
|
||||||
_code = 200;
|
_code = 200;
|
||||||
_contentType = JSON_MIMETYPE;
|
_contentType = FPSTR(CONTENT_TYPE_JSON);
|
||||||
if(isArray)
|
if(isArray)
|
||||||
_root = _jsonBuffer.createNestedArray();
|
_root = _jsonBuffer.createNestedArray();
|
||||||
else
|
else
|
||||||
|
@ -213,6 +213,10 @@
|
|||||||
#include "../usermods/MAX17048_v2/usermod_max17048.h"
|
#include "../usermods/MAX17048_v2/usermod_max17048.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USERMOD_TETRISAI
|
||||||
|
#include "../usermods/TetrisAI_v2/usermod_v2_tetrisai.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
void registerUsermods()
|
void registerUsermods()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -413,4 +417,8 @@ void registerUsermods()
|
|||||||
#ifdef USERMOD_MAX17048
|
#ifdef USERMOD_MAX17048
|
||||||
usermods.add(new Usermod_MAX17048());
|
usermods.add(new Usermod_MAX17048());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USERMOD_TETRISAI
|
||||||
|
usermods.add(new TetrisAIUsermod());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -228,7 +228,6 @@ bool requestJSONBufferLock(uint8_t module)
|
|||||||
DEBUG_PRINT(F("JSON buffer locked. ("));
|
DEBUG_PRINT(F("JSON buffer locked. ("));
|
||||||
DEBUG_PRINT(jsonBufferLock);
|
DEBUG_PRINT(jsonBufferLock);
|
||||||
DEBUG_PRINTLN(")");
|
DEBUG_PRINTLN(")");
|
||||||
fileDoc = pDoc; // used for applying presets (presets.cpp)
|
|
||||||
pDoc->clear();
|
pDoc->clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -239,7 +238,6 @@ void releaseJSONBufferLock()
|
|||||||
DEBUG_PRINT(F("JSON buffer released. ("));
|
DEBUG_PRINT(F("JSON buffer released. ("));
|
||||||
DEBUG_PRINT(jsonBufferLock);
|
DEBUG_PRINT(jsonBufferLock);
|
||||||
DEBUG_PRINTLN(")");
|
DEBUG_PRINTLN(")");
|
||||||
fileDoc = nullptr;
|
|
||||||
jsonBufferLock = 0;
|
jsonBufferLock = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,8 +263,8 @@ uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLe
|
|||||||
} else return 0;
|
} else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src == JSON_palette_names && mode > GRADIENT_PALETTE_COUNT) {
|
if (src == JSON_palette_names && mode > (GRADIENT_PALETTE_COUNT + 13)) {
|
||||||
snprintf_P(dest, maxLen, PSTR("~ Custom %d~"), 255-mode);
|
snprintf_P(dest, maxLen, PSTR("~ Custom %d ~"), 255-mode);
|
||||||
dest[maxLen-1] = '\0';
|
dest[maxLen-1] = '\0';
|
||||||
return strlen(dest);
|
return strlen(dest);
|
||||||
}
|
}
|
||||||
|
@ -240,10 +240,11 @@ void WLED::loop()
|
|||||||
DEBUG_PRINT(F("Runtime: ")); DEBUG_PRINTLN(millis());
|
DEBUG_PRINT(F("Runtime: ")); DEBUG_PRINTLN(millis());
|
||||||
DEBUG_PRINT(F("Unix time: ")); toki.printTime(toki.getTime());
|
DEBUG_PRINT(F("Unix time: ")); toki.printTime(toki.getTime());
|
||||||
DEBUG_PRINT(F("Free heap: ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
DEBUG_PRINT(F("Free heap: ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
if (psramFound()) {
|
if (psramFound()) {
|
||||||
DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB");
|
DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB");
|
||||||
DEBUG_PRINT(F("Free PSRAM: ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB");
|
DEBUG_PRINT(F("Free PSRAM: ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB");
|
||||||
|
if (!psramSafe) DEBUG_PRINTLN(F("Not using PSRAM."));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
DEBUG_PRINT(F("Wifi state: ")); DEBUG_PRINTLN(WiFi.status());
|
DEBUG_PRINT(F("Wifi state: ")); DEBUG_PRINTLN(WiFi.status());
|
||||||
@ -269,6 +270,7 @@ void WLED::loop()
|
|||||||
maxLoopMillis = 0;
|
maxLoopMillis = 0;
|
||||||
maxUsermodMillis = 0;
|
maxUsermodMillis = 0;
|
||||||
maxStripMillis = 0;
|
maxStripMillis = 0;
|
||||||
|
avgLoopMillis = 0;
|
||||||
avgUsermodMillis = 0;
|
avgUsermodMillis = 0;
|
||||||
avgStripMillis = 0;
|
avgStripMillis = 0;
|
||||||
debugTime = millis();
|
debugTime = millis();
|
||||||
@ -365,42 +367,18 @@ void WLED::setup()
|
|||||||
#endif
|
#endif
|
||||||
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
/*
|
#ifndef BOARD_HAS_PSRAM
|
||||||
* The following code is obsolete as PinManager::isPinOK() will return false for reserved GPIO.
|
if (psramFound() && ESP.getChipRevision() < 3) psramSafe = false;
|
||||||
* Additionally xml.cpp will inform UI about reserved GPIO.
|
if (!psramSafe) DEBUG_PRINTLN(F("Not using PSRAM."));
|
||||||
*
|
|
||||||
|
|
||||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
|
||||||
// S3: reserve GPIO 33-37 for "octal" PSRAM
|
|
||||||
managed_pin_type pins[] = { {33, true}, {34, true}, {35, true}, {36, true}, {37, true} };
|
|
||||||
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
|
|
||||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
|
|
||||||
// S2: reserve GPIO 26-32 for PSRAM (may fail due to isPinOk() but that will also prevent other allocation)
|
|
||||||
managed_pin_type pins[] = { {26, true}, {27, true}, {28, true}, {29, true}, {30, true}, {31, true}, {32, true} };
|
|
||||||
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
|
|
||||||
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
|
||||||
// C3: reserve GPIO 12-17 for PSRAM (may fail due to isPinOk() but that will also prevent other allocation)
|
|
||||||
managed_pin_type pins[] = { {12, true}, {13, true}, {14, true}, {15, true}, {16, true}, {17, true} };
|
|
||||||
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
|
|
||||||
#else
|
|
||||||
// GPIO16/GPIO17 reserved for SPI RAM
|
|
||||||
managed_pin_type pins[] = { {16, true}, {17, true} };
|
|
||||||
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
|
|
||||||
#endif
|
#endif
|
||||||
*/
|
pDoc = new PSRAMDynamicJsonDocument((psramSafe && psramFound() ? 2 : 1)*JSON_BUFFER_SIZE);
|
||||||
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
|
DEBUG_PRINT(F("JSON buffer allocated: ")); DEBUG_PRINTLN((psramSafe && psramFound() ? 2 : 1)*JSON_BUFFER_SIZE);
|
||||||
pDoc = new PSRAMDynamicJsonDocument(2*JSON_BUFFER_SIZE);
|
// if the above fails requestJsonBufferLock() will always return false preventing crashes
|
||||||
if (!pDoc) pDoc = new PSRAMDynamicJsonDocument(JSON_BUFFER_SIZE); // falback if double sized buffer could not be allocated
|
|
||||||
// if the above still fails requestJsonBufferLock() will always return false preventing crashes
|
|
||||||
if (psramFound()) {
|
if (psramFound()) {
|
||||||
DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB");
|
DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB");
|
||||||
DEBUG_PRINT(F("Free PSRAM : ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB");
|
DEBUG_PRINT(F("Free PSRAM : ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB");
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if (!pDoc) pDoc = &gDoc; // just in case ... (it should be globally assigned)
|
|
||||||
DEBUG_PRINTLN(F("PSRAM not used."));
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(ARDUINO_ESP32_PICO)
|
#if defined(ARDUINO_ESP32_PICO)
|
||||||
// special handling for PICO-D4: gpio16+17 are in use for onboard SPI FLASH (not PSRAM)
|
// special handling for PICO-D4: gpio16+17 are in use for onboard SPI FLASH (not PSRAM)
|
||||||
@ -408,9 +386,6 @@ void WLED::setup()
|
|||||||
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
|
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//DEBUG_PRINT(F("LEDs inited. heap usage ~"));
|
|
||||||
//DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
|
|
||||||
|
|
||||||
#if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST)
|
#if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST)
|
||||||
pinManager.allocatePin(hardwareTX, true, PinOwner::DebugOut); // TX (GPIO1 on ESP32) reserved for debug output
|
pinManager.allocatePin(hardwareTX, true, PinOwner::DebugOut); // TX (GPIO1 on ESP32) reserved for debug output
|
||||||
#endif
|
#endif
|
||||||
@ -451,6 +426,7 @@ void WLED::setup()
|
|||||||
|
|
||||||
DEBUG_PRINTLN(F("Reading config"));
|
DEBUG_PRINTLN(F("Reading config"));
|
||||||
deserializeConfigFromFS();
|
deserializeConfigFromFS();
|
||||||
|
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||||
|
|
||||||
#if defined(STATUSLED) && STATUSLED>=0
|
#if defined(STATUSLED) && STATUSLED>=0
|
||||||
if (!pinManager.isPinAllocated(STATUSLED)) {
|
if (!pinManager.isPinAllocated(STATUSLED)) {
|
||||||
@ -554,7 +530,7 @@ void WLED::setup()
|
|||||||
void WLED::beginStrip()
|
void WLED::beginStrip()
|
||||||
{
|
{
|
||||||
// Initialize NeoPixel Strip and button
|
// Initialize NeoPixel Strip and button
|
||||||
strip.finalizeInit(); // busses created during deserializeConfig()
|
strip.finalizeInit(); // busses created during deserializeConfig() if config existed
|
||||||
strip.makeAutoSegments();
|
strip.makeAutoSegments();
|
||||||
strip.setBrightness(0);
|
strip.setBrightness(0);
|
||||||
strip.setShowCallback(handleOverlayDraw);
|
strip.setShowCallback(handleOverlayDraw);
|
||||||
|
26
wled00/wled.h
Executable file → Normal file
26
wled00/wled.h
Executable file → Normal file
@ -3,12 +3,12 @@
|
|||||||
/*
|
/*
|
||||||
Main sketch, global variable declarations
|
Main sketch, global variable declarations
|
||||||
@title WLED project sketch
|
@title WLED project sketch
|
||||||
@version 0.15.0-b1
|
@version 0.15.0-b2
|
||||||
@author Christian Schwinne
|
@author Christian Schwinne
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2403070
|
#define VERSION 2403280
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
@ -158,15 +158,16 @@
|
|||||||
// The following is a construct to enable code to compile without it.
|
// The following is a construct to enable code to compile without it.
|
||||||
// There is a code that will still not use PSRAM though:
|
// There is a code that will still not use PSRAM though:
|
||||||
// AsyncJsonResponse is a derived class that implements DynamicJsonDocument (AsyncJson-v6.h)
|
// AsyncJsonResponse is a derived class that implements DynamicJsonDocument (AsyncJson-v6.h)
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
|
extern bool psramSafe;
|
||||||
struct PSRAM_Allocator {
|
struct PSRAM_Allocator {
|
||||||
void* allocate(size_t size) {
|
void* allocate(size_t size) {
|
||||||
if (psramFound()) return ps_malloc(size); // use PSRAM if it exists
|
if (psramSafe && psramFound()) return ps_malloc(size); // use PSRAM if it exists
|
||||||
else return malloc(size); // fallback
|
else return malloc(size); // fallback
|
||||||
}
|
}
|
||||||
void* reallocate(void* ptr, size_t new_size) {
|
void* reallocate(void* ptr, size_t new_size) {
|
||||||
if (psramFound()) return ps_realloc(ptr, new_size); // use PSRAM if it exists
|
if (psramSafe && psramFound()) return ps_realloc(ptr, new_size); // use PSRAM if it exists
|
||||||
else return realloc(ptr, new_size); // fallback
|
else return realloc(ptr, new_size); // fallback
|
||||||
}
|
}
|
||||||
void deallocate(void* pointer) {
|
void deallocate(void* pointer) {
|
||||||
free(pointer);
|
free(pointer);
|
||||||
@ -348,6 +349,11 @@ WLED_GLOBAL bool useGlobalLedBuffer _INIT(true); // double buffering enabled on
|
|||||||
#endif
|
#endif
|
||||||
WLED_GLOBAL bool correctWB _INIT(false); // CCT color correction of RGB color
|
WLED_GLOBAL bool correctWB _INIT(false); // CCT color correction of RGB color
|
||||||
WLED_GLOBAL bool cctFromRgb _INIT(false); // CCT is calculated from RGB instead of using seg.cct
|
WLED_GLOBAL bool cctFromRgb _INIT(false); // CCT is calculated from RGB instead of using seg.cct
|
||||||
|
#ifdef WLED_USE_IC_CCT
|
||||||
|
WLED_GLOBAL bool cctICused _INIT(true); // CCT IC used (Athom 15W bulbs)
|
||||||
|
#else
|
||||||
|
WLED_GLOBAL bool cctICused _INIT(false); // CCT IC used (Athom 15W bulbs)
|
||||||
|
#endif
|
||||||
WLED_GLOBAL bool gammaCorrectCol _INIT(true); // use gamma correction on colors
|
WLED_GLOBAL bool gammaCorrectCol _INIT(true); // use gamma correction on colors
|
||||||
WLED_GLOBAL bool gammaCorrectBri _INIT(false); // use gamma correction on brightness
|
WLED_GLOBAL bool gammaCorrectBri _INIT(false); // use gamma correction on brightness
|
||||||
WLED_GLOBAL float gammaCorrectVal _INIT(2.8f); // gamma correction value
|
WLED_GLOBAL float gammaCorrectVal _INIT(2.8f); // gamma correction value
|
||||||
@ -692,7 +698,6 @@ WLED_GLOBAL uint16_t olen _INIT(0);
|
|||||||
WLED_GLOBAL size_t fsBytesUsed _INIT(0);
|
WLED_GLOBAL size_t fsBytesUsed _INIT(0);
|
||||||
WLED_GLOBAL size_t fsBytesTotal _INIT(0);
|
WLED_GLOBAL size_t fsBytesTotal _INIT(0);
|
||||||
WLED_GLOBAL unsigned long presetsModifiedTime _INIT(0L);
|
WLED_GLOBAL unsigned long presetsModifiedTime _INIT(0L);
|
||||||
WLED_GLOBAL JsonDocument* fileDoc;
|
|
||||||
WLED_GLOBAL bool doCloseFile _INIT(false);
|
WLED_GLOBAL bool doCloseFile _INIT(false);
|
||||||
|
|
||||||
// presets
|
// presets
|
||||||
@ -705,7 +710,8 @@ WLED_GLOBAL byte optionType;
|
|||||||
|
|
||||||
WLED_GLOBAL bool doSerializeConfig _INIT(false); // flag to initiate saving of config
|
WLED_GLOBAL bool doSerializeConfig _INIT(false); // flag to initiate saving of config
|
||||||
WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers
|
WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers
|
||||||
WLED_GLOBAL bool doPublishMqtt _INIT(false);
|
|
||||||
|
WLED_GLOBAL bool psramSafe _INIT(true); // is it safe to use PSRAM (on ESP32 rev.1; compiler fix used "-mfix-esp32-psram-cache-issue")
|
||||||
|
|
||||||
// status led
|
// status led
|
||||||
#if defined(STATUSLED)
|
#if defined(STATUSLED)
|
||||||
@ -782,7 +788,7 @@ WLED_GLOBAL int8_t spi_sclk _INIT(SPISCLKPIN);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// global ArduinoJson buffer
|
// global ArduinoJson buffer
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
WLED_GLOBAL JsonDocument *pDoc _INIT(nullptr);
|
WLED_GLOBAL JsonDocument *pDoc _INIT(nullptr);
|
||||||
#else
|
#else
|
||||||
WLED_GLOBAL StaticJsonDocument<JSON_BUFFER_SIZE> gDoc;
|
WLED_GLOBAL StaticJsonDocument<JSON_BUFFER_SIZE> gDoc;
|
||||||
|
@ -18,36 +18,6 @@ static const char s_unlock_ota [] PROGMEM = "Please unlock OTA in security setti
|
|||||||
static const char s_unlock_cfg [] PROGMEM = "Please unlock settings using PIN code!";
|
static const char s_unlock_cfg [] PROGMEM = "Please unlock settings using PIN code!";
|
||||||
static const char s_notimplemented[] PROGMEM = "Not implemented";
|
static const char s_notimplemented[] PROGMEM = "Not implemented";
|
||||||
static const char s_accessdenied[] PROGMEM = "Access Denied";
|
static const char s_accessdenied[] PROGMEM = "Access Denied";
|
||||||
static const char s_javascript[] PROGMEM = "application/javascript";
|
|
||||||
static const char s_json[] = "application/json"; // AsyncJson-v6.h
|
|
||||||
static const char s_html[] PROGMEM = "text/html";
|
|
||||||
static const char s_plain[] = "text/plain"; // Espalexa.h
|
|
||||||
static const char s_css[] PROGMEM = "text/css";
|
|
||||||
static const char s_png[] PROGMEM = "image/png";
|
|
||||||
static const char s_gif[] PROGMEM = "image/gif";
|
|
||||||
static const char s_jpg[] PROGMEM = "image/jpeg";
|
|
||||||
static const char s_ico[] PROGMEM = "image/x-icon";
|
|
||||||
//static const char s_xml[] PROGMEM = "text/xml";
|
|
||||||
//static const char s_pdf[] PROGMEM = "application/x-pdf";
|
|
||||||
//static const char s_zip[] PROGMEM = "application/x-zip";
|
|
||||||
//static const char s_gz[] PROGMEM = "application/x-gzip";
|
|
||||||
|
|
||||||
String getFileContentType(String &filename) {
|
|
||||||
if (filename.endsWith(F(".htm"))) return FPSTR(s_html);
|
|
||||||
else if (filename.endsWith(F(".html"))) return FPSTR(s_html);
|
|
||||||
else if (filename.endsWith(F(".css"))) return FPSTR(s_css);
|
|
||||||
else if (filename.endsWith(F(".js"))) return FPSTR(s_javascript);
|
|
||||||
else if (filename.endsWith(F(".json"))) return s_json;
|
|
||||||
else if (filename.endsWith(F(".png"))) return FPSTR(s_png);
|
|
||||||
else if (filename.endsWith(F(".gif"))) return FPSTR(s_gif);
|
|
||||||
else if (filename.endsWith(F(".jpg"))) return FPSTR(s_jpg);
|
|
||||||
else if (filename.endsWith(F(".ico"))) return FPSTR(s_ico);
|
|
||||||
// else if (filename.endsWith(F(".xml"))) return FPSTR(s_xml);
|
|
||||||
// else if (filename.endsWith(F(".pdf"))) return FPSTR(s_pdf);
|
|
||||||
// else if (filename.endsWith(F(".zip"))) return FPSTR(s_zip);
|
|
||||||
// else if (filename.endsWith(F(".gz"))) return FPSTR(s_gz);
|
|
||||||
return s_plain;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Is this an IP?
|
//Is this an IP?
|
||||||
static bool isIp(String str) {
|
static bool isIp(String str) {
|
||||||
@ -183,7 +153,7 @@ static String msgProcessor(const String& var)
|
|||||||
|
|
||||||
static void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) {
|
static void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) {
|
||||||
if (!correctPIN) {
|
if (!correctPIN) {
|
||||||
if (final) request->send(401, FPSTR(s_plain), FPSTR(s_unlock_cfg));
|
if (final) request->send(401, FPSTR(CONTENT_TYPE_PLAIN), FPSTR(s_unlock_cfg));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!index) {
|
if (!index) {
|
||||||
@ -204,10 +174,10 @@ static void handleUpload(AsyncWebServerRequest *request, const String& filename,
|
|||||||
request->_tempFile.close();
|
request->_tempFile.close();
|
||||||
if (filename.indexOf(F("cfg.json")) >= 0) { // check for filename with or without slash
|
if (filename.indexOf(F("cfg.json")) >= 0) { // check for filename with or without slash
|
||||||
doReboot = true;
|
doReboot = true;
|
||||||
request->send(200, FPSTR(s_plain), F("Configuration restore successful.\nRebooting..."));
|
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), F("Configuration restore successful.\nRebooting..."));
|
||||||
} else {
|
} else {
|
||||||
if (filename.indexOf(F("palette")) >= 0 && filename.indexOf(F(".json")) >= 0) strip.loadCustomPalettes();
|
if (filename.indexOf(F("palette")) >= 0 && filename.indexOf(F(".json")) >= 0) strip.loadCustomPalettes();
|
||||||
request->send(200, FPSTR(s_plain), F("File Uploaded!"));
|
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), F("File Uploaded!"));
|
||||||
}
|
}
|
||||||
cacheInvalidate++;
|
cacheInvalidate++;
|
||||||
}
|
}
|
||||||
@ -259,24 +229,24 @@ void initServer()
|
|||||||
|
|
||||||
#ifdef WLED_ENABLE_WEBSOCKETS
|
#ifdef WLED_ENABLE_WEBSOCKETS
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
server.on(SET_F("/liveview2D"), HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on(F("/liveview2D"), HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
handleStaticContent(request, "", 200, FPSTR(s_html), PAGE_liveviewws2D, PAGE_liveviewws2D_length);
|
handleStaticContent(request, "", 200, FPSTR(CONTENT_TYPE_HTML), PAGE_liveviewws2D, PAGE_liveviewws2D_length);
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
server.on(SET_F("/liveview"), HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on(F("/liveview"), HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
handleStaticContent(request, "", 200, FPSTR(s_html), PAGE_liveview, PAGE_liveview_length);
|
handleStaticContent(request, "", 200, FPSTR(CONTENT_TYPE_HTML), PAGE_liveview, PAGE_liveview_length);
|
||||||
});
|
});
|
||||||
|
|
||||||
//settings page
|
//settings page
|
||||||
server.on(SET_F("/settings"), HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on(F("/settings"), HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
serveSettings(request);
|
serveSettings(request);
|
||||||
});
|
});
|
||||||
|
|
||||||
// "/settings/settings.js&p=x" request also handled by serveSettings()
|
// "/settings/settings.js&p=x" request also handled by serveSettings()
|
||||||
static const char _style_css[] PROGMEM = "/style.css";
|
static const char _style_css[] PROGMEM = "/style.css";
|
||||||
server.on(_style_css, HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on(_style_css, HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
handleStaticContent(request, FPSTR(_style_css), 200, FPSTR(s_css), PAGE_settingsCss, PAGE_settingsCss_length);
|
handleStaticContent(request, FPSTR(_style_css), 200, FPSTR(CONTENT_TYPE_CSS), PAGE_settingsCss, PAGE_settingsCss_length);
|
||||||
});
|
});
|
||||||
|
|
||||||
static const char _favicon_ico[] PROGMEM = "/favicon.ico";
|
static const char _favicon_ico[] PROGMEM = "/favicon.ico";
|
||||||
@ -287,28 +257,29 @@ void initServer()
|
|||||||
static const char _skin_css[] PROGMEM = "/skin.css";
|
static const char _skin_css[] PROGMEM = "/skin.css";
|
||||||
server.on(_skin_css, HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on(_skin_css, HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
if (handleFileRead(request, FPSTR(_skin_css))) return;
|
if (handleFileRead(request, FPSTR(_skin_css))) return;
|
||||||
AsyncWebServerResponse *response = request->beginResponse(200, FPSTR(s_css));
|
AsyncWebServerResponse *response = request->beginResponse(200, FPSTR(CONTENT_TYPE_CSS));
|
||||||
request->send(response);
|
request->send(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on(SET_F("/welcome"), HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on(F("/welcome"), HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
serveSettings(request);
|
serveSettings(request);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on(SET_F("/reset"), HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on(F("/reset"), HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
serveMessage(request, 200,F("Rebooting now..."),F("Please wait ~10 seconds..."),129);
|
serveMessage(request, 200,F("Rebooting now..."),F("Please wait ~10 seconds..."),129);
|
||||||
doReboot = true;
|
doReboot = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on(SET_F("/settings"), HTTP_POST, [](AsyncWebServerRequest *request){
|
server.on(F("/settings"), HTTP_POST, [](AsyncWebServerRequest *request){
|
||||||
serveSettings(request, true);
|
serveSettings(request, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on(SET_F("/json"), HTTP_GET, [](AsyncWebServerRequest *request){
|
const static char _json[] PROGMEM = "/json";
|
||||||
|
server.on(FPSTR(_json), HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
serveJson(request);
|
serveJson(request);
|
||||||
});
|
});
|
||||||
|
|
||||||
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler(F("/json"), [](AsyncWebServerRequest *request) {
|
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler(FPSTR(_json), [](AsyncWebServerRequest *request) {
|
||||||
bool verboseResponse = false;
|
bool verboseResponse = false;
|
||||||
bool isConfig = false;
|
bool isConfig = false;
|
||||||
|
|
||||||
@ -356,33 +327,33 @@ void initServer()
|
|||||||
doSerializeConfig = true; //serializeConfig(); //Save new settings to FS
|
doSerializeConfig = true; //serializeConfig(); //Save new settings to FS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
request->send(200, s_json, F("{\"success\":true}"));
|
request->send(200, CONTENT_TYPE_JSON, F("{\"success\":true}"));
|
||||||
}, JSON_BUFFER_SIZE);
|
}, JSON_BUFFER_SIZE);
|
||||||
server.addHandler(handler);
|
server.addHandler(handler);
|
||||||
|
|
||||||
server.on(SET_F("/version"), HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on(F("/version"), HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
request->send(200, FPSTR(s_plain), (String)VERSION);
|
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), (String)VERSION);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on(SET_F("/uptime"), HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on(F("/uptime"), HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
request->send(200, FPSTR(s_plain), (String)millis());
|
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), (String)millis());
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on(SET_F("/freeheap"), HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on(F("/freeheap"), HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
request->send(200, FPSTR(s_plain), (String)ESP.getFreeHeap());
|
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), (String)ESP.getFreeHeap());
|
||||||
});
|
});
|
||||||
|
|
||||||
#ifdef WLED_ENABLE_USERMOD_PAGE
|
#ifdef WLED_ENABLE_USERMOD_PAGE
|
||||||
server.on("/u", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on("/u", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
handleStaticContent(request, "", 200, FPSTR(s_html), PAGE_usermod, PAGE_usermod_length);
|
handleStaticContent(request, "", 200, FPSTR(CONTENT_TYPE_HTML), PAGE_usermod, PAGE_usermod_length);
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
server.on(SET_F("/teapot"), HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on(F("/teapot"), HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
serveMessage(request, 418, F("418. I'm a teapot."), F("(Tangible Embedded Advanced Project Of Twinkling)"), 254);
|
serveMessage(request, 418, F("418. I'm a teapot."), F("(Tangible Embedded Advanced Project Of Twinkling)"), 254);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on(SET_F("/upload"), HTTP_POST, [](AsyncWebServerRequest *request) {},
|
server.on(F("/upload"), HTTP_POST, [](AsyncWebServerRequest *request) {},
|
||||||
[](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data,
|
[](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data,
|
||||||
size_t len, bool final) {handleUpload(request, filename, index, data, len, final);}
|
size_t len, bool final) {handleUpload(request, filename, index, data, len, final);}
|
||||||
);
|
);
|
||||||
@ -453,7 +424,7 @@ void initServer()
|
|||||||
|
|
||||||
#ifdef WLED_ENABLE_DMX
|
#ifdef WLED_ENABLE_DMX
|
||||||
server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
request->send_P(200, FPSTR(s_html), PAGE_dmxmap , dmxProcessor);
|
request->send_P(200, FPSTR(CONTENT_TYPE_HTML), PAGE_dmxmap , dmxProcessor);
|
||||||
});
|
});
|
||||||
#else
|
#else
|
||||||
server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
@ -464,7 +435,7 @@ void initServer()
|
|||||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
if (captivePortal(request)) return;
|
if (captivePortal(request)) return;
|
||||||
if (!showWelcomePage || request->hasArg(F("sliders"))) {
|
if (!showWelcomePage || request->hasArg(F("sliders"))) {
|
||||||
handleStaticContent(request, F("/index.htm"), 200, FPSTR(s_html), PAGE_index, PAGE_index_L);
|
handleStaticContent(request, F("/index.htm"), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_index, PAGE_index_L);
|
||||||
} else {
|
} else {
|
||||||
serveSettings(request);
|
serveSettings(request);
|
||||||
}
|
}
|
||||||
@ -473,20 +444,20 @@ void initServer()
|
|||||||
#ifdef WLED_ENABLE_PIXART
|
#ifdef WLED_ENABLE_PIXART
|
||||||
static const char _pixart_htm[] PROGMEM = "/pixart.htm";
|
static const char _pixart_htm[] PROGMEM = "/pixart.htm";
|
||||||
server.on(_pixart_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on(_pixart_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
handleStaticContent(request, FPSTR(_pixart_htm), 200, FPSTR(s_html), PAGE_pixart, PAGE_pixart_L);
|
handleStaticContent(request, FPSTR(_pixart_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_pixart, PAGE_pixart_L);
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_PXMAGIC
|
#ifndef WLED_DISABLE_PXMAGIC
|
||||||
static const char _pxmagic_htm[] PROGMEM = "/pxmagic.htm";
|
static const char _pxmagic_htm[] PROGMEM = "/pxmagic.htm";
|
||||||
server.on(_pxmagic_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on(_pxmagic_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
handleStaticContent(request, FPSTR(_pxmagic_htm), 200, FPSTR(s_html), PAGE_pxmagic, PAGE_pxmagic_L);
|
handleStaticContent(request, FPSTR(_pxmagic_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_pxmagic, PAGE_pxmagic_L);
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char _cpal_htm[] PROGMEM = "/cpal.htm";
|
static const char _cpal_htm[] PROGMEM = "/cpal.htm";
|
||||||
server.on(_cpal_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on(_cpal_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
handleStaticContent(request, FPSTR(_cpal_htm), 200, FPSTR(s_html), PAGE_cpal, PAGE_cpal_L);
|
handleStaticContent(request, FPSTR(_cpal_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_cpal, PAGE_cpal_L);
|
||||||
});
|
});
|
||||||
|
|
||||||
#ifdef WLED_ENABLE_WEBSOCKETS
|
#ifdef WLED_ENABLE_WEBSOCKETS
|
||||||
@ -511,7 +482,7 @@ void initServer()
|
|||||||
#ifndef WLED_DISABLE_ALEXA
|
#ifndef WLED_DISABLE_ALEXA
|
||||||
if(espalexa.handleAlexaApiCall(request)) return;
|
if(espalexa.handleAlexaApiCall(request)) return;
|
||||||
#endif
|
#endif
|
||||||
handleStaticContent(request, request->url(), 404, FPSTR(s_html), PAGE_404, PAGE_404_length);
|
handleStaticContent(request, request->url(), 404, FPSTR(CONTENT_TYPE_HTML), PAGE_404, PAGE_404_length);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,7 +493,7 @@ void serveMessage(AsyncWebServerRequest* request, uint16_t code, const String& h
|
|||||||
messageSub = subl;
|
messageSub = subl;
|
||||||
optionType = optionT;
|
optionType = optionT;
|
||||||
|
|
||||||
request->send_P(code, FPSTR(s_html), PAGE_msg, msgProcessor);
|
request->send_P(code, FPSTR(CONTENT_TYPE_HTML), PAGE_msg, msgProcessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -530,7 +501,7 @@ void serveJsonError(AsyncWebServerRequest* request, uint16_t code, uint16_t erro
|
|||||||
{
|
{
|
||||||
AsyncJsonResponse *response = new AsyncJsonResponse(64);
|
AsyncJsonResponse *response = new AsyncJsonResponse(64);
|
||||||
if (error < ERR_NOT_IMPL) response->addHeader(F("Retry-After"), F("1"));
|
if (error < ERR_NOT_IMPL) response->addHeader(F("Retry-After"), F("1"));
|
||||||
response->setContentType(s_json);
|
response->setContentType(CONTENT_TYPE_JSON);
|
||||||
response->setCode(code);
|
response->setCode(code);
|
||||||
JsonObject obj = response->getRoot();
|
JsonObject obj = response->getRoot();
|
||||||
obj[F("error")] = error;
|
obj[F("error")] = error;
|
||||||
@ -546,12 +517,12 @@ void serveSettingsJS(AsyncWebServerRequest* request)
|
|||||||
byte subPage = request->arg(F("p")).toInt();
|
byte subPage = request->arg(F("p")).toInt();
|
||||||
if (subPage > 10) {
|
if (subPage > 10) {
|
||||||
strcpy_P(buf, PSTR("alert('Settings for this request are not implemented.');"));
|
strcpy_P(buf, PSTR("alert('Settings for this request are not implemented.');"));
|
||||||
request->send(501, FPSTR(s_javascript), buf);
|
request->send(501, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (subPage > 0 && !correctPIN && strlen(settingsPIN)>0) {
|
if (subPage > 0 && !correctPIN && strlen(settingsPIN)>0) {
|
||||||
strcpy_P(buf, PSTR("alert('PIN incorrect.');"));
|
strcpy_P(buf, PSTR("alert('PIN incorrect.');"));
|
||||||
request->send(401, FPSTR(s_javascript), buf);
|
request->send(401, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
strcat_P(buf,PSTR("function GetV(){var d=document;"));
|
strcat_P(buf,PSTR("function GetV(){var d=document;"));
|
||||||
@ -559,7 +530,7 @@ void serveSettingsJS(AsyncWebServerRequest* request)
|
|||||||
strcat_P(buf,PSTR("}"));
|
strcat_P(buf,PSTR("}"));
|
||||||
|
|
||||||
AsyncWebServerResponse *response;
|
AsyncWebServerResponse *response;
|
||||||
response = request->beginResponse(200, FPSTR(s_javascript), buf);
|
response = request->beginResponse(200, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
|
||||||
response->addHeader(F("Cache-Control"), F("no-store"));
|
response->addHeader(F("Cache-Control"), F("no-store"));
|
||||||
response->addHeader(F("Expires"), F("0"));
|
response->addHeader(F("Expires"), F("0"));
|
||||||
request->send(response);
|
request->send(response);
|
||||||
@ -640,7 +611,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int code = 200;
|
int code = 200;
|
||||||
String contentType = FPSTR(s_html);
|
String contentType = FPSTR(CONTENT_TYPE_HTML);
|
||||||
const uint8_t* content;
|
const uint8_t* content;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
@ -666,7 +637,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case SUBPAGE_PINREQ : content = PAGE_settings_pin; len = PAGE_settings_pin_length; code = 401; break;
|
case SUBPAGE_PINREQ : content = PAGE_settings_pin; len = PAGE_settings_pin_length; code = 401; break;
|
||||||
case SUBPAGE_CSS : content = PAGE_settingsCss; len = PAGE_settingsCss_length; contentType = FPSTR(s_css); break;
|
case SUBPAGE_CSS : content = PAGE_settingsCss; len = PAGE_settingsCss_length; contentType = FPSTR(CONTENT_TYPE_CSS); break;
|
||||||
case SUBPAGE_JS : serveSettingsJS(request); return;
|
case SUBPAGE_JS : serveSettingsJS(request); return;
|
||||||
case SUBPAGE_WELCOME : content = PAGE_welcome; len = PAGE_welcome_length; break;
|
case SUBPAGE_WELCOME : content = PAGE_welcome; len = PAGE_welcome_length; break;
|
||||||
default: content = PAGE_settings; len = PAGE_settings_length; break;
|
default: content = PAGE_settings; len = PAGE_settings_length; break;
|
||||||
|
@ -55,7 +55,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
|||||||
} else {
|
} else {
|
||||||
verboseResponse = deserializeState(root);
|
verboseResponse = deserializeState(root);
|
||||||
}
|
}
|
||||||
releaseJSONBufferLock(); // will clean fileDoc
|
releaseJSONBufferLock();
|
||||||
|
|
||||||
if (!interfaceUpdateCallMode) { // individual client response only needed if no WS broadcast soon
|
if (!interfaceUpdateCallMode) { // individual client response only needed if no WS broadcast soon
|
||||||
if (verboseResponse) {
|
if (verboseResponse) {
|
||||||
@ -102,7 +102,6 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
|||||||
void sendDataWs(AsyncWebSocketClient * client)
|
void sendDataWs(AsyncWebSocketClient * client)
|
||||||
{
|
{
|
||||||
if (!ws.count()) return;
|
if (!ws.count()) return;
|
||||||
AsyncWebSocketMessageBuffer * buffer;
|
|
||||||
|
|
||||||
if (!requestJSONBufferLock(12)) {
|
if (!requestJSONBufferLock(12)) {
|
||||||
if (client) {
|
if (client) {
|
||||||
@ -129,7 +128,7 @@ void sendDataWs(AsyncWebSocketClient * client)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
buffer = ws.makeBuffer(len); // will not allocate correct memory sometimes on ESP8266
|
AsyncWebSocketBuffer buffer(len);
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
size_t heap2 = ESP.getFreeHeap();
|
size_t heap2 = ESP.getFreeHeap();
|
||||||
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||||
@ -141,23 +140,18 @@ void sendDataWs(AsyncWebSocketClient * client)
|
|||||||
DEBUG_PRINTLN(F("WS buffer allocation failed."));
|
DEBUG_PRINTLN(F("WS buffer allocation failed."));
|
||||||
ws.closeAll(1013); //code 1013 = temporary overload, try again later
|
ws.closeAll(1013); //code 1013 = temporary overload, try again later
|
||||||
ws.cleanupClients(0); //disconnect all clients to release memory
|
ws.cleanupClients(0); //disconnect all clients to release memory
|
||||||
ws._cleanBuffers();
|
|
||||||
return; //out of memory
|
return; //out of memory
|
||||||
}
|
}
|
||||||
|
serializeJson(*pDoc, (char *)buffer.data(), len);
|
||||||
buffer->lock();
|
|
||||||
serializeJson(*pDoc, (char *)buffer->get(), len);
|
|
||||||
|
|
||||||
DEBUG_PRINT(F("Sending WS data "));
|
DEBUG_PRINT(F("Sending WS data "));
|
||||||
if (client) {
|
if (client) {
|
||||||
client->text(buffer);
|
client->text(std::move(buffer));
|
||||||
DEBUG_PRINTLN(F("to a single client."));
|
DEBUG_PRINTLN(F("to a single client."));
|
||||||
} else {
|
} else {
|
||||||
ws.textAll(buffer);
|
ws.textAll(std::move(buffer));
|
||||||
DEBUG_PRINTLN(F("to multiple clients."));
|
DEBUG_PRINTLN(F("to multiple clients."));
|
||||||
}
|
}
|
||||||
buffer->unlock();
|
|
||||||
ws._cleanBuffers();
|
|
||||||
|
|
||||||
releaseJSONBufferLock();
|
releaseJSONBufferLock();
|
||||||
}
|
}
|
||||||
@ -187,11 +181,10 @@ bool sendLiveLedsWs(uint32_t wsClient)
|
|||||||
#endif
|
#endif
|
||||||
size_t bufSize = pos + (used/n)*3;
|
size_t bufSize = pos + (used/n)*3;
|
||||||
|
|
||||||
AsyncWebSocketMessageBuffer * wsBuf = ws.makeBuffer(bufSize);
|
AsyncWebSocketBuffer wsBuf(bufSize);
|
||||||
if (!wsBuf) return false; //out of memory
|
if (!wsBuf) return false; //out of memory
|
||||||
uint8_t* buffer = wsBuf->get();
|
uint8_t* buffer = reinterpret_cast<uint8_t*>(wsBuf.data());
|
||||||
if (!buffer) return false; //out of memory
|
if (!buffer) return false; //out of memory
|
||||||
wsBuf->lock(); // protect buffer from being cleaned by another WS instance
|
|
||||||
buffer[0] = 'L';
|
buffer[0] = 'L';
|
||||||
buffer[1] = 1; //version
|
buffer[1] = 1; //version
|
||||||
|
|
||||||
@ -218,9 +211,7 @@ bool sendLiveLedsWs(uint32_t wsClient)
|
|||||||
buffer[pos++] = scale8(qadd8(w, b), strip.getBrightness()); //B
|
buffer[pos++] = scale8(qadd8(w, b), strip.getBrightness()); //B
|
||||||
}
|
}
|
||||||
|
|
||||||
wsc->binary(wsBuf);
|
wsc->binary(std::move(wsBuf));
|
||||||
wsBuf->unlock(); // un-protect buffer
|
|
||||||
ws._cleanBuffers();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
wled00/xml.cpp
Executable file → Normal file
5
wled00/xml.cpp
Executable file → Normal file
@ -163,7 +163,7 @@ void appendGPIOinfo() {
|
|||||||
|
|
||||||
//Note: Using pin 3 (RX) disables Adalight / Serial JSON
|
//Note: Using pin 3 (RX) disables Adalight / Serial JSON
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
#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)
|
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)
|
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
@ -360,6 +360,7 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
|
|
||||||
sappend('c',SET_F("MS"),autoSegments);
|
sappend('c',SET_F("MS"),autoSegments);
|
||||||
sappend('c',SET_F("CCT"),correctWB);
|
sappend('c',SET_F("CCT"),correctWB);
|
||||||
|
sappend('c',SET_F("IC"),cctICused);
|
||||||
sappend('c',SET_F("CR"),cctFromRgb);
|
sappend('c',SET_F("CR"),cctFromRgb);
|
||||||
sappend('v',SET_F("CB"),strip.cctBlending);
|
sappend('v',SET_F("CB"),strip.cctBlending);
|
||||||
sappend('v',SET_F("FR"),strip.getTargetFps());
|
sappend('v',SET_F("FR"),strip.getTargetFps());
|
||||||
@ -471,8 +472,10 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
}
|
}
|
||||||
sappend('c',SET_F("IP"),disablePullUp);
|
sappend('c',SET_F("IP"),disablePullUp);
|
||||||
sappend('v',SET_F("TT"),touchThreshold);
|
sappend('v',SET_F("TT"),touchThreshold);
|
||||||
|
#ifndef WLED_DISABLE_INFRARED
|
||||||
sappend('v',SET_F("IR"),irPin);
|
sappend('v',SET_F("IR"),irPin);
|
||||||
sappend('v',SET_F("IT"),irEnabled);
|
sappend('v',SET_F("IT"),irEnabled);
|
||||||
|
#endif
|
||||||
sappend('c',SET_F("MSO"),!irApplyToAllSelected);
|
sappend('c',SET_F("MSO"),!irApplyToAllSelected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user