Compare commits
	
		
			149 Commits
		
	
	
		
			lto_size_o
			...
			v0.15.0-rc
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 9328e6faca | ||
|   | bbacc2daae | ||
|   | 3e22f9cabb | ||
|   | a121f5b61b | ||
|   | 251062170e | ||
|   | 92e59af4d8 | ||
|   | fa4c23b76e | ||
|   | a0a46850f5 | ||
|   | 4cd0563a93 | ||
|   | b83f0f461c | ||
|   | 685ad83d4b | ||
|   | 62ddb18a1a | ||
|   | 3668ede0ff | ||
|   | 6a12378475 | ||
|   | 945584384a | ||
|   | b1dd27b516 | ||
|   | dcba1aad10 | ||
|   | acc8b9cdbc | ||
|   | d26b3108da | ||
|   | 6cbdd825eb | ||
|   | cc55f6015d | ||
|   | c89e4576b4 | ||
|   | bc79f44a26 | ||
|   | 7ece14ff3f | ||
|   | 95718ab6ec | ||
|   | feab27295d | ||
|   | ca176c7549 | ||
|   | f8a7a0d6e8 | ||
|   | 1a8aaa3b26 | ||
|   | cd1c13b4b1 | ||
|   | d87c5035dd | ||
|   | 77967731d5 | ||
|   | 0b54034470 | ||
|   | 0b3643132b | ||
|   | a5693fbf8d | ||
|   | 5c5b70f52b | ||
|   | ae97e388a6 | ||
|   | 37cddcaacc | ||
|   | a1b332fc78 | ||
|   | 86d7c24513 | ||
|   | b28add3b8b | ||
|   | 5fd3a513a4 | ||
|   | b98a8a10b0 | ||
|   | 2bee2793ef | ||
|   | 2f6fa66f4d | ||
|   | 8ad2583785 | ||
|   | dd533a9ab4 | ||
|   | 5b989adebc | ||
|   | 5d38acd787 | ||
|   | e607fcb5c5 | ||
|   | 8a18555ae4 | ||
|   | beb709dc8f | ||
|   | 20f8d3c8a9 | ||
|   | 0c77dbb7ea | ||
|   | 2448e2ae3b | ||
|   | d53d7aa2e2 | ||
|   | 7a58c69a80 | ||
|   | 0be1df7ee8 | ||
|   | 1082c85789 | ||
|   | 568d2edd96 | ||
|   | 6aef0e145c | ||
|   | 32dc54ce72 | ||
|   | 548736f432 | ||
|   | 89d587e7dd | ||
|   | 5c8b2ebf7a | ||
|   | 5ac8ba9bae | ||
|   | 49fb16e2c6 | ||
|   | 545bfa6ef9 | ||
|   | c596b5a17d | ||
|   | 84dd26c1b7 | ||
|   | a765903a41 | ||
|   | 25ab381916 | ||
|   | 4d3df5d98f | ||
|   | 6fe2024542 | ||
|   | 4cd4c13b2d | ||
|   | d2d56ebbd2 | ||
|   | 86be5df475 | ||
|   | 8c5e0cd4e9 | ||
|   | a9b0b8adc8 | ||
|   | ba01cb82f7 | ||
|   | 223b97b884 | ||
|   | 5de86d3d91 | ||
|   | 536444f9d1 | ||
|   | 271a07a7d6 | ||
|   | 4634ace74e | ||
|   | 3733715184 | ||
|   | bf37ac53a3 | ||
|   | 70323b9477 | ||
|   | 7d0951a08a | ||
|   | d98ca9a202 | ||
|   | 3c2c5bedc5 | ||
|   | 749d34cd30 | ||
|   | 1898be2fe1 | ||
|   | af34da4160 | ||
|   | fa053b7e60 | ||
|   | 4588219e31 | ||
|   | 6e89346f00 | ||
|   | 2703c9899a | ||
|   | d05c358fd2 | ||
|   | 7c6bc5c421 | ||
|   | 798c398f23 | ||
|   | 4cc2cc4ad4 | ||
|   | dcfdca6351 | ||
|   | 832599b8c5 | ||
|   | c81ef2669e | ||
|   | 19d837c222 | ||
|   | 4f48ddfaec | ||
|   | 2e01fe0b5b | ||
|   | 7d067d8c30 | ||
|   | b3b326738c | ||
|   | 2bb2caf2d2 | ||
|   | 2a094883ad | ||
|   | 6d1126b8aa | ||
|   | 26a47537f9 | ||
|   | 01d43c69fb | ||
|   | 7db1989093 | ||
|   | 0a97e28aab | ||
|   | 98a6907976 | ||
|   | e9d2182390 | ||
|   | 5e29f2c1b7 | ||
|   | 44e28f96e0 | ||
|   | a0e81da8c5 | ||
|   | 85a7c3c60d | ||
|   | 01e07ca0bc | ||
|   | 1468ee5fde | ||
|   | 49f044ecde | ||
|   | 37f32ab197 | ||
|   | a60231ba59 | ||
|   | c8dafede6d | ||
|   | 7deea9eb75 | ||
|   | 5e9a46d54d | ||
|   | 488974dd3e | ||
|   | 5975b9125f | ||
|   | f301296f1e | ||
|   | 407477dc68 | ||
|   | 1b0ce9a123 | ||
|   | 7b855c851d | ||
|   | ba636b17a0 | ||
|   | 2a07eb84f6 | ||
|   | 949b9fb10e | ||
|   | ae1b6af0d4 | ||
|   | dd27504d30 | ||
|   | c30a08cfc5 | ||
|   | a4c49aa35e | ||
|   | 402fba734a | ||
|   | 262af0678f | ||
|   | 3765d558b6 | ||
|   | 4ed8ded502 | ||
|   | 7fa25ca7ae | 
							
								
								
									
										80
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| name: WLED Build | ||||
|  | ||||
| # Only included into other workflows | ||||
| on: | ||||
|   workflow_call: | ||||
|    | ||||
| jobs: | ||||
|  | ||||
|   get_default_envs: | ||||
|     name: Gather Environments | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - uses: actions/checkout@v4 | ||||
|     - uses: actions/setup-python@v5 | ||||
|       with: | ||||
|         python-version: '3.12' | ||||
|         cache: 'pip' | ||||
|     - name: Install PlatformIO | ||||
|       run: pip install -r requirements.txt | ||||
|     - name: Get default environments | ||||
|       id: envs | ||||
|       run: | | ||||
|         echo "environments=$(pio project config --json-output | jq -cr '.[0][1][0][1]')" >> $GITHUB_OUTPUT | ||||
|     outputs: | ||||
|       environments: ${{ steps.envs.outputs.environments }} | ||||
|  | ||||
|  | ||||
|   build: | ||||
|     name: Build Enviornments | ||||
|     runs-on: ubuntu-latest | ||||
|     needs: get_default_envs | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         environment: ${{ fromJSON(needs.get_default_envs.outputs.environments) }} | ||||
|     steps: | ||||
|     - uses: actions/checkout@v4 | ||||
|     - name: Set up Node.js | ||||
|       uses: actions/setup-node@v4 | ||||
|       with: | ||||
|         cache: 'npm' | ||||
|     - run: npm ci | ||||
|     - name: Cache PlatformIO | ||||
|       uses: actions/cache@v4 | ||||
|       with: | ||||
|         path: | | ||||
|               ~/.platformio/.cache | ||||
|               ~/.buildcache | ||||
|               build_output | ||||
|         key: pio-${{ runner.os }}-${{ matrix.environment }}-${{ hashFiles('platformio.ini', 'pio-scripts/output_bins.py') }}-${{ hashFiles('wled00/**', 'usermods/**') }} | ||||
|         restore-keys: pio-${{ runner.os }}-${{ matrix.environment }}-${{ hashFiles('platformio.ini', 'pio-scripts/output_bins.py') }}- | ||||
|     - name: Set up Python | ||||
|       uses: actions/setup-python@v5 | ||||
|       with: | ||||
|           python-version: '3.12' | ||||
|           cache: 'pip' | ||||
|     - name: Install PlatformIO | ||||
|       run: pip install -r requirements.txt | ||||
|     - name: Build firmware | ||||
|       run: pio run -e ${{ matrix.environment }} | ||||
|     - uses: actions/upload-artifact@v4 | ||||
|       with: | ||||
|         name: firmware-${{ matrix.environment }} | ||||
|         path: | | ||||
|           build_output/release/*.bin | ||||
|           build_output/release/*_ESP02*.bin.gz | ||||
|  | ||||
|  | ||||
|   testCdata: | ||||
|     name: Test cdata.js | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|       - name: Use Node.js | ||||
|         uses: actions/setup-node@v4 | ||||
|         with: | ||||
|           node-version: '20.x' | ||||
|           cache: 'npm' | ||||
|       - run: npm ci | ||||
|       - run: npm test | ||||
							
								
								
									
										28
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| name: WLED Release CI | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     tags: | ||||
|       - '*' | ||||
|  | ||||
| jobs: | ||||
|    | ||||
|   wled_build: | ||||
|     uses: ./.github/workflows/build.yml | ||||
|      | ||||
|   release: | ||||
|     name: Create Release | ||||
|     runs-on: ubuntu-latest | ||||
|     needs: wled_build | ||||
|     steps: | ||||
|     - uses: actions/download-artifact@v4 | ||||
|       with: | ||||
|         merge-multiple: true | ||||
|     - name: Create draft release | ||||
|       uses: softprops/action-gh-release@v1 | ||||
|       with: | ||||
|         draft: True | ||||
|         files: | | ||||
|           *.bin | ||||
|           *.bin.gz | ||||
|  | ||||
							
								
								
									
										97
									
								
								.github/workflows/wled-ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										97
									
								
								.github/workflows/wled-ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,94 +1,11 @@ | ||||
| name: WLED CI | ||||
|  | ||||
| on: [push, pull_request] | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - '*' | ||||
|   pull_request: | ||||
|  | ||||
| jobs: | ||||
|  | ||||
|   get_default_envs: | ||||
|     name: Gather Environments | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - uses: actions/checkout@v4 | ||||
|     - uses: actions/setup-python@v5 | ||||
|       with: | ||||
|         python-version: '3.12' | ||||
|         cache: 'pip' | ||||
|     - name: Install PlatformIO | ||||
|       run: pip install -r requirements.txt | ||||
|     - name: Get default environments | ||||
|       id: envs | ||||
|       run: | | ||||
|         echo "environments=$(pio project config --json-output | jq -cr '.[0][1][0][1]')" >> $GITHUB_OUTPUT | ||||
|     outputs: | ||||
|       environments: ${{ steps.envs.outputs.environments }} | ||||
|  | ||||
|  | ||||
|   build: | ||||
|     name: Build Enviornments | ||||
|     runs-on: ubuntu-latest | ||||
|     needs: get_default_envs | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         environment: ${{ fromJSON(needs.get_default_envs.outputs.environments) }} | ||||
|     steps: | ||||
|     - uses: actions/checkout@v4 | ||||
|     - name: Set up Node.js | ||||
|       uses: actions/setup-node@v4 | ||||
|       with: | ||||
|         cache: 'npm' | ||||
|     - run: npm ci | ||||
|     - name: Cache PlatformIO | ||||
|       uses: actions/cache@v4 | ||||
|       with: | ||||
|         path: | | ||||
|               ~/.platformio/.cache | ||||
|               ~/.buildcache | ||||
|               build_output | ||||
|         key: pio-${{ runner.os }}-${{ matrix.environment }}-${{ hashFiles('platformio.ini', 'pio-scripts/output_bins.py') }}-${{ hashFiles('wled00/**', 'usermods/**') }} | ||||
|         restore-keys: pio-${{ runner.os }}-${{ matrix.environment }}-${{ hashFiles('platformio.ini', 'pio-scripts/output_bins.py') }}- | ||||
|     - name: Set up Python | ||||
|       uses: actions/setup-python@v5 | ||||
|       with: | ||||
|           python-version: '3.12' | ||||
|           cache: 'pip' | ||||
|     - name: Install PlatformIO | ||||
|       run: pip install -r requirements.txt | ||||
|     - name: Build firmware | ||||
|       run: pio run -e ${{ matrix.environment }} | ||||
|     - uses: actions/upload-artifact@v4 | ||||
|       with: | ||||
|         name: firmware-${{ matrix.environment }} | ||||
|         path: | | ||||
|           build_output/release/*.bin | ||||
|           build_output/release/*_ESP02*.bin.gz | ||||
|   release: | ||||
|     name: Create Release | ||||
|     runs-on: ubuntu-latest | ||||
|     needs: build | ||||
|     if: startsWith(github.ref, 'refs/tags/') | ||||
|     steps: | ||||
|     - uses: actions/download-artifact@v4 | ||||
|       with: | ||||
|         merge-multiple: true | ||||
|     - name: Create draft release | ||||
|       uses: softprops/action-gh-release@v1 | ||||
|       with: | ||||
|         draft: True | ||||
|         files: | | ||||
|           *.bin | ||||
|           *.bin.gz | ||||
|  | ||||
|  | ||||
|   testCdata: | ||||
|     name: Test cdata.js | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|       - name: Use Node.js | ||||
|         uses: actions/setup-node@v4 | ||||
|         with: | ||||
|           node-version: '20.x' | ||||
|           cache: 'npm' | ||||
|       - run: npm ci | ||||
|       - run: npm test | ||||
|   wled_build: | ||||
|     uses: ./.github/workflows/build.yml | ||||
|   | ||||
							
								
								
									
										39
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,9 +1,48 @@ | ||||
| ## WLED changelog | ||||
|  | ||||
| #### Build 2411250 | ||||
| -   WLED 0.15.0-rc1 release | ||||
| -   Add support for esp32S3_wroom2 (#4243 by @softhack007) | ||||
| -   Fix mixed LED SK6812 and ws2812b booloop (#4301 by @willmmiles) | ||||
| -   Improved FPS calculation (by DedeHai) | ||||
| -   Fix crashes when using HTTP API within MQTT (#4269 by @willmmiles) | ||||
| -   Fix array overflow in exploding_fireworks (#4120 by @willmmiles) | ||||
| -   Fix MQTT topic buffer length (#4293 by @WouterGritter) | ||||
| -   Fix SparkFunDMX fix for possible array bounds violation in DMX.write (by @softhack007) | ||||
| -   Allow TV Simulator on single LED segments (by @softhack007) | ||||
| -   Fix WLED_RELEASE_NAME (by @netmindz) | ||||
|  | ||||
|  | ||||
| #### Build 2410270 | ||||
| -   WLED 0.15.0-b7 release | ||||
| -   Re-license the WLED project from MIT to EUPL (#4194 by @Aircoookie) | ||||
| -   Fix alexa devices invisible/uncontrollable (#4214 by @Svennte) | ||||
| -   Add visual expand button on hover (#4172) | ||||
| -   Usermod: Audioreactive tuning and performance enhancements (by @softhack007) | ||||
| -   `/json/live` (JSON live data/peek) only enabled when WebSockets are disabled | ||||
| -   Various bugfixes and optimisations: #4179, #4215, #4219, #4222, #4223, #4224, #4228, #4230 | ||||
|  | ||||
| #### Build 2410140 | ||||
| -   WLED 0.15.0-b6 release | ||||
| -   Added BRT timezone (#4188 by @LuisFadini) | ||||
| -   Fixed the positioning of the "Download the latest binary" button (#4184 by @maxi4329) | ||||
| -   Add WLED_AUTOSEGMENTS compile flag (#4183 by @PaoloTK) | ||||
| -   New 512kB FS parition map for 4MB devices | ||||
| -   Internal API change: Static PinManager & UsermodManager | ||||
| -   Change in Improv chip ID and version generation | ||||
| -   Various optimisations, bugfixes and enhancements (#4005, #4174 & #4175 by @Xevel, #4180, #4168, #4154, #4189 by @dosipod) | ||||
|  | ||||
| #### Build 2409170 | ||||
| -   UI: Introduce common.js in settings pages (size optimisation) | ||||
| -   Add the ability to toggle the reception of palette synchronizations (#4137 by @felddy) | ||||
| -   Usermod/FX: Temperature usermod added Temperature effect (example usermod effect by @blazoncek) | ||||
| -   Fix AsyncWebServer version pin | ||||
|  | ||||
| #### Build 2409140 | ||||
| -   Configure different kinds of busses at compile (#4107 by @PaoloTK) | ||||
|     - BREAKING: removes LEDPIN and DEFAULT_LED_TYPE compile overrides | ||||
| -   Fetch LED types from Bus classes (dynamic UI) (#4129 by @netmindz, @blazoncek, @dedehai) | ||||
| -   Temperature usermod: update OneWire to 2.3.8 (#4131 by @iammattcoleman) | ||||
|  | ||||
| #### Build 2409100 | ||||
| -   WLED 0.15.0-b5 release | ||||
|   | ||||
							
								
								
									
										307
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										307
									
								
								LICENSE
									
									
									
									
									
								
							| @@ -1,21 +1,294 @@ | ||||
| MIT License | ||||
| Copyright (c) 2016-present Christian Schwinne and individual WLED contributors | ||||
| Licensed under the EUPL v. 1.2 or later | ||||
|  | ||||
| Copyright (c) 2016 Christian Schwinne | ||||
|                       EUROPEAN UNION PUBLIC LICENCE v. 1.2 | ||||
|                       EUPL © the European Union 2007, 2016 | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| This European Union Public Licence (the ‘EUPL’) applies to the Work (as | ||||
| defined below) which is provided under the terms of this Licence. Any use of | ||||
| the Work, other than as authorised under this Licence is prohibited (to the | ||||
| extent such use is covered by a right of the copyright holder of the Work). | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| The Work is provided under the terms of this Licence when the Licensor (as | ||||
| defined below) has placed the following notice immediately following the | ||||
| copyright notice for the Work: | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
|         Licensed under the EUPL | ||||
|  | ||||
| or has expressed by any other means his willingness to license under the EUPL. | ||||
|  | ||||
| 1. Definitions | ||||
|  | ||||
| In this Licence, the following terms have the following meaning: | ||||
|  | ||||
| - ‘The Licence’: this Licence. | ||||
|  | ||||
| - ‘The Original Work’: the work or software distributed or communicated by the | ||||
|   Licensor under this Licence, available as Source Code and also as Executable | ||||
|   Code as the case may be. | ||||
|  | ||||
| - ‘Derivative Works’: the works or software that could be created by the | ||||
|   Licensee, based upon the Original Work or modifications thereof. This | ||||
|   Licence does not define the extent of modification or dependence on the | ||||
|   Original Work required in order to classify a work as a Derivative Work; | ||||
|   this extent is determined by copyright law applicable in the country | ||||
|   mentioned in Article 15. | ||||
|  | ||||
| - ‘The Work’: the Original Work or its Derivative Works. | ||||
|  | ||||
| - ‘The Source Code’: the human-readable form of the Work which is the most | ||||
|   convenient for people to study and modify. | ||||
|  | ||||
| - ‘The Executable Code’: any code which has generally been compiled and which | ||||
|   is meant to be interpreted by a computer as a program. | ||||
|  | ||||
| - ‘The Licensor’: the natural or legal person that distributes or communicates | ||||
|   the Work under the Licence. | ||||
|  | ||||
| - ‘Contributor(s)’: any natural or legal person who modifies the Work under | ||||
|   the Licence, or otherwise contributes to the creation of a Derivative Work. | ||||
|  | ||||
| - ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of | ||||
|   the Work under the terms of the Licence. | ||||
|  | ||||
| - ‘Distribution’ or ‘Communication’: any act of selling, giving, lending, | ||||
|   renting, distributing, communicating, transmitting, or otherwise making | ||||
|   available, online or offline, copies of the Work or providing access to its | ||||
|   essential functionalities at the disposal of any other natural or legal | ||||
|   person. | ||||
|  | ||||
| 2. Scope of the rights granted by the Licence | ||||
|  | ||||
| The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, | ||||
| sublicensable licence to do the following, for the duration of copyright | ||||
| vested in the Original Work: | ||||
|  | ||||
| - use the Work in any circumstance and for all usage, | ||||
| - reproduce the Work, | ||||
| - modify the Work, and make Derivative Works based upon the Work, | ||||
| - communicate to the public, including the right to make available or display | ||||
|   the Work or copies thereof to the public and perform publicly, as the case | ||||
|   may be, the Work, | ||||
| - distribute the Work or copies thereof, | ||||
| - lend and rent the Work or copies thereof, | ||||
| - sublicense rights in the Work or copies thereof. | ||||
|  | ||||
| Those rights can be exercised on any media, supports and formats, whether now | ||||
| known or later invented, as far as the applicable law permits so. | ||||
|  | ||||
| In the countries where moral rights apply, the Licensor waives his right to | ||||
| exercise his moral right to the extent allowed by law in order to make | ||||
| effective the licence of the economic rights here above listed. | ||||
|  | ||||
| The Licensor grants to the Licensee royalty-free, non-exclusive usage rights | ||||
| to any patents held by the Licensor, to the extent necessary to make use of | ||||
| the rights granted on the Work under this Licence. | ||||
|  | ||||
| 3. Communication of the Source Code | ||||
|  | ||||
| The Licensor may provide the Work either in its Source Code form, or as | ||||
| Executable Code. If the Work is provided as Executable Code, the Licensor | ||||
| provides in addition a machine-readable copy of the Source Code of the Work | ||||
| along with each copy of the Work that the Licensor distributes or indicates, | ||||
| in a notice following the copyright notice attached to the Work, a repository | ||||
| where the Source Code is easily and freely accessible for as long as the | ||||
| Licensor continues to distribute or communicate the Work. | ||||
|  | ||||
| 4. Limitations on copyright | ||||
|  | ||||
| Nothing in this Licence is intended to deprive the Licensee of the benefits | ||||
| from any exception or limitation to the exclusive rights of the rights owners | ||||
| in the Work, of the exhaustion of those rights or of other applicable | ||||
| limitations thereto. | ||||
|  | ||||
| 5. Obligations of the Licensee | ||||
|  | ||||
| The grant of the rights mentioned above is subject to some restrictions and | ||||
| obligations imposed on the Licensee. Those obligations are the following: | ||||
|  | ||||
| Attribution right: The Licensee shall keep intact all copyright, patent or | ||||
| trademarks notices and all notices that refer to the Licence and to the | ||||
| disclaimer of warranties. The Licensee must include a copy of such notices and | ||||
| a copy of the Licence with every copy of the Work he/she distributes or | ||||
| communicates. The Licensee must cause any Derivative Work to carry prominent | ||||
| notices stating that the Work has been modified and the date of modification. | ||||
|  | ||||
| Copyleft clause: If the Licensee distributes or communicates copies of the | ||||
| Original Works or Derivative Works, this Distribution or Communication will be | ||||
| done under the terms of this Licence or of a later version of this Licence | ||||
| unless the Original Work is expressly distributed only under this version of | ||||
| the Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee | ||||
| (becoming Licensor) cannot offer or impose any additional terms or conditions | ||||
| on the Work or Derivative Work that alter or restrict the terms of the | ||||
| Licence. | ||||
|  | ||||
| Compatibility clause: If the Licensee Distributes or Communicates Derivative | ||||
| Works or copies thereof based upon both the Work and another work licensed | ||||
| under a Compatible Licence, this Distribution or Communication can be done | ||||
| under the terms of this Compatible Licence. For the sake of this clause, | ||||
| ‘Compatible Licence’ refers to the licences listed in the appendix attached to | ||||
| this Licence. Should the Licensee's obligations under the Compatible Licence | ||||
| conflict with his/her obligations under this Licence, the obligations of the | ||||
| Compatible Licence shall prevail. | ||||
|  | ||||
| Provision of Source Code: When distributing or communicating copies of the | ||||
| Work, the Licensee will provide a machine-readable copy of the Source Code or | ||||
| indicate a repository where this Source will be easily and freely available | ||||
| for as long as the Licensee continues to distribute or communicate the Work. | ||||
|  | ||||
| Legal Protection: This Licence does not grant permission to use the trade | ||||
| names, trademarks, service marks, or names of the Licensor, except as required | ||||
| for reasonable and customary use in describing the origin of the Work and | ||||
| reproducing the content of the copyright notice. | ||||
|  | ||||
| 6. Chain of Authorship | ||||
|  | ||||
| The original Licensor warrants that the copyright in the Original Work granted | ||||
| hereunder is owned by him/her or licensed to him/her and that he/she has the | ||||
| power and authority to grant the Licence. | ||||
|  | ||||
| Each Contributor warrants that the copyright in the modifications he/she | ||||
| brings to the Work are owned by him/her or licensed to him/her and that he/she | ||||
| has the power and authority to grant the Licence. | ||||
|  | ||||
| Each time You accept the Licence, the original Licensor and subsequent | ||||
| Contributors grant You a licence to their contributions to the Work, under the | ||||
| terms of this Licence. | ||||
|  | ||||
| 7. Disclaimer of Warranty | ||||
|  | ||||
| The Work is a work in progress, which is continuously improved by numerous | ||||
| Contributors. It is not a finished work and may therefore contain defects or | ||||
| ‘bugs’ inherent to this type of development. | ||||
|  | ||||
| For the above reason, the Work is provided under the Licence on an ‘as is’ | ||||
| basis and without warranties of any kind concerning the Work, including | ||||
| without limitation merchantability, fitness for a particular purpose, absence | ||||
| of defects or errors, accuracy, non-infringement of intellectual property | ||||
| rights other than copyright as stated in Article 6 of this Licence. | ||||
|  | ||||
| This disclaimer of warranty is an essential part of the Licence and a | ||||
| condition for the grant of any rights to the Work. | ||||
|  | ||||
| 8. Disclaimer of Liability | ||||
|  | ||||
| Except in the cases of wilful misconduct or damages directly caused to natural | ||||
| persons, the Licensor will in no event be liable for any direct or indirect, | ||||
| material or moral, damages of any kind, arising out of the Licence or of the | ||||
| use of the Work, including without limitation, damages for loss of goodwill, | ||||
| work stoppage, computer failure or malfunction, loss of data or any commercial | ||||
| damage, even if the Licensor has been advised of the possibility of such | ||||
| damage. However, the Licensor will be liable under statutory product liability | ||||
| laws as far such laws apply to the Work. | ||||
|  | ||||
| 9. Additional agreements | ||||
|  | ||||
| While distributing the Work, You may choose to conclude an additional | ||||
| agreement, defining obligations or services consistent with this Licence. | ||||
| However, if accepting obligations, You may act only on your own behalf and on | ||||
| your sole responsibility, not on behalf of the original Licensor or any other | ||||
| Contributor, and only if You agree to indemnify, defend, and hold each | ||||
| Contributor harmless for any liability incurred by, or claims asserted against | ||||
| such Contributor by the fact You have accepted any warranty or additional | ||||
| liability. | ||||
|  | ||||
| 10. Acceptance of the Licence | ||||
|  | ||||
| The provisions of this Licence can be accepted by clicking on an icon ‘I | ||||
| agree’ placed under the bottom of a window displaying the text of this Licence | ||||
| or by affirming consent in any other similar way, in accordance with the rules | ||||
| of applicable law. Clicking on that icon indicates your clear and irrevocable | ||||
| acceptance of this Licence and all of its terms and conditions. | ||||
|  | ||||
| Similarly, you irrevocably accept this Licence and all of its terms and | ||||
| conditions by exercising any rights granted to You by Article 2 of this | ||||
| Licence, such as the use of the Work, the creation by You of a Derivative Work | ||||
| or the Distribution or Communication by You of the Work or copies thereof. | ||||
|  | ||||
| 11. Information to the public | ||||
|  | ||||
| In case of any Distribution or Communication of the Work by means of | ||||
| electronic communication by You (for example, by offering to download the Work | ||||
| from a remote location) the distribution channel or media (for example, a | ||||
| website) must at least provide to the public the information requested by the | ||||
| applicable law regarding the Licensor, the Licence and the way it may be | ||||
| accessible, concluded, stored and reproduced by the Licensee. | ||||
|  | ||||
| 12. Termination of the Licence | ||||
|  | ||||
| The Licence and the rights granted hereunder will terminate automatically upon | ||||
| any breach by the Licensee of the terms of the Licence. | ||||
|  | ||||
| Such a termination will not terminate the licences of any person who has | ||||
| received the Work from the Licensee under the Licence, provided such persons | ||||
| remain in full compliance with the Licence. | ||||
|  | ||||
| 13. Miscellaneous | ||||
|  | ||||
| Without prejudice of Article 9 above, the Licence represents the complete | ||||
| agreement between the Parties as to the Work. | ||||
|  | ||||
| If any provision of the Licence is invalid or unenforceable under applicable | ||||
| law, this will not affect the validity or enforceability of the Licence as a | ||||
| whole. Such provision will be construed or reformed so as necessary to make it | ||||
| valid and enforceable. | ||||
|  | ||||
| The European Commission may publish other linguistic versions or new versions | ||||
| of this Licence or updated versions of the Appendix, so far this is required | ||||
| and reasonable, without reducing the scope of the rights granted by the | ||||
| Licence. New versions of the Licence will be published with a unique version | ||||
| number. | ||||
|  | ||||
| All linguistic versions of this Licence, approved by the European Commission, | ||||
| have identical value. Parties can take advantage of the linguistic version of | ||||
| their choice. | ||||
|  | ||||
| 14. Jurisdiction | ||||
|  | ||||
| Without prejudice to specific agreement between parties, | ||||
|  | ||||
| - any litigation resulting from the interpretation of this License, arising | ||||
|   between the European Union institutions, bodies, offices or agencies, as a | ||||
|   Licensor, and any Licensee, will be subject to the jurisdiction of the Court | ||||
|   of Justice of the European Union, as laid down in article 272 of the Treaty | ||||
|   on the Functioning of the European Union, | ||||
|  | ||||
| - any litigation arising between other parties and resulting from the | ||||
|   interpretation of this License, will be subject to the exclusive | ||||
|   jurisdiction of the competent court where the Licensor resides or conducts | ||||
|   its primary business. | ||||
|  | ||||
| 15. Applicable Law | ||||
|  | ||||
| Without prejudice to specific agreement between parties, | ||||
|  | ||||
| - this Licence shall be governed by the law of the European Union Member State | ||||
|   where the Licensor has his seat, resides or has his registered office, | ||||
|  | ||||
| - this licence shall be governed by Belgian law if the Licensor has no seat, | ||||
|   residence or registered office inside a European Union Member State. | ||||
|  | ||||
| Appendix | ||||
|  | ||||
| ‘Compatible Licences’ according to Article 5 EUPL are: | ||||
|  | ||||
| - GNU General Public License (GPL) v. 2, v. 3 | ||||
| - GNU Affero General Public License (AGPL) v. 3 | ||||
| - Open Software License (OSL) v. 2.1, v. 3.0 | ||||
| - Eclipse Public License (EPL) v. 1.0 | ||||
| - CeCILL v. 2.0, v. 2.1 | ||||
| - Mozilla Public Licence (MPL) v. 2 | ||||
| - GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 | ||||
| - Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for | ||||
|   works other than software | ||||
| - European Union Public Licence (EUPL) v. 1.1, v. 1.2 | ||||
| - Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong | ||||
|   Reciprocity (LiLiQ-R+). | ||||
|  | ||||
| The European Commission may update this Appendix to later versions of the | ||||
| above licences without producing a new version of the EUPL, as long as they | ||||
| provide the rights granted in Article 2 of this Licence and protect the | ||||
| covered Source Code from exclusive appropriation. | ||||
|  | ||||
| All other changes or additions to this Appendix require the production of a | ||||
| new EUPL version. | ||||
							
								
								
									
										6
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,18 +1,18 @@ | ||||
| { | ||||
|   "name": "wled", | ||||
|   "version": "0.15.0-b5", | ||||
|   "version": "0.15.0-rc1", | ||||
|   "lockfileVersion": 3, | ||||
|   "requires": true, | ||||
|   "packages": { | ||||
|     "": { | ||||
|       "name": "wled", | ||||
|       "version": "0.15.0-b5", | ||||
|       "version": "0.15.0-rc1", | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "clean-css": "^5.3.3", | ||||
|         "html-minifier-terser": "^7.2.0", | ||||
|         "inliner": "^1.13.1", | ||||
|         "nodemon": "^3.0.2" | ||||
|         "nodemon": "^3.1.7" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@jridgewell/gen-mapping": { | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "wled", | ||||
|   "version": "0.15.0-b5", | ||||
|   "version": "0.15.0-rc1", | ||||
|   "description": "Tools for WLED project", | ||||
|   "main": "tools/cdata.js", | ||||
|   "directories": { | ||||
| @@ -27,5 +27,8 @@ | ||||
|     "html-minifier-terser": "^7.2.0", | ||||
|     "inliner": "^1.13.1", | ||||
|     "nodemon": "^3.1.7" | ||||
|   }, | ||||
|   "engines": { | ||||
|     "node": ">=20.0.0" | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -19,8 +19,9 @@ def _create_dirs(dirs=["map", "release", "firmware"]): | ||||
|         os.makedirs(os.path.join(OUTPUT_DIR, d), exist_ok=True) | ||||
|  | ||||
| def create_release(source): | ||||
|     release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME") | ||||
|     if release_name: | ||||
|     release_name_def = _get_cpp_define_value(env, "WLED_RELEASE_NAME") | ||||
|     if release_name_def: | ||||
|         release_name = release_name_def.replace("\\\"", "") | ||||
|         version = _get_cpp_define_value(env, "WLED_VERSION") | ||||
|         release_file = os.path.join(OUTPUT_DIR, "release", f"WLED_{version}_{release_name}.bin") | ||||
|         release_gz_file = release_file + ".gz" | ||||
|   | ||||
| @@ -197,6 +197,7 @@ build_flags = | ||||
|   ; decrease code cache size and increase IRAM to fit all pixel functions | ||||
|   -D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48 ;; in case of linker errors like "section `.text1' will not fit in region `iram1_0_seg'" | ||||
|   ; -D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED ;; (experimental) adds some extra heap, but may cause slowdown | ||||
|   -D NON32XFER_HANDLER ;; ask forgiveness for PROGMEM misuse | ||||
|  | ||||
| lib_deps = | ||||
|   #https://github.com/lorol/LITTLEFS.git | ||||
| @@ -259,7 +260,8 @@ lib_deps = | ||||
|   https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 | ||||
|   ${env.lib_deps} | ||||
| # additional build flags for audioreactive | ||||
| AR_build_flags = -D USERMOD_AUDIOREACTIVE | ||||
| AR_build_flags = -D USERMOD_AUDIOREACTIVE  | ||||
|   -D sqrt_internal=sqrtf ;; -fsingle-precision-constant ;; forces ArduinoFFT to use float math (2x faster) | ||||
| AR_lib_deps = kosme/arduinoFFT @ 2.0.1 | ||||
|  | ||||
| [esp32_idf_V4] | ||||
| @@ -343,7 +345,7 @@ platform = ${common.platform_wled_default} | ||||
| platform_packages = ${common.platform_packages} | ||||
| board_build.ldscript = ${common.ldscript_4m1m} | ||||
| build_unflags = ${common.build_unflags} | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP8266 #-DWLED_DISABLE_2D | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP8266\" #-DWLED_DISABLE_2D | ||||
| lib_deps = ${esp8266.lib_deps} | ||||
| monitor_filters = esp8266_exception_decoder | ||||
|  | ||||
| @@ -352,13 +354,13 @@ extends = env:nodemcuv2 | ||||
| ;; using platform version and build options from WLED 0.14.0 | ||||
| platform = ${esp8266.platform_compat} | ||||
| platform_packages = ${esp8266.platform_packages_compat} | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=ESP8266_compat #-DWLED_DISABLE_2D | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=\"ESP8266_compat\" #-DWLED_DISABLE_2D | ||||
| ;; lib_deps = ${esp8266.lib_deps_compat} ;; experimental - use older NeoPixelBus 2.7.9 | ||||
|  | ||||
| [env:nodemcuv2_160] | ||||
| extends = env:nodemcuv2 | ||||
| board_build.f_cpu = 160000000L | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP8266_160 #-DWLED_DISABLE_2D | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP8266_160\" #-DWLED_DISABLE_2D | ||||
|   -D USERMOD_AUDIOREACTIVE | ||||
|  | ||||
| [env:esp8266_2m] | ||||
| @@ -367,7 +369,7 @@ platform = ${common.platform_wled_default} | ||||
| platform_packages = ${common.platform_packages} | ||||
| board_build.ldscript = ${common.ldscript_2m512k} | ||||
| build_unflags = ${common.build_unflags} | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP02 | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP02\" | ||||
| lib_deps = ${esp8266.lib_deps} | ||||
|  | ||||
| [env:esp8266_2m_compat] | ||||
| @@ -375,12 +377,12 @@ extends = env:esp8266_2m | ||||
| ;; using platform version and build options from WLED 0.14.0 | ||||
| platform = ${esp8266.platform_compat} | ||||
| platform_packages = ${esp8266.platform_packages_compat} | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=ESP02_compat #-DWLED_DISABLE_2D | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=\"ESP02_compat\" #-DWLED_DISABLE_2D | ||||
|  | ||||
| [env:esp8266_2m_160] | ||||
| extends = env:esp8266_2m | ||||
| board_build.f_cpu = 160000000L | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP02_160 | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP02_160\" | ||||
|   -D USERMOD_AUDIOREACTIVE | ||||
|  | ||||
| [env:esp01_1m_full] | ||||
| @@ -389,7 +391,7 @@ platform = ${common.platform_wled_default} | ||||
| platform_packages = ${common.platform_packages} | ||||
| board_build.ldscript = ${common.ldscript_1m128k} | ||||
| build_unflags = ${common.build_unflags} | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP01 -D WLED_DISABLE_OTA | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP01\" -D WLED_DISABLE_OTA | ||||
|   ; -D WLED_USE_REAL_MATH ;; may fix wrong sunset/sunrise times, at the cost of 7064 bytes FLASH and 975 bytes RAM | ||||
| lib_deps = ${esp8266.lib_deps} | ||||
|  | ||||
| @@ -398,12 +400,12 @@ extends = env:esp01_1m_full | ||||
| ;; using platform version and build options from WLED 0.14.0 | ||||
| platform = ${esp8266.platform_compat} | ||||
| platform_packages = ${esp8266.platform_packages_compat} | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=ESP01_compat -D WLED_DISABLE_OTA #-DWLED_DISABLE_2D | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=\"ESP01_compat\" -D WLED_DISABLE_OTA #-DWLED_DISABLE_2D | ||||
|  | ||||
| [env:esp01_1m_full_160] | ||||
| extends = env:esp01_1m_full | ||||
| board_build.f_cpu = 160000000L | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP01_160 -D WLED_DISABLE_OTA | ||||
| build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP01_160\" -D WLED_DISABLE_OTA | ||||
|   -D USERMOD_AUDIOREACTIVE | ||||
|   ; -D WLED_USE_REAL_MATH ;; may fix wrong sunset/sunrise times, at the cost of 7064 bytes FLASH and 975 bytes RAM | ||||
|  | ||||
| @@ -412,7 +414,7 @@ board = esp32dev | ||||
| platform = ${esp32.platform} | ||||
| platform_packages = ${esp32.platform_packages} | ||||
| build_unflags = ${common.build_unflags} | ||||
| build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=ESP32 #-D WLED_DISABLE_BROWNOUT_DET | ||||
| build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32\" #-D WLED_DISABLE_BROWNOUT_DET | ||||
|   ${esp32.AR_build_flags} | ||||
| lib_deps = ${esp32.lib_deps} | ||||
|   ${esp32.AR_lib_deps} | ||||
| @@ -424,20 +426,39 @@ board = esp32dev | ||||
| platform = ${esp32_idf_V4.platform} | ||||
| platform_packages = ${esp32_idf_V4.platform_packages} | ||||
| build_unflags = ${common.build_unflags} | ||||
| build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=ESP32_8M #-D WLED_DISABLE_BROWNOUT_DET | ||||
| build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_8M\" #-D WLED_DISABLE_BROWNOUT_DET | ||||
|   ${esp32.AR_build_flags} | ||||
| lib_deps = ${esp32_idf_V4.lib_deps} | ||||
|   ${esp32.AR_lib_deps} | ||||
| monitor_filters = esp32_exception_decoder | ||||
| board_build.partitions = ${esp32.large_partitions} | ||||
| board_upload.flash_size = 8MB | ||||
| board_upload.maximum_size = 8388608 | ||||
| ; board_build.f_flash = 80000000L | ||||
| ; board_build.flash_mode = qio | ||||
|  | ||||
| [env:esp32dev_16M] | ||||
| board = esp32dev | ||||
| platform = ${esp32_idf_V4.platform} | ||||
| platform_packages = ${esp32_idf_V4.platform_packages} | ||||
| build_unflags = ${common.build_unflags} | ||||
| build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_16M\" #-D WLED_DISABLE_BROWNOUT_DET | ||||
|   ${esp32.AR_build_flags} | ||||
| lib_deps = ${esp32_idf_V4.lib_deps} | ||||
|   ${esp32.AR_lib_deps} | ||||
| monitor_filters = esp32_exception_decoder | ||||
| board_build.partitions = ${esp32.extreme_partitions} | ||||
| board_upload.flash_size = 16MB | ||||
| board_upload.maximum_size = 16777216 | ||||
| board_build.f_flash = 80000000L | ||||
| board_build.flash_mode = dio | ||||
|  | ||||
| ;[env:esp32dev_audioreactive] | ||||
| ;board = esp32dev | ||||
| ;platform = ${esp32.platform} | ||||
| ;platform_packages = ${esp32.platform_packages} | ||||
| ;build_unflags = ${common.build_unflags} | ||||
| ;build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=ESP32_audioreactive #-D WLED_DISABLE_BROWNOUT_DET | ||||
| ;build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32_audioreactive\" #-D WLED_DISABLE_BROWNOUT_DET | ||||
| ;  ${esp32.AR_build_flags} | ||||
| ;lib_deps = ${esp32.lib_deps} | ||||
| ;  ${esp32.AR_lib_deps} | ||||
| @@ -452,7 +473,7 @@ platform = ${esp32.platform} | ||||
| platform_packages = ${esp32.platform_packages} | ||||
| upload_speed = 921600 | ||||
| build_unflags = ${common.build_unflags} | ||||
| build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=ESP32_Ethernet -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 | ||||
| build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32_Ethernet\" -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 | ||||
| ;  -D WLED_DISABLE_ESPNOW ;; ESP-NOW requires wifi, may crash with ethernet only | ||||
|   ${esp32.AR_build_flags} | ||||
| lib_deps = ${esp32.lib_deps} | ||||
| @@ -468,7 +489,7 @@ board_build.f_flash = 80000000L | ||||
| board_build.flash_mode = qio | ||||
| board_build.partitions = ${esp32.extended_partitions} | ||||
| build_unflags = ${common.build_unflags} | ||||
| build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=ESP32_WROVER | ||||
| build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_WROVER\" | ||||
|   -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 DATA_PINS=25 | ||||
|   ${esp32.AR_build_flags} | ||||
| @@ -482,7 +503,7 @@ platform_packages = ${esp32c3.platform_packages} | ||||
| framework = arduino | ||||
| board = esp32-c3-devkitm-1 | ||||
| board_build.partitions = ${esp32.default_partitions} | ||||
| build_flags = ${common.build_flags} ${esp32c3.build_flags} -D WLED_RELEASE_NAME=ESP32-C3 | ||||
| build_flags = ${common.build_flags} ${esp32c3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-C3\" | ||||
|   -D WLED_WATCHDOG_TIMEOUT=0 | ||||
|   -DLOLIN_WIFI_FIX ; seems to work much better with this | ||||
|   -DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB | ||||
| @@ -499,7 +520,7 @@ platform = ${esp32s3.platform} | ||||
| platform_packages = ${esp32s3.platform_packages} | ||||
| upload_speed = 921600 | ||||
| build_unflags = ${common.build_unflags} | ||||
| build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_16MB_opi | ||||
| build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_16MB_opi\" | ||||
|   -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 | ||||
|   ;-D ARDUINO_USB_CDC_ON_BOOT=0  ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip | ||||
|   -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1      ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") | ||||
| @@ -508,6 +529,8 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME= | ||||
| lib_deps = ${esp32s3.lib_deps} | ||||
|   ${esp32.AR_lib_deps} | ||||
| board_build.partitions = ${esp32.extreme_partitions} | ||||
| board_upload.flash_size = 16MB | ||||
| board_upload.maximum_size = 16777216 | ||||
| board_build.f_flash = 80000000L | ||||
| board_build.flash_mode = qio | ||||
| monitor_filters = esp32_exception_decoder | ||||
| @@ -520,7 +543,7 @@ platform = ${esp32s3.platform} | ||||
| platform_packages = ${esp32s3.platform_packages} | ||||
| upload_speed = 921600 | ||||
| build_unflags = ${common.build_unflags} | ||||
| build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_8MB_opi | ||||
| build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_8MB_opi\" | ||||
|   -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 | ||||
|   ;-D ARDUINO_USB_CDC_ON_BOOT=0  ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip | ||||
|   -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1      ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") | ||||
| @@ -533,6 +556,33 @@ board_build.f_flash = 80000000L | ||||
| board_build.flash_mode = qio | ||||
| monitor_filters = esp32_exception_decoder | ||||
|  | ||||
| [env:esp32S3_wroom2] | ||||
| ;; For ESP32-S3 WROOM-2, a.k.a. ESP32-S3 DevKitC-1 v1.1 | ||||
| ;; with >= 16MB FLASH and >= 8MB PSRAM (memory_type: opi_opi) | ||||
| platform = ${esp32s3.platform} | ||||
| platform_packages = ${esp32s3.platform_packages} | ||||
| board = esp32s3camlcd ;; this is the only standard board with "opi_opi" | ||||
| board_build.arduino.memory_type = opi_opi | ||||
| upload_speed = 921600 | ||||
| build_unflags = ${common.build_unflags} | ||||
| build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_WROOM-2\" | ||||
|   -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 | ||||
|   -D ARDUINO_USB_CDC_ON_BOOT=0  ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip | ||||
|   ;; -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1      ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") | ||||
|   -DBOARD_HAS_PSRAM | ||||
|   -D LEDPIN=38 -D DATA_PINS=38 ;; buildin WS2812b LED | ||||
|   -D BTNPIN=0 -D RLYPIN=16 -D IRPIN=17 -D AUDIOPIN=-1 | ||||
|   -D WLED_DEBUG | ||||
|   ${esp32.AR_build_flags} | ||||
|   -D SR_DMTYPE=1 -D I2S_SDPIN=13 -D I2S_CKPIN=14 -D I2S_WSPIN=15 -D MCLK_PIN=4  ;; I2S mic | ||||
| lib_deps = ${esp32s3.lib_deps} | ||||
|   ${esp32.AR_lib_deps} | ||||
|  | ||||
| board_build.partitions = ${esp32.extreme_partitions} | ||||
| board_upload.flash_size = 16MB | ||||
| board_upload.maximum_size = 16777216 | ||||
| monitor_filters = esp32_exception_decoder | ||||
|  | ||||
| [env:esp32s3_4M_qspi] | ||||
| ;; ESP32-S3, with 4MB FLASH and <= 4MB PSRAM (memory_type: qio_qspi) | ||||
| board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM  | ||||
| @@ -540,7 +590,7 @@ platform = ${esp32s3.platform} | ||||
| platform_packages = ${esp32s3.platform_packages} | ||||
| upload_speed = 921600 | ||||
| build_unflags = ${common.build_unflags} | ||||
| build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_4M_qspi | ||||
| build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_4M_qspi\" | ||||
|   -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MODE=1      ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") | ||||
|   -DBOARD_HAS_PSRAM | ||||
|   -DLOLIN_WIFI_FIX ; seems to work much better with this | ||||
| @@ -561,7 +611,7 @@ board_build.partitions = ${esp32.default_partitions} | ||||
| board_build.flash_mode = qio | ||||
| board_build.f_flash = 80000000L | ||||
| build_unflags = ${common.build_unflags} | ||||
| build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=ESP32-S2 | ||||
| build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S2\" | ||||
|   -DARDUINO_USB_CDC_ON_BOOT=1 | ||||
|   -DARDUINO_USB_MSC_ON_BOOT=0 | ||||
|   -DARDUINO_USB_DFU_ON_BOOT=0 | ||||
|   | ||||
| @@ -37,7 +37,7 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} | ||||
| ; *** To use the below defines/overrides, copy and paste each onto it's own line just below build_flags in the section above. | ||||
| ;  | ||||
| ; Set a release name that may be used to distinguish required binary for flashing | ||||
| ;   -D WLED_RELEASE_NAME=ESP32_MULTI_USREMODS | ||||
| ;   -D WLED_RELEASE_NAME=\"ESP32_MULTI_USREMODS\" | ||||
| ; | ||||
| ; disable specific features | ||||
| ;   -D WLED_DISABLE_OTA | ||||
| @@ -111,7 +111,6 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} | ||||
| ; | ||||
| ; Use 4 Line Display usermod with SPI display | ||||
| ;   -D USERMOD_FOUR_LINE_DISPLAY | ||||
| ;   -D USE_ALT_DISPlAY # mandatory | ||||
| ;   -DFLD_SPI_DEFAULT | ||||
| ;   -D FLD_TYPE=SSD1306_SPI64 | ||||
| ;   -D FLD_PIN_CLOCKSPI=14 | ||||
| @@ -359,6 +358,8 @@ upload_speed = 115200 | ||||
| lib_deps = ${esp32c3.lib_deps} | ||||
| board_build.partitions = tools/WLED_ESP32_2MB_noOTA.csv | ||||
| board_build.flash_mode = dio | ||||
| board_upload.flash_size = 2MB | ||||
| board_upload.maximum_size = 2097152 | ||||
|  | ||||
| [env:wemos_shield_esp32] | ||||
| board = esp32dev | ||||
| @@ -375,7 +376,6 @@ build_flags = ${common.build_flags} ${esp32.build_flags} | ||||
|   -D USERMOD_DALLASTEMPERATURE | ||||
|   -D USERMOD_FOUR_LINE_DISPLAY | ||||
|   -D TEMPERATURE_PIN=23 | ||||
|   -D USE_ALT_DISPlAY ; new versions of USERMOD_FOUR_LINE_DISPLAY and USERMOD_ROTARY_ENCODER_UI | ||||
|   -D USERMOD_AUDIOREACTIVE | ||||
| lib_deps = ${esp32.lib_deps} | ||||
|   OneWire@~2.3.5 | ||||
|   | ||||
| @@ -61,7 +61,7 @@ See [here](https://kno.wled.ge/basics/compatible-hardware)! | ||||
|  | ||||
| ## ✌️ Other | ||||
|  | ||||
| Licensed under the MIT license   | ||||
| Licensed under the EUPL v1.2 license   | ||||
| Credits [here](https://kno.wled.ge/about/contributors/)! | ||||
|  | ||||
| Join the Discord server to discuss everything about WLED! | ||||
| @@ -80,5 +80,5 @@ If WLED really brightens up your day, you can [ { | ||||
| async function minify(str, type = "plain") { | ||||
|   const options = { | ||||
|     collapseWhitespace: true, | ||||
|     conservativeCollapse: true, // preserve spaces in text | ||||
|     collapseBooleanAttributes: true, | ||||
|     collapseInlineTagWhitespace: true, | ||||
|     minifyCSS: true, | ||||
|   | ||||
| @@ -102,9 +102,9 @@ private: | ||||
|  | ||||
|     void secondsEffectSineFade(int16_t secondLed, Toki::Time const& time) { | ||||
|         uint32_t ms = time.ms % 1000; | ||||
|         uint8_t b0 = (cos8(ms * 64 / 1000) - 128) * 2; | ||||
|         uint8_t b0 = (cos8_t(ms * 64 / 1000) - 128) * 2; | ||||
|         setPixelColor(secondLed, gamma32(scale32(secondColor, b0))); | ||||
|         uint8_t b1 = (sin8(ms * 64 / 1000) - 128) * 2; | ||||
|         uint8_t b1 = (sin8_t(ms * 64 / 1000) - 128) * 2; | ||||
|         setPixelColor(inc(secondLed, 1, secondsSegment), gamma32(scale32(secondColor, b1))); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -425,10 +425,10 @@ class Animated_Staircase : public Usermod { | ||||
|     } | ||||
|  | ||||
|     void appendConfigData() { | ||||
|       //oappend(SET_F("dd=addDropdown('staircase','selectfield');")); | ||||
|       //oappend(SET_F("addOption(dd,'1st value',0);")); | ||||
|       //oappend(SET_F("addOption(dd,'2nd value',1);")); | ||||
|       //oappend(SET_F("addInfo('staircase:selectfield',1,'additional info');"));  // 0 is field type, 1 is actual field | ||||
|       //oappend(F("dd=addDropdown('staircase','selectfield');")); | ||||
|       //oappend(F("addOption(dd,'1st value',0);")); | ||||
|       //oappend(F("addOption(dd,'2nd value',1);")); | ||||
|       //oappend(F("addInfo('staircase:selectfield',1,'additional info');"));  // 0 is field type, 1 is actual field | ||||
|     } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -767,22 +767,22 @@ void UsermodBME68X::appendConfigData() { | ||||
| 	// snprintf_P(charbuffer, 127, PSTR("addInfo('%s:%s',1,'*) Set to minus to deactivate (all sensors)');"), UMOD_NAME, _nameTemp); oappend(charbuffer); | ||||
|  | ||||
| 	/* Dropdown for Celsius/Fahrenheit*/ | ||||
| 	oappend(SET_F("dd=addDropdown('")); | ||||
| 	oappend(F("dd=addDropdown('")); | ||||
| 	oappend(UMOD_NAME); | ||||
| 	oappend(SET_F("','")); | ||||
| 	oappend(F("','")); | ||||
| 	oappend(_nameTempScale); | ||||
| 	oappend(SET_F("');")); | ||||
| 	oappend(SET_F("addOption(dd,'Celsius',0);")); | ||||
| 	oappend(SET_F("addOption(dd,'Fahrenheit',1);")); | ||||
| 	oappend(F("');")); | ||||
| 	oappend(F("addOption(dd,'Celsius',0);")); | ||||
| 	oappend(F("addOption(dd,'Fahrenheit',1);")); | ||||
|  | ||||
| 	/* i²C Address*/ | ||||
| 	oappend(SET_F("dd=addDropdown('")); | ||||
| 	oappend(F("dd=addDropdown('")); | ||||
| 	oappend(UMOD_NAME); | ||||
| 	oappend(SET_F("','")); | ||||
| 	oappend(F("','")); | ||||
| 	oappend(_nameI2CAdr); | ||||
| 	oappend(SET_F("');")); | ||||
| 	oappend(SET_F("addOption(dd,'0x76',0x76);")); | ||||
| 	oappend(SET_F("addOption(dd,'0x77',0x77);")); | ||||
| 	oappend(F("');")); | ||||
| 	oappend(F("addOption(dd,'0x76',0x76);")); | ||||
| 	oappend(F("addOption(dd,'0x77',0x77);")); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -478,29 +478,29 @@ class UsermodBattery : public Usermod | ||||
|     void appendConfigData() | ||||
|     { | ||||
|       // Total: 462 Bytes | ||||
|       oappend(SET_F("td=addDropdown('Battery','type');"));              // 34 Bytes | ||||
|       oappend(SET_F("addOption(td,'Unkown','0');"));                    // 28 Bytes | ||||
|       oappend(SET_F("addOption(td,'LiPo','1');"));                      // 26 Bytes | ||||
|       oappend(SET_F("addOption(td,'LiOn','2');"));                      // 26 Bytes | ||||
|       oappend(SET_F("addInfo('Battery:type',1,'<small style=\"color:orange\">requires reboot</small>');")); // 81 Bytes | ||||
|       oappend(SET_F("addInfo('Battery:min-voltage',1,'v');"));          // 38 Bytes | ||||
|       oappend(SET_F("addInfo('Battery:max-voltage',1,'v');"));          // 38 Bytes | ||||
|       oappend(SET_F("addInfo('Battery:interval',1,'ms');"));            // 36 Bytes | ||||
|       oappend(SET_F("addInfo('Battery:HA-discovery',1,'');"));          // 38 Bytes | ||||
|       oappend(SET_F("addInfo('Battery:auto-off:threshold',1,'%');"));   // 45 Bytes | ||||
|       oappend(SET_F("addInfo('Battery:indicator:threshold',1,'%');"));  // 46 Bytes | ||||
|       oappend(SET_F("addInfo('Battery:indicator:duration',1,'s');"));   // 45 Bytes | ||||
|       oappend(F("td=addDropdown('Battery','type');"));              // 34 Bytes | ||||
|       oappend(F("addOption(td,'Unkown','0');"));                    // 28 Bytes | ||||
|       oappend(F("addOption(td,'LiPo','1');"));                      // 26 Bytes | ||||
|       oappend(F("addOption(td,'LiOn','2');"));                      // 26 Bytes | ||||
|       oappend(F("addInfo('Battery:type',1,'<small style=\"color:orange\">requires reboot</small>');")); // 81 Bytes | ||||
|       oappend(F("addInfo('Battery:min-voltage',1,'v');"));          // 38 Bytes | ||||
|       oappend(F("addInfo('Battery:max-voltage',1,'v');"));          // 38 Bytes | ||||
|       oappend(F("addInfo('Battery:interval',1,'ms');"));            // 36 Bytes | ||||
|       oappend(F("addInfo('Battery:HA-discovery',1,'');"));          // 38 Bytes | ||||
|       oappend(F("addInfo('Battery:auto-off:threshold',1,'%');"));   // 45 Bytes | ||||
|       oappend(F("addInfo('Battery:indicator:threshold',1,'%');"));  // 46 Bytes | ||||
|       oappend(F("addInfo('Battery:indicator:duration',1,'s');"));   // 45 Bytes | ||||
|        | ||||
|       // this option list would exeed the oappend() buffer | ||||
|       // a list of all presets to select one from | ||||
|       // oappend(SET_F("bd=addDropdown('Battery:low-power-indicator', 'preset');")); | ||||
|       // the loop generates: oappend(SET_F("addOption(bd, 'preset name', preset id);")); | ||||
|       // oappend(F("bd=addDropdown('Battery:low-power-indicator', 'preset');")); | ||||
|       // the loop generates: oappend(F("addOption(bd, 'preset name', preset id);")); | ||||
|       // for(int8_t i=1; i < 42; i++) { | ||||
|       //   oappend(SET_F("addOption(bd, 'Preset#")); | ||||
|       //   oappend(F("addOption(bd, 'Preset#")); | ||||
|       //   oappendi(i); | ||||
|       //   oappend(SET_F("',")); | ||||
|       //   oappend(F("',")); | ||||
|       //   oappendi(i); | ||||
|       //   oappend(SET_F(");")); | ||||
|       //   oappend(F(");")); | ||||
|       // } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -287,11 +287,11 @@ class MyExampleUsermod : public Usermod { | ||||
|      */ | ||||
|     void appendConfigData() override | ||||
|     { | ||||
|       oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":great")); oappend(SET_F("',1,'<i>(this is a great config value)</i>');")); | ||||
|       oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":testString")); oappend(SET_F("',1,'enter any string you want');")); | ||||
|       oappend(SET_F("dd=addDropdown('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F("','testInt');")); | ||||
|       oappend(SET_F("addOption(dd,'Nothing',0);")); | ||||
|       oappend(SET_F("addOption(dd,'Everything',42);")); | ||||
|       oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":great")); oappend(F("',1,'<i>(this is a great config value)</i>');")); | ||||
|       oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":testString")); oappend(F("',1,'enter any string you want');")); | ||||
|       oappend(F("dd=addDropdown('")); oappend(String(FPSTR(_name)).c_str()); oappend(F("','testInt');")); | ||||
|       oappend(F("addOption(dd,'Nothing',0);")); | ||||
|       oappend(F("addOption(dd,'Everything',42);")); | ||||
|     } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -149,11 +149,11 @@ public: | ||||
|     void appendConfigData() | ||||
|     { | ||||
|     // Display 'ms' next to the 'Loop Interval' setting | ||||
|     oappend(SET_F("addInfo('Internal Temperature:Loop Interval', 1, 'ms');")); | ||||
|     oappend(F("addInfo('Internal Temperature:Loop Interval', 1, 'ms');")); | ||||
|     // Display '°C' next to the 'Activation Threshold' setting | ||||
|     oappend(SET_F("addInfo('Internal Temperature:Activation Threshold', 1, '°C');")); | ||||
|     oappend(F("addInfo('Internal Temperature:Activation Threshold', 1, '°C');")); | ||||
|     // Display '0 = Disabled' next to the 'Preset To Activate' setting | ||||
|     oappend(SET_F("addInfo('Internal Temperature:Preset To Activate', 1, '0 = unused');")); | ||||
|     oappend(F("addInfo('Internal Temperature:Preset To Activate', 1, '0 = unused');")); | ||||
|     } | ||||
|  | ||||
|   bool readFromConfig(JsonObject &root) | ||||
|   | ||||
| @@ -511,8 +511,8 @@ void PIRsensorSwitch::addToConfig(JsonObject &root) | ||||
|  | ||||
| void PIRsensorSwitch::appendConfigData() | ||||
| { | ||||
|   oappend(SET_F("addInfo('PIRsensorSwitch:HA-discovery',1,'HA=Home Assistant');"));     // 0 is field type, 1 is actual field | ||||
|   oappend(SET_F("addInfo('PIRsensorSwitch:override',1,'Cancel timer on change');"));    // 0 is field type, 1 is actual field | ||||
|   oappend(F("addInfo('PIRsensorSwitch:HA-discovery',1,'HA=Home Assistant');"));     // 0 is field type, 1 is actual field | ||||
|   oappend(F("addInfo('PIRsensorSwitch:override',1,'Cancel timer on change');"));    // 0 is field type, 1 is actual field | ||||
|   for (int i = 0; i < PIR_SENSOR_MAX_SENSORS; i++) { | ||||
|     char str[128]; | ||||
|     sprintf_P(str, PSTR("addInfo('PIRsensorSwitch:pin[]',%d,'','#%d');"), i, i); | ||||
|   | ||||
| @@ -377,10 +377,10 @@ class St7789DisplayUsermod : public Usermod { | ||||
|  | ||||
|  | ||||
|     void appendConfigData() override { | ||||
|       oappend(SET_F("addInfo('ST7789:pin[]',0,'','SPI CS');")); | ||||
|       oappend(SET_F("addInfo('ST7789:pin[]',1,'','SPI DC');")); | ||||
|       oappend(SET_F("addInfo('ST7789:pin[]',2,'','SPI RST');")); | ||||
|       oappend(SET_F("addInfo('ST7789:pin[]',3,'','SPI BL');")); | ||||
|       oappend(F("addInfo('ST7789:pin[]',0,'','SPI CS');")); | ||||
|       oappend(F("addInfo('ST7789:pin[]',1,'','SPI DC');")); | ||||
|       oappend(F("addInfo('ST7789:pin[]',2,'','SPI RST');")); | ||||
|       oappend(F("addInfo('ST7789:pin[]',3,'','SPI BL');")); | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|   | ||||
| @@ -435,10 +435,10 @@ bool UsermodTemperature::readFromConfig(JsonObject &root) { | ||||
| } | ||||
|  | ||||
| void UsermodTemperature::appendConfigData() { | ||||
|   oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":")); oappend(String(FPSTR(_parasite)).c_str()); | ||||
|   oappend(SET_F("',1,'<i>(if no Vcc connected)</i>');"));  // 0 is field type, 1 is actual field | ||||
|   oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":")); oappend(String(FPSTR(_parasitePin)).c_str()); | ||||
|   oappend(SET_F("',1,'<i>(for external MOSFET)</i>');"));  // 0 is field type, 1 is actual field | ||||
|   oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":")); oappend(String(FPSTR(_parasite)).c_str()); | ||||
|   oappend(F("',1,'<i>(if no Vcc connected)</i>');"));  // 0 is field type, 1 is actual field | ||||
|   oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":")); oappend(String(FPSTR(_parasitePin)).c_str()); | ||||
|   oappend(F("',1,'<i>(for external MOSFET)</i>');"));  // 0 is field type, 1 is actual field | ||||
| } | ||||
|  | ||||
| float UsermodTemperature::getTemperature() { | ||||
|   | ||||
| @@ -191,8 +191,8 @@ constexpr uint16_t samplesFFT_2 = 256;          // meaningfull part of FFT resul | ||||
| #define LOG_256  5.54517744f                            // log(256) | ||||
|  | ||||
| // These are the input and output vectors.  Input vectors receive computed results from FFT. | ||||
| static float vReal[samplesFFT] = {0.0f};       // FFT sample inputs / freq output -  these are our raw result bins | ||||
| static float vImag[samplesFFT] = {0.0f};       // imaginary parts | ||||
| static float* vReal = nullptr;                  // FFT sample inputs / freq output -  these are our raw result bins | ||||
| static float* vImag = nullptr;                  // imaginary parts | ||||
|  | ||||
| // Create FFT object | ||||
| // lib_deps += https://github.com/kosme/arduinoFFT#develop @ 1.9.2 | ||||
| @@ -200,14 +200,9 @@ static float vImag[samplesFFT] = {0.0f};       // imaginary parts | ||||
| // #define FFT_SPEED_OVER_PRECISION     // enables use of reciprocals (1/x etc) - not faster on ESP32 | ||||
| // #define FFT_SQRT_APPROXIMATION       // enables "quake3" style inverse sqrt  - slower on ESP32 | ||||
| // Below options are forcing ArduinoFFT to use sqrtf() instead of sqrt() | ||||
| #define sqrt(x) sqrtf(x)             // little hack that reduces FFT time by 10-50% on ESP32 | ||||
| #define sqrt_internal sqrtf          // see https://github.com/kosme/arduinoFFT/pull/83 | ||||
|  | ||||
| #include <arduinoFFT.h> | ||||
|  | ||||
| /* Create FFT object with weighing factor storage */ | ||||
| static ArduinoFFT<float> FFT = ArduinoFFT<float>( vReal, vImag, samplesFFT, SAMPLE_RATE, true); | ||||
| // #define sqrt_internal sqrtf          // see https://github.com/kosme/arduinoFFT/pull/83 - since v2.0.0 this must be done in build_flags | ||||
|  | ||||
| #include <arduinoFFT.h>             // FFT object is created in FFTcode | ||||
| // Helper functions | ||||
|  | ||||
| // compute average of several FFT result bins | ||||
| @@ -226,6 +221,18 @@ void FFTcode(void * parameter) | ||||
| { | ||||
|   DEBUGSR_PRINT("FFT started on core: "); DEBUGSR_PRINTLN(xPortGetCoreID()); | ||||
|  | ||||
|   // allocate FFT buffers on first call | ||||
|   if (vReal == nullptr) vReal = (float*) calloc(sizeof(float), samplesFFT); | ||||
|   if (vImag == nullptr) vImag = (float*) calloc(sizeof(float), samplesFFT); | ||||
|   if ((vReal == nullptr) || (vImag == nullptr)) { | ||||
|     // something went wrong | ||||
|     if (vReal) free(vReal); vReal = nullptr; | ||||
|     if (vImag) free(vImag); vImag = nullptr; | ||||
|     return; | ||||
|   } | ||||
|   // Create FFT object with weighing factor storage | ||||
|   ArduinoFFT<float> FFT = ArduinoFFT<float>( vReal, vImag, samplesFFT, SAMPLE_RATE, true); | ||||
|  | ||||
|   // see https://www.freertos.org/vtaskdelayuntil.html | ||||
|   const TickType_t xFrequency = FFT_MIN_CYCLE * portTICK_PERIOD_MS;   | ||||
|  | ||||
| @@ -247,6 +254,7 @@ void FFTcode(void * parameter) | ||||
|  | ||||
|     // get a fresh batch of samples from I2S | ||||
|     if (audioSource) audioSource->getSamples(vReal, samplesFFT); | ||||
|     memset(vImag, 0, samplesFFT * sizeof(float));   // set imaginary parts to 0 | ||||
|  | ||||
| #if defined(WLED_DEBUG) || defined(SR_DEBUG) | ||||
|     if (start < esp_timer_get_time()) { // filter out overflows | ||||
| @@ -265,8 +273,6 @@ void FFTcode(void * parameter) | ||||
|     // find highest sample in the batch | ||||
|     float maxSample = 0.0f;                         // max sample from FFT batch | ||||
|     for (int i=0; i < samplesFFT; i++) { | ||||
| 	    // set imaginary parts to 0 | ||||
|       vImag[i] = 0; | ||||
| 	    // pick our  our current mic sample - we take the max value from all samples that go into FFT | ||||
| 	    if ((vReal[i] <= (INT16_MAX - 1024)) && (vReal[i] >= (INT16_MIN + 1024)))  //skip extreme values - normally these are artefacts | ||||
|         if (fabsf((float)vReal[i]) > maxSample) maxSample = fabsf((float)vReal[i]); | ||||
| @@ -297,7 +303,7 @@ void FFTcode(void * parameter) | ||||
| #endif | ||||
|  | ||||
|     } else { // noise gate closed - only clear results as FFT was skipped. MIC samples are still valid when we do this. | ||||
|       memset(vReal, 0, sizeof(vReal)); | ||||
|       memset(vReal, 0, samplesFFT * sizeof(float)); | ||||
|       FFT_MajorPeak = 1; | ||||
|       FFT_Magnitude = 0.001; | ||||
|     } | ||||
| @@ -1879,57 +1885,59 @@ class AudioReactive : public Usermod { | ||||
|     } | ||||
|  | ||||
|  | ||||
|     void appendConfigData() override | ||||
|     void appendConfigData(Print& uiScript) override | ||||
|     { | ||||
| #ifdef ARDUINO_ARCH_ESP32    | ||||
|       oappend(SET_F("dd=addDropdown('AudioReactive','digitalmic:type');")); | ||||
|       uiScript.print(F("ux='AudioReactive';"));         // ux = shortcut for Audioreactive - fingers crossed that "ux" isn't already used as JS var, html post parameter or css style | ||||
| #ifdef ARDUINO_ARCH_ESP32 | ||||
|       uiScript.print(F("uxp=ux+':digitalmic:pin[]';")); // uxp = shortcut for AudioReactive:digitalmic:pin[] | ||||
|       uiScript.print(F("dd=addDropdown(ux,'digitalmic:type');")); | ||||
|     #if  !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) | ||||
|       oappend(SET_F("addOption(dd,'Generic Analog',0);")); | ||||
|       uiScript.print(F("addOption(dd,'Generic Analog',0);")); | ||||
|     #endif | ||||
|       oappend(SET_F("addOption(dd,'Generic I2S',1);")); | ||||
|       oappend(SET_F("addOption(dd,'ES7243',2);")); | ||||
|       oappend(SET_F("addOption(dd,'SPH0654',3);")); | ||||
|       oappend(SET_F("addOption(dd,'Generic I2S with Mclk',4);")); | ||||
|       uiScript.print(F("addOption(dd,'Generic I2S',1);")); | ||||
|       uiScript.print(F("addOption(dd,'ES7243',2);")); | ||||
|       uiScript.print(F("addOption(dd,'SPH0654',3);")); | ||||
|       uiScript.print(F("addOption(dd,'Generic I2S with Mclk',4);")); | ||||
|     #if  !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) | ||||
|       oappend(SET_F("addOption(dd,'Generic I2S PDM',5);")); | ||||
|       uiScript.print(F("addOption(dd,'Generic I2S PDM',5);")); | ||||
|     #endif | ||||
|     oappend(SET_F("addOption(dd,'ES8388',6);")); | ||||
|     uiScript.print(F("addOption(dd,'ES8388',6);")); | ||||
|      | ||||
|       oappend(SET_F("dd=addDropdown('AudioReactive','config:AGC');")); | ||||
|       oappend(SET_F("addOption(dd,'Off',0);")); | ||||
|       oappend(SET_F("addOption(dd,'Normal',1);")); | ||||
|       oappend(SET_F("addOption(dd,'Vivid',2);")); | ||||
|       oappend(SET_F("addOption(dd,'Lazy',3);")); | ||||
|       uiScript.print(F("dd=addDropdown(ux,'config:AGC');")); | ||||
|       uiScript.print(F("addOption(dd,'Off',0);")); | ||||
|       uiScript.print(F("addOption(dd,'Normal',1);")); | ||||
|       uiScript.print(F("addOption(dd,'Vivid',2);")); | ||||
|       uiScript.print(F("addOption(dd,'Lazy',3);")); | ||||
|  | ||||
|       oappend(SET_F("dd=addDropdown('AudioReactive','dynamics:limiter');")); | ||||
|       oappend(SET_F("addOption(dd,'Off',0);")); | ||||
|       oappend(SET_F("addOption(dd,'On',1);")); | ||||
|       oappend(SET_F("addInfo('AudioReactive:dynamics:limiter',0,' On ');"));  // 0 is field type, 1 is actual field | ||||
|       oappend(SET_F("addInfo('AudioReactive:dynamics:rise',1,'ms <i>(♪ effects only)</i>');")); | ||||
|       oappend(SET_F("addInfo('AudioReactive:dynamics:fall',1,'ms <i>(♪ effects only)</i>');")); | ||||
|       uiScript.print(F("dd=addDropdown(ux,'dynamics:limiter');")); | ||||
|       uiScript.print(F("addOption(dd,'Off',0);")); | ||||
|       uiScript.print(F("addOption(dd,'On',1);")); | ||||
|       uiScript.print(F("addInfo(ux+':dynamics:limiter',0,' On ');"));  // 0 is field type, 1 is actual field | ||||
|       uiScript.print(F("addInfo(ux+':dynamics:rise',1,'ms <i>(♪ effects only)</i>');")); | ||||
|       uiScript.print(F("addInfo(ux+':dynamics:fall',1,'ms <i>(♪ effects only)</i>');")); | ||||
|  | ||||
|       oappend(SET_F("dd=addDropdown('AudioReactive','frequency:scale');")); | ||||
|       oappend(SET_F("addOption(dd,'None',0);")); | ||||
|       oappend(SET_F("addOption(dd,'Linear (Amplitude)',2);")); | ||||
|       oappend(SET_F("addOption(dd,'Square Root (Energy)',3);")); | ||||
|       oappend(SET_F("addOption(dd,'Logarithmic (Loudness)',1);")); | ||||
|       uiScript.print(F("dd=addDropdown(ux,'frequency:scale');")); | ||||
|       uiScript.print(F("addOption(dd,'None',0);")); | ||||
|       uiScript.print(F("addOption(dd,'Linear (Amplitude)',2);")); | ||||
|       uiScript.print(F("addOption(dd,'Square Root (Energy)',3);")); | ||||
|       uiScript.print(F("addOption(dd,'Logarithmic (Loudness)',1);")); | ||||
| #endif | ||||
|  | ||||
|       oappend(SET_F("dd=addDropdown('AudioReactive','sync:mode');")); | ||||
|       oappend(SET_F("addOption(dd,'Off',0);")); | ||||
|       uiScript.print(F("dd=addDropdown(ux,'sync:mode');")); | ||||
|       uiScript.print(F("addOption(dd,'Off',0);")); | ||||
| #ifdef ARDUINO_ARCH_ESP32 | ||||
|       oappend(SET_F("addOption(dd,'Send',1);")); | ||||
|       uiScript.print(F("addOption(dd,'Send',1);")); | ||||
| #endif | ||||
|       oappend(SET_F("addOption(dd,'Receive',2);")); | ||||
|       uiScript.print(F("addOption(dd,'Receive',2);")); | ||||
| #ifdef ARDUINO_ARCH_ESP32 | ||||
|       oappend(SET_F("addInfo('AudioReactive:digitalmic:type',1,'<i>requires reboot!</i>');"));  // 0 is field type, 1 is actual field | ||||
|       oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',0,'<i>sd/data/dout</i>','I2S SD');")); | ||||
|       oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',1,'<i>ws/clk/lrck</i>','I2S WS');")); | ||||
|       oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',2,'<i>sck/bclk</i>','I2S SCK');")); | ||||
|       uiScript.print(F("addInfo(ux+':digitalmic:type',1,'<i>requires reboot!</i>');"));  // 0 is field type, 1 is actual field | ||||
|       uiScript.print(F("addInfo(uxp,0,'<i>sd/data/dout</i>','I2S SD');")); | ||||
|       uiScript.print(F("addInfo(uxp,1,'<i>ws/clk/lrck</i>','I2S WS');")); | ||||
|       uiScript.print(F("addInfo(uxp,2,'<i>sck/bclk</i>','I2S SCK');")); | ||||
|       #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) | ||||
|         oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',3,'<i>only use -1, 0, 1 or 3</i>','I2S MCLK');")); | ||||
|         uiScript.print(F("addInfo(uxp,3,'<i>only use -1, 0, 1 or 3</i>','I2S MCLK');")); | ||||
|       #else | ||||
|         oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',3,'<i>master clock</i>','I2S MCLK');")); | ||||
|         uiScript.print(F("addInfo(uxp,3,'<i>master clock</i>','I2S MCLK');")); | ||||
|       #endif | ||||
| #endif | ||||
|     } | ||||
|   | ||||
| @@ -30,7 +30,7 @@ There are however plans to create a lightweight audioreactive for the 8266, with | ||||
| ### using latest _arduinoFFT_ library version 2.x | ||||
| The latest arduinoFFT release version should be used for audioreactive. | ||||
|  | ||||
| * `build_flags` = `-D USERMOD_AUDIOREACTIVE` | ||||
| * `build_flags` = `-D USERMOD_AUDIOREACTIVE -D sqrt_internal=sqrtf` | ||||
| * `lib_deps`= `kosme/arduinoFFT @ 2.0.1` | ||||
|  | ||||
| ## Configuration | ||||
|   | ||||
| @@ -305,14 +305,14 @@ class BobLightUsermod : public Usermod { | ||||
|     } | ||||
|  | ||||
|     void appendConfigData() override { | ||||
|       //oappend(SET_F("dd=addDropdown('usermod','selectfield');")); | ||||
|       //oappend(SET_F("addOption(dd,'1st value',0);")); | ||||
|       //oappend(SET_F("addOption(dd,'2nd value',1);")); | ||||
|       oappend(SET_F("addInfo('BobLight:top',1,'LEDs');"));                // 0 is field type, 1 is actual field | ||||
|       oappend(SET_F("addInfo('BobLight:bottom',1,'LEDs');"));             // 0 is field type, 1 is actual field | ||||
|       oappend(SET_F("addInfo('BobLight:left',1,'LEDs');"));               // 0 is field type, 1 is actual field | ||||
|       oappend(SET_F("addInfo('BobLight:right',1,'LEDs');"));              // 0 is field type, 1 is actual field | ||||
|       oappend(SET_F("addInfo('BobLight:pct',1,'Depth of scan [%]');"));   // 0 is field type, 1 is actual field | ||||
|       //oappend(F("dd=addDropdown('usermod','selectfield');")); | ||||
|       //oappend(F("addOption(dd,'1st value',0);")); | ||||
|       //oappend(F("addOption(dd,'2nd value',1);")); | ||||
|       oappend(F("addInfo('BobLight:top',1,'LEDs');"));                // 0 is field type, 1 is actual field | ||||
|       oappend(F("addInfo('BobLight:bottom',1,'LEDs');"));             // 0 is field type, 1 is actual field | ||||
|       oappend(F("addInfo('BobLight:left',1,'LEDs');"));               // 0 is field type, 1 is actual field | ||||
|       oappend(F("addInfo('BobLight:right',1,'LEDs');"));              // 0 is field type, 1 is actual field | ||||
|       oappend(F("addInfo('BobLight:pct',1,'Depth of scan [%]');"));   // 0 is field type, 1 is actual field | ||||
|     } | ||||
|  | ||||
|     void addToConfig(JsonObject& root) override { | ||||
|   | ||||
| @@ -264,7 +264,7 @@ void MultiRelay::handleOffTimer() { | ||||
| void MultiRelay::InitHtmlAPIHandle() {  // https://github.com/me-no-dev/ESPAsyncWebServer | ||||
|   DEBUG_PRINTLN(F("Relays: Initialize HTML API")); | ||||
|  | ||||
|   server.on(SET_F("/relays"), HTTP_GET, [this](AsyncWebServerRequest *request) { | ||||
|   server.on(F("/relays"), HTTP_GET, [this](AsyncWebServerRequest *request) { | ||||
|     DEBUG_PRINTLN(F("Relays: HTML API")); | ||||
|     String janswer; | ||||
|     String error = ""; | ||||
| @@ -765,10 +765,10 @@ void MultiRelay::addToConfig(JsonObject &root) { | ||||
| } | ||||
|  | ||||
| void MultiRelay::appendConfigData() { | ||||
|   oappend(SET_F("addInfo('MultiRelay:PCF8574-address',1,'<i>(not hex!)</i>');")); | ||||
|   oappend(SET_F("addInfo('MultiRelay:broadcast-sec',1,'(MQTT message)');")); | ||||
|   //oappend(SET_F("addInfo('MultiRelay:relay-0:pin',1,'(use -1 for PCF8574)');")); | ||||
|   oappend(SET_F("d.extra.push({'MultiRelay':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});")); | ||||
|   oappend(F("addInfo('MultiRelay:PCF8574-address',1,'<i>(not hex!)</i>');")); | ||||
|   oappend(F("addInfo('MultiRelay:broadcast-sec',1,'(MQTT message)');")); | ||||
|   //oappend(F("addInfo('MultiRelay:relay-0:pin',1,'(use -1 for PCF8574)');")); | ||||
|   oappend(F("d.extra.push({'MultiRelay':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});")); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -387,23 +387,23 @@ class PixelsDiceTrayUsermod : public Usermod { | ||||
|     // To work around this, add info text to the end of the preceding item. | ||||
|     // | ||||
|     // See addInfo in wled00/data/settings_um.htm for details on what this function does. | ||||
|     oappend(SET_F( | ||||
|     oappend(F( | ||||
|         "addInfo('DiceTray:ble_scan_duration',1,'<br><br><i>Set to \"*\" to " | ||||
|         "connect to any die.<br>Leave Blank to disable.</i><br><i " | ||||
|         "class=\"warn\">Saving will replace \"*\" with die names.</i>','');")); | ||||
| #if USING_TFT_DISPLAY | ||||
|     oappend(SET_F("ddr=addDropdown('DiceTray','rotation');")); | ||||
|     oappend(SET_F("addOption(ddr,'0 deg',0);")); | ||||
|     oappend(SET_F("addOption(ddr,'90 deg',1);")); | ||||
|     oappend(SET_F("addOption(ddr,'180 deg',2);")); | ||||
|     oappend(SET_F("addOption(ddr,'270 deg',3);")); | ||||
|     oappend(SET_F( | ||||
|     oappend(F("ddr=addDropdown('DiceTray','rotation');")); | ||||
|     oappend(F("addOption(ddr,'0 deg',0);")); | ||||
|     oappend(F("addOption(ddr,'90 deg',1);")); | ||||
|     oappend(F("addOption(ddr,'180 deg',2);")); | ||||
|     oappend(F("addOption(ddr,'270 deg',3);")); | ||||
|     oappend(F( | ||||
|         "addInfo('DiceTray:rotation',1,'<br><i class=\"warn\">DO NOT CHANGE " | ||||
|         "SPI PINS.</i><br><i class=\"warn\">CHANGES ARE IGNORED.</i>','');")); | ||||
|     oappend(SET_F("addInfo('TFT:pin[]',0,'','SPI CS');")); | ||||
|     oappend(SET_F("addInfo('TFT:pin[]',1,'','SPI DC');")); | ||||
|     oappend(SET_F("addInfo('TFT:pin[]',2,'','SPI RST');")); | ||||
|     oappend(SET_F("addInfo('TFT:pin[]',3,'','SPI BL');")); | ||||
|     oappend(F("addInfo('TFT:pin[]',0,'','SPI CS');")); | ||||
|     oappend(F("addInfo('TFT:pin[]',1,'','SPI DC');")); | ||||
|     oappend(F("addInfo('TFT:pin[]',2,'','SPI RST');")); | ||||
|     oappend(F("addInfo('TFT:pin[]',3,'','SPI BL');")); | ||||
| #endif | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -310,22 +310,22 @@ void ShtUsermod::onMqttConnect(bool sessionPresent) { | ||||
|  * @return void | ||||
|  */ | ||||
| void ShtUsermod::appendConfigData() { | ||||
|   oappend(SET_F("dd=addDropdown('")); | ||||
|   oappend(F("dd=addDropdown('")); | ||||
|   oappend(_name); | ||||
|   oappend(SET_F("','")); | ||||
|   oappend(F("','")); | ||||
|   oappend(_shtType); | ||||
|   oappend(SET_F("');")); | ||||
|   oappend(SET_F("addOption(dd,'SHT30',0);")); | ||||
|   oappend(SET_F("addOption(dd,'SHT31',1);")); | ||||
|   oappend(SET_F("addOption(dd,'SHT35',2);")); | ||||
|   oappend(SET_F("addOption(dd,'SHT85',3);")); | ||||
|   oappend(SET_F("dd=addDropdown('")); | ||||
|   oappend(F("');")); | ||||
|   oappend(F("addOption(dd,'SHT30',0);")); | ||||
|   oappend(F("addOption(dd,'SHT31',1);")); | ||||
|   oappend(F("addOption(dd,'SHT35',2);")); | ||||
|   oappend(F("addOption(dd,'SHT85',3);")); | ||||
|   oappend(F("dd=addDropdown('")); | ||||
|   oappend(_name); | ||||
|   oappend(SET_F("','")); | ||||
|   oappend(F("','")); | ||||
|   oappend(_unitOfTemp); | ||||
|   oappend(SET_F("');")); | ||||
|   oappend(SET_F("addOption(dd,'Celsius',0);")); | ||||
|   oappend(SET_F("addOption(dd,'Fahrenheit',1);")); | ||||
|   oappend(F("');")); | ||||
|   oappend(F("addOption(dd,'Celsius',0);")); | ||||
|   oappend(F("addOption(dd,'Fahrenheit',1);")); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -96,7 +96,7 @@ void setup() { | ||||
|     jsonTransitionOnce = true; | ||||
|     strip.setTransition(0); //no transition | ||||
|     effectCurrent = FX_MODE_COLOR_WIPE; | ||||
|     resetTimebase(); //make sure wipe starts from beginning | ||||
|     strip.resetTimebase(); //make sure wipe starts from beginning | ||||
|  | ||||
|     //set wipe direction | ||||
|     Segment& seg = strip.getSegment(0); | ||||
|   | ||||
| @@ -86,7 +86,7 @@ void startWipe() | ||||
|   bri = briLast; //turn on | ||||
|   transitionDelayTemp = 0; //no transition | ||||
|   effectCurrent = FX_MODE_COLOR_WIPE; | ||||
|   resetTimebase(); //make sure wipe starts from beginning | ||||
|   strip.resetTimebase(); //make sure wipe starts from beginning | ||||
|  | ||||
|   //set wipe direction | ||||
|   Segment& seg = strip.getSegment(0); | ||||
|   | ||||
| @@ -7,11 +7,12 @@ 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 | ||||
|     -D USERMOD_FOUR_LINE_DISPLAY | ||||
|     -D FLD_TYPE=SH1106 | ||||
|     -D I2CSCLPIN=27 | ||||
|     -D I2CSDAPIN=26 | ||||
| 
 | ||||
| lib_deps = | ||||
|     ${esp32.lib_deps} | ||||
|     U8g2@~2.34.4 | ||||
|     Wire | ||||
| 
 | ||||
| @@ -1,16 +1,8 @@ | ||||
| # I2C/SPI 4 Line Display Usermod ALT | ||||
|  | ||||
| Thank you to the authors of the original version of these usermods. It would not have been possible without them! | ||||
| "usermod_v2_four_line_display" | ||||
| "usermod_v2_rotary_encoder_ui" | ||||
| This usermod could be used in compination with `usermod_v2_rotary_encoder_ui_ALT`. | ||||
|  | ||||
| The core of these usermods are a copy of the originals. The main changes are to the FourLineDisplay usermod. | ||||
| The display usermod UI has been completely changed. | ||||
|  | ||||
|  | ||||
| The changes made to the RotaryEncoder usermod were made to support the new UI in the display usermod. | ||||
| Without the display, it functions identical to the original. | ||||
| The original "usermod_v2_auto_save" will not work with the display just yet. | ||||
| ## Functionalities | ||||
|  | ||||
| Press the encoder to cycle through the options: | ||||
| * Brightness | ||||
| @@ -18,26 +10,18 @@ Press the encoder to cycle through the options: | ||||
| * Intensity | ||||
| * Palette | ||||
| * Effect | ||||
| * Main Color (only if display is used) | ||||
| * Saturation (only if display is used) | ||||
| * Main Color | ||||
| * Saturation | ||||
|  | ||||
| Press and hold the encoder to display Network Info. If AP is active, it will display AP, SSID and password | ||||
| Press and hold the encoder to display Network Info. If AP is active, it will display the AP, SSID and Password | ||||
|  | ||||
| Also shows if the timer is enabled | ||||
| Also shows if the timer is enabled. | ||||
|  | ||||
| [See the pair of usermods in action](https://www.youtube.com/watch?v=ulZnBt9z3TI) | ||||
|  | ||||
| ## Installation | ||||
|  | ||||
| Please refer to the original `usermod_v2_rotary_encoder_ui` readme for the main instructions. | ||||
|  | ||||
| Copy the example `platformio_override.sample.ini` from the usermod_v2_rotary_encoder_ui_ALT folder to the root directory of your particular build and rename it to `platformio_override.ini`. | ||||
|  | ||||
| This file should be placed in the same directory as `platformio.ini`. | ||||
|  | ||||
| Then, to activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE SENSITIVE) to the `usermods_list.cpp` file, | ||||
|                                         or add `-D USE_ALT_DISPlAY` to the original `platformio_override.ini.sample` file | ||||
|  | ||||
| Copy the example `platformio_override.sample.ini` to the root directory of your particular build. | ||||
|  | ||||
| ## Configuration | ||||
|  | ||||
|   | ||||
| @@ -1202,21 +1202,21 @@ void FourLineDisplayUsermod::onUpdateBegin(bool init) { | ||||
| //} | ||||
|  | ||||
| void FourLineDisplayUsermod::appendConfigData() { | ||||
|   oappend(SET_F("dd=addDropdown('4LineDisplay','type');")); | ||||
|   oappend(SET_F("addOption(dd,'None',0);")); | ||||
|   oappend(SET_F("addOption(dd,'SSD1306',1);")); | ||||
|   oappend(SET_F("addOption(dd,'SH1106',2);")); | ||||
|   oappend(SET_F("addOption(dd,'SSD1306 128x64',3);")); | ||||
|   oappend(SET_F("addOption(dd,'SSD1305',4);")); | ||||
|   oappend(SET_F("addOption(dd,'SSD1305 128x64',5);")); | ||||
|   oappend(SET_F("addOption(dd,'SSD1309 128x64',9);")); | ||||
|   oappend(SET_F("addOption(dd,'SSD1306 SPI',6);")); | ||||
|   oappend(SET_F("addOption(dd,'SSD1306 SPI 128x64',7);")); | ||||
|   oappend(SET_F("addOption(dd,'SSD1309 SPI 128x64',8);")); | ||||
|   oappend(SET_F("addInfo('4LineDisplay:type',1,'<br><i class=\"warn\">Change may require reboot</i>','');")); | ||||
|   oappend(SET_F("addInfo('4LineDisplay:pin[]',0,'','SPI CS');")); | ||||
|   oappend(SET_F("addInfo('4LineDisplay:pin[]',1,'','SPI DC');")); | ||||
|   oappend(SET_F("addInfo('4LineDisplay:pin[]',2,'','SPI RST');")); | ||||
|   oappend(F("dd=addDropdown('4LineDisplay','type');")); | ||||
|   oappend(F("addOption(dd,'None',0);")); | ||||
|   oappend(F("addOption(dd,'SSD1306',1);")); | ||||
|   oappend(F("addOption(dd,'SH1106',2);")); | ||||
|   oappend(F("addOption(dd,'SSD1306 128x64',3);")); | ||||
|   oappend(F("addOption(dd,'SSD1305',4);")); | ||||
|   oappend(F("addOption(dd,'SSD1305 128x64',5);")); | ||||
|   oappend(F("addOption(dd,'SSD1309 128x64',9);")); | ||||
|   oappend(F("addOption(dd,'SSD1306 SPI',6);")); | ||||
|   oappend(F("addOption(dd,'SSD1306 SPI 128x64',7);")); | ||||
|   oappend(F("addOption(dd,'SSD1309 SPI 128x64',8);")); | ||||
|   oappend(F("addInfo('4LineDisplay:type',1,'<br><i class=\"warn\">Change may require reboot</i>','');")); | ||||
|   oappend(F("addInfo('4LineDisplay:pin[]',0,'','SPI CS');")); | ||||
|   oappend(F("addInfo('4LineDisplay:pin[]',1,'','SPI DC');")); | ||||
|   oappend(F("addInfo('4LineDisplay:pin[]',2,'','SPI RST');")); | ||||
| } | ||||
|  | ||||
| /* | ||||
|   | ||||
| @@ -0,0 +1,14 @@ | ||||
| [platformio] | ||||
| default_envs = esp32dev | ||||
|  | ||||
| [env:esp32dev] | ||||
| board = esp32dev | ||||
| platform = ${esp32.platform} | ||||
| build_unflags = ${common.build_unflags} | ||||
| build_flags = | ||||
|     ${common.build_flags_esp32} | ||||
|     -D USERMOD_ROTARY_ENCODER_UI | ||||
|     -D USERMOD_ROTARY_ENCODER_GPIO=INPUT | ||||
|     -D ENCODER_DT_PIN=21 | ||||
|     -D ENCODER_CLK_PIN=23 | ||||
|     -D ENCODER_SW_PIN=0 | ||||
| @@ -1,16 +1,8 @@ | ||||
| # Rotary Encoder UI Usermod ALT | ||||
|  | ||||
| Thank you to the authors of the original version of these usermods. It would not have been possible without them! | ||||
| "usermod_v2_four_line_display" | ||||
| "usermod_v2_rotary_encoder_ui" | ||||
| This usermod supports the UI of the `usermod_v2_rotary_encoder_ui_ALT`. | ||||
|  | ||||
| The core of these usermods are a copy of the originals. The main changes are to the FourLineDisplay usermod. | ||||
| The display usermod UI has been completely changed. | ||||
|  | ||||
|  | ||||
| The changes made to the RotaryEncoder usermod were made to support the new UI in the display usermod. | ||||
| Without the display, it functions identical to the original. | ||||
| The original "usermod_v2_auto_save" will not work with the display just yet. | ||||
| ## Functionalities | ||||
|  | ||||
| Press the encoder to cycle through the options: | ||||
| * Brightness | ||||
| @@ -21,8 +13,7 @@ Press the encoder to cycle through the options: | ||||
| * Main Color (only if display is used) | ||||
| * Saturation (only if display is used) | ||||
|  | ||||
| Press and hold the encoder to display Network Info | ||||
|     if AP is active, it will display the AP, SSID and Password | ||||
| Press and hold the encoder to display Network Info. If AP is active, it will display the AP, SSID and Password | ||||
|  | ||||
| Also shows if the timer is enabled. | ||||
|  | ||||
| @@ -30,9 +21,7 @@ Also shows if the timer is enabled. | ||||
|  | ||||
| ## Installation | ||||
|  | ||||
| Copy the example `platformio_override.sample.ini` to the root directory of your particular build and rename it to `platformio_override.ini`. | ||||
|  | ||||
| To activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE SENSITIVE) to the `usermods_list.cpp` file, or add `-D USE_ALT_DISPlAY` to your `platformio_override.ini` file | ||||
| Copy the example `platformio_override.sample.ini` to the root directory of your particular build. | ||||
|  | ||||
| ### Define Your Options | ||||
|  | ||||
| @@ -40,7 +29,6 @@ To activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE | ||||
| * `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 | ||||
| @@ -50,7 +38,7 @@ To activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE | ||||
|  | ||||
| ### PlatformIO requirements | ||||
|  | ||||
| Note: the Four Line Display usermod requires the libraries `U8g2` and `Wire`. | ||||
| No special requirements. | ||||
|  | ||||
| ## Change Log | ||||
|  | ||||
|   | ||||
| @@ -1090,8 +1090,8 @@ void RotaryEncoderUIUsermod::addToConfig(JsonObject &root) { | ||||
| } | ||||
|  | ||||
| void RotaryEncoderUIUsermod::appendConfigData() { | ||||
|   oappend(SET_F("addInfo('Rotary-Encoder:PCF8574-address',1,'<i>(not hex!)</i>');")); | ||||
|   oappend(SET_F("d.extra.push({'Rotary-Encoder':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});")); | ||||
|   oappend(F("addInfo('Rotary-Encoder:PCF8574-address',1,'<i>(not hex!)</i>');")); | ||||
|   oappend(F("d.extra.push({'Rotary-Encoder':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});")); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -433,8 +433,8 @@ class WordClockUsermod : public Usermod | ||||
|  | ||||
|     void appendConfigData() | ||||
|     { | ||||
|       oappend(SET_F("addInfo('WordClockUsermod:ledOffset', 1, 'Number of LEDs before the letters');")); | ||||
|       oappend(SET_F("addInfo('WordClockUsermod:Norddeutsch', 1, 'Viertel vor instead of Dreiviertel');")); | ||||
|       oappend(F("addInfo('WordClockUsermod:ledOffset', 1, 'Number of LEDs before the letters');")); | ||||
|       oappend(F("addInfo('WordClockUsermod:Norddeutsch', 1, 'Viertel vor instead of Dreiviertel');")); | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|   | ||||
| @@ -54,13 +54,13 @@ class WireguardUsermod : public Usermod { | ||||
|     } | ||||
|  | ||||
|     void appendConfigData() { | ||||
|         oappend(SET_F("addInfo('WireGuard:host',1,'Server Hostname');"));           // 0 is field type, 1 is actual field | ||||
|         oappend(SET_F("addInfo('WireGuard:port',1,'Server Port');"));               // 0 is field type, 1 is actual field | ||||
|         oappend(SET_F("addInfo('WireGuard:ip',1,'Device IP');"));                   // 0 is field type, 1 is actual field | ||||
|         oappend(SET_F("addInfo('WireGuard:psk',1,'Pre Shared Key (optional)');"));  // 0 is field type, 1 is actual field | ||||
|         oappend(SET_F("addInfo('WireGuard:pem',1,'Private Key');"));                // 0 is field type, 1 is actual field | ||||
|         oappend(SET_F("addInfo('WireGuard:pub',1,'Public Key');"));                 // 0 is field type, 1 is actual field | ||||
|         oappend(SET_F("addInfo('WireGuard:tz',1,'POSIX timezone string');"));       // 0 is field type, 1 is actual field | ||||
|         oappend(F("addInfo('WireGuard:host',1,'Server Hostname');"));           // 0 is field type, 1 is actual field | ||||
|         oappend(F("addInfo('WireGuard:port',1,'Server Port');"));               // 0 is field type, 1 is actual field | ||||
|         oappend(F("addInfo('WireGuard:ip',1,'Device IP');"));                   // 0 is field type, 1 is actual field | ||||
|         oappend(F("addInfo('WireGuard:psk',1,'Pre Shared Key (optional)');"));  // 0 is field type, 1 is actual field | ||||
|         oappend(F("addInfo('WireGuard:pem',1,'Private Key');"));                // 0 is field type, 1 is actual field | ||||
|         oappend(F("addInfo('WireGuard:pub',1,'Public Key');"));                 // 0 is field type, 1 is actual field | ||||
|         oappend(F("addInfo('WireGuard:tz',1,'POSIX timezone string');"));       // 0 is field type, 1 is actual field | ||||
|     } | ||||
|  | ||||
|     void addToConfig(JsonObject& root) { | ||||
|   | ||||
							
								
								
									
										323
									
								
								wled00/FX.cpp
									
									
									
									
									
								
							
							
						
						
									
										323
									
								
								wled00/FX.cpp
									
									
									
									
									
								
							| @@ -2,24 +2,10 @@ | ||||
|   WS2812FX.cpp contains all effect methods | ||||
|   Harm Aldick - 2016 | ||||
|   www.aldick.org | ||||
|   LICENSE | ||||
|   The MIT License (MIT) | ||||
|  | ||||
|   Copyright (c) 2016  Harm Aldick | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   in the Software without restriction, including without limitation the rights | ||||
|   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|   copies of the Software, and to permit persons to whom the Software is | ||||
|   furnished to do so, subject to the following conditions: | ||||
|   The above copyright notice and this permission notice shall be included in | ||||
|   all copies or substantial portions of the Software. | ||||
|   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|   THE SOFTWARE. | ||||
|   Licensed under the EUPL v. 1.2 or later | ||||
|   Adapted from code originally licensed under the MIT license | ||||
|  | ||||
|   Modified heavily for WLED | ||||
| */ | ||||
| @@ -39,7 +25,7 @@ | ||||
| // effect utility functions | ||||
| uint8_t sin_gap(uint16_t in) { | ||||
|   if (in & 0x100) return 0; | ||||
|   return sin8(in + 192); // correct phase shift of sine so that it starts and stops at 0 | ||||
|   return sin8_t(in + 192); // correct phase shift of sine so that it starts and stops at 0 | ||||
| } | ||||
|  | ||||
| uint16_t triwave16(uint16_t in) { | ||||
| @@ -349,7 +335,7 @@ uint16_t mode_breath(void) { | ||||
|   counter = (counter >> 2) + (counter >> 4); //0-16384 + 0-2048 | ||||
|   if (counter < 16384) { | ||||
|     if (counter > 8192) counter = 8192 - (counter - 8192); | ||||
|     var = sin16(counter) / 103; //close to parabolic in range 0-8192, max val. 23170 | ||||
|     var = sin16_t(counter) / 103; //close to parabolic in range 0-8192, max val. 23170 | ||||
|   } | ||||
|  | ||||
|   unsigned lum = 30 + var; | ||||
| @@ -531,7 +517,7 @@ static uint16_t running_base(bool saw, bool dual=false) { | ||||
|       } | ||||
|       a = 255 - a; | ||||
|     } | ||||
|     uint8_t s = dual ? sin_gap(a) : sin8(a); | ||||
|     uint8_t s = dual ? sin_gap(a) : sin8_t(a); | ||||
|     uint32_t ca = color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 0), s); | ||||
|     if (dual) { | ||||
|       unsigned b = (SEGLEN-1-i)*x_scale - counter; | ||||
| @@ -1893,16 +1879,16 @@ uint16_t mode_pride_2015(void) { | ||||
|   unsigned sPseudotime = SEGENV.step; | ||||
|   unsigned sHue16 = SEGENV.aux0; | ||||
|  | ||||
|   uint8_t sat8 = beatsin88( 87, 220, 250); | ||||
|   uint8_t brightdepth = beatsin88( 341, 96, 224); | ||||
|   unsigned brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256)); | ||||
|   unsigned msmultiplier = beatsin88(147, 23, 60); | ||||
|   uint8_t sat8 = beatsin88_t( 87, 220, 250); | ||||
|   uint8_t brightdepth = beatsin88_t( 341, 96, 224); | ||||
|   unsigned brightnessthetainc16 = beatsin88_t( 203, (25 * 256), (40 * 256)); | ||||
|   unsigned msmultiplier = beatsin88_t(147, 23, 60); | ||||
|  | ||||
|   unsigned hue16 = sHue16;//gHue * 256; | ||||
|   unsigned hueinc16 = beatsin88(113, 1, 3000); | ||||
|   unsigned hueinc16 = beatsin88_t(113, 1, 3000); | ||||
|  | ||||
|   sPseudotime += duration * msmultiplier; | ||||
|   sHue16 += duration * beatsin88( 400, 5,9); | ||||
|   sHue16 += duration * beatsin88_t( 400, 5,9); | ||||
|   unsigned brightnesstheta16 = sPseudotime; | ||||
|  | ||||
|   for (unsigned i = 0 ; i < SEGLEN; i++) { | ||||
| @@ -1910,7 +1896,7 @@ uint16_t mode_pride_2015(void) { | ||||
|     uint8_t hue8 = hue16 >> 8; | ||||
|  | ||||
|     brightnesstheta16  += brightnessthetainc16; | ||||
|     unsigned b16 = sin16( brightnesstheta16  ) + 32768; | ||||
|     unsigned b16 = sin16_t( brightnesstheta16  ) + 32768; | ||||
|  | ||||
|     unsigned bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536; | ||||
|     uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536; | ||||
| @@ -1935,7 +1921,7 @@ uint16_t mode_juggle(void) { | ||||
|   CRGB fastled_col; | ||||
|   byte dothue = 0; | ||||
|   for (int i = 0; i < 8; i++) { | ||||
|     int index = 0 + beatsin88((16 + SEGMENT.speed)*(i + 7), 0, SEGLEN -1); | ||||
|     int index = 0 + beatsin88_t((16 + SEGMENT.speed)*(i + 7), 0, SEGLEN -1); | ||||
|     fastled_col = CRGB(SEGMENT.getPixelColor(index)); | ||||
|     fastled_col |= (SEGMENT.palette==0)?CHSV(dothue, 220, 255):ColorFromPalette(SEGPALETTE, dothue, 255); | ||||
|     SEGMENT.setPixelColor(index, fastled_col); | ||||
| @@ -1956,8 +1942,8 @@ uint16_t mode_palette() { | ||||
|   constexpr mathType maxAngle                = 0x8000; | ||||
|   constexpr mathType staticRotationScale     = 256; | ||||
|   constexpr mathType animatedRotationScale   = 1; | ||||
|   constexpr int16_t (*sinFunction)(uint16_t) = &sin16; | ||||
|   constexpr int16_t (*cosFunction)(uint16_t) = &cos16; | ||||
|   constexpr int16_t (*sinFunction)(uint16_t) = &sin16_t; | ||||
|   constexpr int16_t (*cosFunction)(uint16_t) = &cos16_t; | ||||
| #else | ||||
|   using mathType = float; | ||||
|   using wideMathType = float; | ||||
| @@ -1980,7 +1966,7 @@ uint16_t mode_palette() { | ||||
|   const bool inputAnimateRotation = SEGMENT.check2; | ||||
|   const bool inputAssumeSquare    = SEGMENT.check3; | ||||
|  | ||||
|   const angleType theta = (!inputAnimateRotation) ? (inputRotation * maxAngle / staticRotationScale) : (((strip.now * ((inputRotation >> 4) +1)) & 0xFFFF) * animatedRotationScale); | ||||
|   const angleType theta = (!inputAnimateRotation) ? ((inputRotation + 128) * maxAngle / staticRotationScale) : (((strip.now * ((inputRotation >> 4) +1)) & 0xFFFF) * animatedRotationScale); | ||||
|   const mathType sinTheta = sinFunction(theta); | ||||
|   const mathType cosTheta = cosFunction(theta); | ||||
|  | ||||
| @@ -1999,7 +1985,7 @@ uint16_t mode_palette() { | ||||
|   // So the rectangle needs to have exactly the right size. That size depends on the rotation. | ||||
|   // This scale computation here only considers one dimension. You can think of it like the rectangle is always scaled so that | ||||
|   // the left and right most points always match the left and right side of the display. | ||||
|   const mathType scale   = std::abs(sinTheta) + (std::abs(cosTheta) * maxYOut / maxXOut); | ||||
|   const mathType scale = std::abs(sinTheta) + (std::abs(cosTheta) * maxYOut / maxXOut); | ||||
|   // 2D simulation: | ||||
|   // If we are dealing with a 1D setup, we assume that each segment represents one line on a 2-dimensional display. | ||||
|   // The function is called once per segments, so we need to handle one line at a time. | ||||
| @@ -2030,8 +2016,8 @@ uint16_t mode_palette() { | ||||
|         colorIndex = ((inputSize - 112) * colorIndex) / 16; | ||||
|       } | ||||
|       // Finally, shift the palette a bit. | ||||
|       const int paletteOffset = (!inputAnimateShift) ? (inputShift-128) : (((strip.now * ((inputShift >> 3) +1)) & 0xFFFF) >> 8); | ||||
|       colorIndex += paletteOffset; | ||||
|       const int paletteOffset = (!inputAnimateShift) ? (inputShift) : (((strip.now * ((inputShift >> 3) +1)) & 0xFFFF) >> 8); | ||||
|       colorIndex -= paletteOffset; | ||||
|       const uint32_t color = SEGMENT.color_wheel((uint8_t)colorIndex); | ||||
|       if (isMatrix) { | ||||
|         SEGMENT.setPixelColorXY(x, y, color); | ||||
| @@ -2042,7 +2028,7 @@ uint16_t mode_palette() { | ||||
|   } | ||||
|   return FRAMETIME; | ||||
| } | ||||
| static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Shift,Size,Rotation,,,Animate Shift,Animate Rotation,Anamorphic;;!;12;c1=128,c2=128,c3=128,o1=1,o2=1,o3=0"; | ||||
| static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Shift,Size,Rotation,,,Animate Shift,Animate Rotation,Anamorphic;;!;12;ix=112,c1=0,o1=1,o2=0,o3=1"; | ||||
|  | ||||
|  | ||||
| // WLED limitation: Analog Clock overlay will NOT work when Fire2012 is active | ||||
| @@ -2141,15 +2127,15 @@ uint16_t mode_colorwaves() { | ||||
|   unsigned sPseudotime = SEGENV.step; | ||||
|   unsigned sHue16 = SEGENV.aux0; | ||||
|  | ||||
|   unsigned brightdepth = beatsin88(341, 96, 224); | ||||
|   unsigned brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256)); | ||||
|   unsigned msmultiplier = beatsin88(147, 23, 60); | ||||
|   unsigned brightdepth = beatsin88_t(341, 96, 224); | ||||
|   unsigned brightnessthetainc16 = beatsin88_t( 203, (25 * 256), (40 * 256)); | ||||
|   unsigned msmultiplier = beatsin88_t(147, 23, 60); | ||||
|  | ||||
|   unsigned hue16 = sHue16;//gHue * 256; | ||||
|   unsigned hueinc16 = beatsin88(113, 60, 300)*SEGMENT.intensity*10/255;  // Use the Intensity Slider for the hues | ||||
|   unsigned hueinc16 = beatsin88_t(113, 60, 300)*SEGMENT.intensity*10/255;  // Use the Intensity Slider for the hues | ||||
|  | ||||
|   sPseudotime += duration * msmultiplier; | ||||
|   sHue16 += duration * beatsin88(400, 5, 9); | ||||
|   sHue16 += duration * beatsin88_t(400, 5, 9); | ||||
|   unsigned brightnesstheta16 = sPseudotime; | ||||
|  | ||||
|   for (int i = 0 ; i < SEGLEN; i++) { | ||||
| @@ -2163,7 +2149,7 @@ uint16_t mode_colorwaves() { | ||||
|     } | ||||
|  | ||||
|     brightnesstheta16  += brightnessthetainc16; | ||||
|     unsigned b16 = sin16(brightnesstheta16) + 32768; | ||||
|     unsigned b16 = sin16_t(brightnesstheta16) + 32768; | ||||
|  | ||||
|     unsigned bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536; | ||||
|     uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536; | ||||
| @@ -2182,7 +2168,7 @@ static const char _data_FX_MODE_COLORWAVES[] PROGMEM = "Colorwaves@!,Hue;!;!"; | ||||
| // colored stripes pulsing at a defined Beats-Per-Minute (BPM) | ||||
| uint16_t mode_bpm() { | ||||
|   uint32_t stp = (strip.now / 20) & 0xFF; | ||||
|   uint8_t beat = beatsin8(SEGMENT.speed, 64, 255); | ||||
|   uint8_t beat = beatsin8_t(SEGMENT.speed, 64, 255); | ||||
|   for (int i = 0; i < SEGLEN; i++) { | ||||
|     SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(stp + (i * 2), false, PALETTE_SOLID_WRAP, 0, beat - stp + (i * 10))); | ||||
|   } | ||||
| @@ -2198,7 +2184,7 @@ uint16_t mode_fillnoise8() { | ||||
|     unsigned index = inoise8(i * SEGLEN, SEGENV.step + i * SEGLEN); | ||||
|     SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0)); | ||||
|   } | ||||
|   SEGENV.step += beatsin8(SEGMENT.speed, 1, 6); //10,1,4 | ||||
|   SEGENV.step += beatsin8_t(SEGMENT.speed, 1, 6); //10,1,4 | ||||
|  | ||||
|   return FRAMETIME; | ||||
| } | ||||
| @@ -2210,13 +2196,13 @@ uint16_t mode_noise16_1() { | ||||
|   SEGENV.step += (1 + SEGMENT.speed/16); | ||||
|  | ||||
|   for (int i = 0; i < SEGLEN; i++) { | ||||
|     unsigned shift_x = beatsin8(11);                          // the x position of the noise field swings @ 17 bpm | ||||
|     unsigned shift_x = beatsin8_t(11);                          // the x position of the noise field swings @ 17 bpm | ||||
|     unsigned shift_y = SEGENV.step/42;                        // the y position becomes slowly incremented | ||||
|     unsigned real_x = (i + shift_x) * scale;                  // the x position of the noise field swings @ 17 bpm | ||||
|     unsigned real_y = (i + shift_y) * scale;                  // the y position becomes slowly incremented | ||||
|     uint32_t real_z = SEGENV.step;                            // the z position becomes quickly incremented | ||||
|     unsigned noise = inoise16(real_x, real_y, real_z) >> 8;   // get the noise data and scale it down | ||||
|     unsigned index = sin8(noise * 3);                         // map LED color based on noise data | ||||
|     unsigned index = sin8_t(noise * 3);                         // map LED color based on noise data | ||||
|  | ||||
|     SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0)); | ||||
|   } | ||||
| @@ -2234,7 +2220,7 @@ uint16_t mode_noise16_2() { | ||||
|     unsigned shift_x = SEGENV.step >> 6;                        // x as a function of time | ||||
|     uint32_t real_x = (i + shift_x) * scale;                    // calculate the coordinates within the noise field | ||||
|     unsigned noise = inoise16(real_x, 0, 4223) >> 8;            // get the noise data and scale it down | ||||
|     unsigned index = sin8(noise * 3);                           // map led color based on noise data | ||||
|     unsigned index = sin8_t(noise * 3);                           // map led color based on noise data | ||||
|  | ||||
|     SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0, noise)); | ||||
|   } | ||||
| @@ -2255,7 +2241,7 @@ uint16_t mode_noise16_3() { | ||||
|     uint32_t real_y = (i + shift_y) * scale;                  // based on the precalculated positions | ||||
|     uint32_t real_z = SEGENV.step*8; | ||||
|     unsigned noise = inoise16(real_x, real_y, real_z) >> 8;   // get the noise data and scale it down | ||||
|     unsigned index = sin8(noise * 3);                         // map led color based on noise data | ||||
|     unsigned index = sin8_t(noise * 3);                         // map led color based on noise data | ||||
|  | ||||
|     SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0, noise)); | ||||
|   } | ||||
| @@ -2335,13 +2321,13 @@ static const char _data_FX_MODE_COLORTWINKLE[] PROGMEM = "Colortwinkles@Fade spe | ||||
| //Calm effect, like a lake at night | ||||
| uint16_t mode_lake() { | ||||
|   unsigned sp = SEGMENT.speed/10; | ||||
|   int wave1 = beatsin8(sp +2, -64,64); | ||||
|   int wave2 = beatsin8(sp +1, -64,64); | ||||
|   int wave3 = beatsin8(sp +2,   0,80); | ||||
|   int wave1 = beatsin8_t(sp +2, -64,64); | ||||
|   int wave2 = beatsin8_t(sp +1, -64,64); | ||||
|   int wave3 = beatsin8_t(sp +2,   0,80); | ||||
|  | ||||
|   for (int i = 0; i < SEGLEN; i++) | ||||
|   { | ||||
|     int index = cos8((i*15)+ wave1)/2 + cubicwave8((i*23)+ wave2)/2; | ||||
|     int index = cos8_t((i*15)+ wave1)/2 + cubicwave8((i*23)+ wave2)/2; | ||||
|     uint8_t lum = (index > wave3) ? index - wave3 : 0; | ||||
|     SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, false, 0, lum)); | ||||
|   } | ||||
| @@ -2514,15 +2500,15 @@ static uint16_t ripple_base() { | ||||
|         propI /= 2; | ||||
|         unsigned cx = rippleorigin >> 8; | ||||
|         unsigned cy = rippleorigin & 0xFF; | ||||
|         unsigned mag = scale8(sin8((propF>>2)), amp); | ||||
|         unsigned mag = scale8(sin8_t((propF>>2)), amp); | ||||
|         if (propI > 0) SEGMENT.drawCircle(cx, cy, propI, color_blend(SEGMENT.getPixelColorXY(cx + propI, cy), col, mag), true); | ||||
|       } else | ||||
|       #endif | ||||
|       { | ||||
|         int left = rippleorigin - propI -1; | ||||
|         int right = rippleorigin + propI +3; | ||||
|         int right = rippleorigin + propI +2; | ||||
|         for (int v = 0; v < 4; v++) { | ||||
|           unsigned mag = scale8(cubicwave8((propF>>2)+(v-left)*64), amp); | ||||
|           unsigned mag = scale8(cubicwave8((propF>>2) + v * 64), amp); | ||||
|           SEGMENT.setPixelColor(left + v, color_blend(SEGMENT.getPixelColor(left + v), col, mag)); // TODO | ||||
|           SEGMENT.setPixelColor(right - v, color_blend(SEGMENT.getPixelColor(right - v), col, mag)); // TODO | ||||
|         } | ||||
| @@ -2581,7 +2567,7 @@ static CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat) | ||||
|   unsigned ticks = ms / SEGENV.aux0; | ||||
|   unsigned fastcycle8 = ticks; | ||||
|   unsigned slowcycle16 = (ticks >> 8) + salt; | ||||
|   slowcycle16 += sin8(slowcycle16); | ||||
|   slowcycle16 += sin8_t(slowcycle16); | ||||
|   slowcycle16 = (slowcycle16 * 2053) + 1384; | ||||
|   unsigned slowcycle8 = (slowcycle16 & 0xFF) + (slowcycle16 >> 8); | ||||
|  | ||||
| @@ -3152,7 +3138,7 @@ static const char _data_FX_MODE_ROLLINGBALLS[] PROGMEM = "Rolling Balls@!,# of b | ||||
| static uint16_t sinelon_base(bool dual, bool rainbow=false) { | ||||
|   if (SEGLEN == 1) return mode_static(); | ||||
|   SEGMENT.fade_out(SEGMENT.intensity); | ||||
|   unsigned pos = beatsin16(SEGMENT.speed/10,0,SEGLEN-1); | ||||
|   unsigned pos = beatsin16_t(SEGMENT.speed/10,0,SEGLEN-1); | ||||
|   if (SEGENV.call == 0) SEGENV.aux0 = pos; | ||||
|   uint32_t color1 = SEGMENT.color_from_palette(pos, true, false, 0); | ||||
|   uint32_t color2 = SEGCOLOR(2); | ||||
| @@ -3561,7 +3547,7 @@ uint16_t mode_exploding_fireworks(void) | ||||
|   if (segs <= (strip.getMaxSegments() /4)) maxData *= 2; //ESP8266: 1024 if <= 4 segs ESP32: 2560 if <= 8 segs | ||||
|   int maxSparks = maxData / sizeof(spark); //ESP8266: max. 21/42/85 sparks/seg, ESP32: max. 53/106/213 sparks/seg | ||||
|  | ||||
|   unsigned numSparks = min(2 + ((rows*cols) >> 1), maxSparks); | ||||
|   unsigned numSparks = min(5 + ((rows*cols) >> 1), maxSparks); | ||||
|   unsigned dataSize = sizeof(spark) * numSparks; | ||||
|   if (!SEGENV.allocateData(dataSize + sizeof(float))) return mode_static(); //allocation failed | ||||
|   float *dying_gravity = reinterpret_cast<float*>(SEGENV.data + dataSize); | ||||
| @@ -3616,7 +3602,8 @@ uint16_t mode_exploding_fireworks(void) | ||||
|      * Size is proportional to the height. | ||||
|      */ | ||||
|     unsigned nSparks = flare->pos + random8(4); | ||||
|     nSparks = constrain(nSparks, 4, numSparks); | ||||
|     nSparks = std::max(nSparks, 4U);  // This is not a standard constrain; numSparks is not guaranteed to be at least 4 | ||||
|     nSparks = std::min(nSparks, numSparks); | ||||
|  | ||||
|     // initialize sparks | ||||
|     if (SEGENV.aux0 == 2) { | ||||
| @@ -3868,13 +3855,13 @@ uint16_t mode_plasma(void) { | ||||
|   if (SEGENV.call == 0) { | ||||
|     SEGENV.aux0 = random8(0,2);  // add a bit of randomness | ||||
|   } | ||||
|   unsigned thisPhase = beatsin8(6+SEGENV.aux0,-64,64); | ||||
|   unsigned thatPhase = beatsin8(7+SEGENV.aux0,-64,64); | ||||
|   unsigned thisPhase = beatsin8_t(6+SEGENV.aux0,-64,64); | ||||
|   unsigned thatPhase = beatsin8_t(7+SEGENV.aux0,-64,64); | ||||
|  | ||||
|   for (unsigned i = 0; i < SEGLEN; i++) {   // For each of the LED's in the strand, set color &  brightness based on a wave as follows: | ||||
|     unsigned colorIndex = cubicwave8((i*(2+ 3*(SEGMENT.speed >> 5))+thisPhase) & 0xFF)/2   // factor=23 // Create a wave and add a phase change and add another wave with its own phase change. | ||||
|                               + cos8((i*(1+ 2*(SEGMENT.speed >> 5))+thatPhase) & 0xFF)/2;  // factor=15 // Hey, you can even change the frequencies if you wish. | ||||
|     unsigned thisBright = qsub8(colorIndex, beatsin8(7,0, (128 - (SEGMENT.intensity>>1)))); | ||||
|                               + cos8_t((i*(1+ 2*(SEGMENT.speed >> 5))+thatPhase) & 0xFF)/2;  // factor=15 // Hey, you can even change the frequencies if you wish. | ||||
|     unsigned thisBright = qsub8(colorIndex, beatsin8_t(7,0, (128 - (SEGMENT.intensity>>1)))); | ||||
|     SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(colorIndex, false, PALETTE_SOLID_WRAP, 0, thisBright)); | ||||
|   } | ||||
|  | ||||
| @@ -4001,10 +3988,10 @@ static CRGB pacifica_one_layer(uint16_t i, CRGBPalette16& p, uint16_t cistart, u | ||||
|   unsigned wavescale_half = (wavescale >> 1) + 20; | ||||
|  | ||||
|   waveangle += ((120 + SEGMENT.intensity) * i); //original 250 * i | ||||
|   unsigned s16 = sin16(waveangle) + 32768; | ||||
|   unsigned s16 = sin16_t(waveangle) + 32768; | ||||
|   unsigned cs = scale16(s16, wavescale_half) + wavescale_half; | ||||
|   ci += (cs * i); | ||||
|   unsigned sindex16 = sin16(ci) + 32768; | ||||
|   unsigned sindex16 = sin16_t(ci) + 32768; | ||||
|   unsigned sindex8 = scale16(sindex16, 240); | ||||
|   return ColorFromPalette(p, sindex8, bri, LINEARBLEND); | ||||
| } | ||||
| @@ -4031,39 +4018,39 @@ uint16_t mode_pacifica() | ||||
|  | ||||
|   // Increment the four "color index start" counters, one for each wave layer. | ||||
|   // Each is incremented at a different speed, and the speeds vary over time. | ||||
|   unsigned sCIStart1 = SEGENV.aux0, sCIStart2 = SEGENV.aux1, sCIStart3 = SEGENV.step, sCIStart4 = SEGENV.step >> 16; | ||||
|   unsigned sCIStart1 = SEGENV.aux0, sCIStart2 = SEGENV.aux1, sCIStart3 = SEGENV.step & 0xFFFF, sCIStart4 = (SEGENV.step >> 16); | ||||
|   uint32_t deltams = (FRAMETIME >> 2) + ((FRAMETIME * SEGMENT.speed) >> 7); | ||||
|   uint64_t deltat = (strip.now >> 2) + ((strip.now * SEGMENT.speed) >> 7); | ||||
|   strip.now = deltat; | ||||
|  | ||||
|   unsigned speedfactor1 = beatsin16(3, 179, 269); | ||||
|   unsigned speedfactor2 = beatsin16(4, 179, 269); | ||||
|   unsigned speedfactor1 = beatsin16_t(3, 179, 269); | ||||
|   unsigned speedfactor2 = beatsin16_t(4, 179, 269); | ||||
|   uint32_t deltams1 = (deltams * speedfactor1) / 256; | ||||
|   uint32_t deltams2 = (deltams * speedfactor2) / 256; | ||||
|   uint32_t deltams21 = (deltams1 + deltams2) / 2; | ||||
|   sCIStart1 += (deltams1 * beatsin88(1011,10,13)); | ||||
|   sCIStart2 -= (deltams21 * beatsin88(777,8,11)); | ||||
|   sCIStart3 -= (deltams1 * beatsin88(501,5,7)); | ||||
|   sCIStart4 -= (deltams2 * beatsin88(257,4,6)); | ||||
|   sCIStart1 += (deltams1 * beatsin88_t(1011,10,13)); | ||||
|   sCIStart2 -= (deltams21 * beatsin88_t(777,8,11)); | ||||
|   sCIStart3 -= (deltams1 * beatsin88_t(501,5,7)); | ||||
|   sCIStart4 -= (deltams2 * beatsin88_t(257,4,6)); | ||||
|   SEGENV.aux0 = sCIStart1; SEGENV.aux1 = sCIStart2; | ||||
|   SEGENV.step = sCIStart4; SEGENV.step = (SEGENV.step << 16) + sCIStart3; | ||||
|   SEGENV.step = (sCIStart4 << 16) | (sCIStart3 & 0xFFFF); | ||||
|  | ||||
|   // Clear out the LED array to a dim background blue-green | ||||
|   //SEGMENT.fill(132618); | ||||
|  | ||||
|   unsigned basethreshold = beatsin8( 9, 55, 65); | ||||
|   unsigned basethreshold = beatsin8_t( 9, 55, 65); | ||||
|   unsigned wave = beat8( 7 ); | ||||
|  | ||||
|   for (int i = 0; i < SEGLEN; i++) { | ||||
|     CRGB c = CRGB(2, 6, 10); | ||||
|     // Render each of four layers, with different scales and speeds, that vary over time | ||||
|     c += pacifica_one_layer(i, pacifica_palette_1, sCIStart1, beatsin16(3, 11 * 256, 14 * 256), beatsin8(10, 70, 130), 0-beat16(301)); | ||||
|     c += pacifica_one_layer(i, pacifica_palette_2, sCIStart2, beatsin16(4,  6 * 256,  9 * 256), beatsin8(17, 40,  80),   beat16(401)); | ||||
|     c += pacifica_one_layer(i, pacifica_palette_3, sCIStart3,                         6 * 256 , beatsin8(9, 10,38)   , 0-beat16(503)); | ||||
|     c += pacifica_one_layer(i, pacifica_palette_3, sCIStart4,                         5 * 256 , beatsin8(8, 10,28)   ,   beat16(601)); | ||||
|     c += pacifica_one_layer(i, pacifica_palette_1, sCIStart1, beatsin16_t(3, 11 * 256, 14 * 256), beatsin8_t(10, 70, 130), 0-beat16(301)); | ||||
|     c += pacifica_one_layer(i, pacifica_palette_2, sCIStart2, beatsin16_t(4,  6 * 256,  9 * 256), beatsin8_t(17, 40,  80),   beat16(401)); | ||||
|     c += pacifica_one_layer(i, pacifica_palette_3, sCIStart3,                         6 * 256 , beatsin8_t(9, 10,38)   , 0-beat16(503)); | ||||
|     c += pacifica_one_layer(i, pacifica_palette_3, sCIStart4,                         5 * 256 , beatsin8_t(8, 10,28)   ,   beat16(601)); | ||||
|  | ||||
|     // Add extra 'white' to areas where the four layers of light have lined up brightly | ||||
|     unsigned threshold = scale8( sin8( wave), 20) + basethreshold; | ||||
|     unsigned threshold = scale8( sin8_t( wave), 20) + basethreshold; | ||||
|     wave += 7; | ||||
|     unsigned l = c.getAverageLight(); | ||||
|     if (l > threshold) { | ||||
| @@ -4077,7 +4064,7 @@ uint16_t mode_pacifica() | ||||
|     c.green = scale8(c.green, 200); | ||||
|     c |= CRGB( 2, 5, 7); | ||||
|  | ||||
|     SEGMENT.setPixelColor(i, c.red, c.green, c.blue); | ||||
|     SEGMENT.setPixelColor(i, c); | ||||
|   } | ||||
|  | ||||
|   strip.now = nowOld; | ||||
| @@ -4187,7 +4174,7 @@ uint16_t mode_twinkleup(void) {                 // A very short twinkle routine | ||||
|  | ||||
|   for (int i = 0; i < SEGLEN; i++) { | ||||
|     unsigned ranstart = random8();               // The starting value (aka brightness) for each pixel. Must be consistent each time through the loop for this to work. | ||||
|     unsigned pixBri = sin8(ranstart + 16 * strip.now/(256-SEGMENT.speed)); | ||||
|     unsigned pixBri = sin8_t(ranstart + 16 * strip.now/(256-SEGMENT.speed)); | ||||
|     if (random8() > SEGMENT.intensity) pixBri = 0; | ||||
|     SEGMENT.setPixelColor(i, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(random8()+strip.now/100, false, PALETTE_SOLID_WRAP, 0), pixBri)); | ||||
|   } | ||||
| @@ -4230,7 +4217,7 @@ uint16_t mode_noisepal(void) {                                    // Slow noise | ||||
|     SEGMENT.setPixelColor(i, color.red, color.green, color.blue); | ||||
|   } | ||||
|  | ||||
|   SEGENV.aux0 += beatsin8(10,1,4);                                        // Moving along the distance. Vary it a bit with a sine wave. | ||||
|   SEGENV.aux0 += beatsin8_t(10,1,4);                                        // Moving along the distance. Vary it a bit with a sine wave. | ||||
|  | ||||
|   return FRAMETIME; | ||||
| } | ||||
| @@ -4312,7 +4299,7 @@ uint16_t mode_chunchun(void) | ||||
|   for (unsigned i = 0; i < numBirds; i++) | ||||
|   { | ||||
|     counter -= span; | ||||
|     unsigned megumin = sin16(counter) + 0x8000; | ||||
|     unsigned megumin = sin16_t(counter) + 0x8000; | ||||
|     unsigned bird = uint32_t(megumin * SEGLEN) >> 16; | ||||
|     uint32_t c = SEGMENT.color_from_palette((i * 255)/ numBirds, false, false, 0);  // no palette wrapping | ||||
|     bird = constrain(bird, 0U, SEGLEN-1U); | ||||
| @@ -4481,7 +4468,7 @@ uint16_t mode_washing_machine(void) { | ||||
|   SEGENV.step += (speed * 2048) / (512 - SEGMENT.speed); | ||||
|  | ||||
|   for (int i = 0; i < SEGLEN; i++) { | ||||
|     uint8_t col = sin8(((SEGMENT.intensity / 25 + 1) * 255 * i / SEGLEN) + (SEGENV.step >> 7)); | ||||
|     uint8_t col = sin8_t(((SEGMENT.intensity / 25 + 1) * 255 * i / SEGLEN) + (SEGENV.step >> 7)); | ||||
|     SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(col, false, PALETTE_SOLID_WRAP, 3)); | ||||
|   } | ||||
|  | ||||
| @@ -4644,7 +4631,7 @@ uint16_t mode_tv_simulator(void) { | ||||
|  | ||||
|   return FRAMETIME; | ||||
| } | ||||
| static const char _data_FX_MODE_TV_SIMULATOR[] PROGMEM = "TV Simulator@!,!;;"; | ||||
| static const char _data_FX_MODE_TV_SIMULATOR[] PROGMEM = "TV Simulator@!,!;;!;01"; | ||||
|  | ||||
|  | ||||
| /* | ||||
| @@ -4837,8 +4824,8 @@ static const char _data_FX_MODE_PERLINMOVE[] PROGMEM = "Perlin Move@!,# of pixel | ||||
| uint16_t mode_wavesins(void) { | ||||
|  | ||||
|   for (int i = 0; i < SEGLEN; i++) { | ||||
|     uint8_t bri = sin8(strip.now/4 + i * SEGMENT.intensity); | ||||
|     uint8_t index = beatsin8(SEGMENT.speed, SEGMENT.custom1, SEGMENT.custom1+SEGMENT.custom2, 0, i * (SEGMENT.custom3<<3)); // custom3 is reduced resolution slider | ||||
|     uint8_t bri = sin8_t(strip.now/4 + i * SEGMENT.intensity); | ||||
|     uint8_t index = beatsin8_t(SEGMENT.speed, SEGMENT.custom1, SEGMENT.custom1+SEGMENT.custom2, 0, i * (SEGMENT.custom3<<3)); // custom3 is reduced resolution slider | ||||
|     //SEGMENT.setPixelColor(i, ColorFromPalette(SEGPALETTE, index, bri, LINEARBLEND)); | ||||
|     SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0, bri)); | ||||
|   } | ||||
| @@ -4860,9 +4847,9 @@ uint16_t mode_FlowStripe(void) { | ||||
|  | ||||
|   for (int i = 0; i < SEGLEN; i++) { | ||||
|     int c = (abs(i - hl) / hl) * 127; | ||||
|     c = sin8(c); | ||||
|     c = sin8(c / 2 + t); | ||||
|     byte b = sin8(c + t/8); | ||||
|     c = sin8_t(c); | ||||
|     c = sin8_t(c / 2 + t); | ||||
|     byte b = sin8_t(c + t/8); | ||||
|     SEGMENT.setPixelColor(i, CHSV(b + hue, 255, 255)); | ||||
|   } | ||||
|  | ||||
| @@ -4889,14 +4876,14 @@ uint16_t mode_2DBlackHole(void) {            // By: Stepko https://editor.soulma | ||||
|   unsigned long t = strip.now/128;                 // timebase | ||||
|   // outer stars | ||||
|   for (size_t i = 0; i < 8; i++) { | ||||
|     x = beatsin8(SEGMENT.custom1>>3,   0, cols - 1, 0, ((i % 2) ? 128 : 0) + t * i); | ||||
|     y = beatsin8(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + t * i); | ||||
|     x = beatsin8_t(SEGMENT.custom1>>3,   0, cols - 1, 0, ((i % 2) ? 128 : 0) + t * i); | ||||
|     y = beatsin8_t(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + t * i); | ||||
|     SEGMENT.addPixelColorXY(x, y, SEGMENT.color_from_palette(i*32, false, PALETTE_SOLID_WRAP, SEGMENT.check1?0:255)); | ||||
|   } | ||||
|   // inner stars | ||||
|   for (size_t i = 0; i < 4; i++) { | ||||
|     x = beatsin8(SEGMENT.custom2>>3, cols/4, cols - 1 - cols/4, 0, ((i % 2) ? 128 : 0) + t * i); | ||||
|     y = beatsin8(SEGMENT.custom3   , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + t * i); | ||||
|     x = beatsin8_t(SEGMENT.custom2>>3, cols/4, cols - 1 - cols/4, 0, ((i % 2) ? 128 : 0) + t * i); | ||||
|     y = beatsin8_t(SEGMENT.custom3   , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + t * i); | ||||
|     SEGMENT.addPixelColorXY(x, y, SEGMENT.color_from_palette(255-i*64, false, PALETTE_SOLID_WRAP, SEGMENT.check1?0:255)); | ||||
|   } | ||||
|   // central white dot | ||||
| @@ -4930,10 +4917,10 @@ uint16_t mode_2DColoredBursts() {              // By: ldirko   https://editor.so | ||||
|   SEGENV.aux0++;  // hue | ||||
|   SEGMENT.fadeToBlackBy(40); | ||||
|   for (size_t i = 0; i < numLines; i++) { | ||||
|     byte x1 = beatsin8(2 + SEGMENT.speed/16, 0, (cols - 1)); | ||||
|     byte x2 = beatsin8(1 + SEGMENT.speed/16, 0, (cols - 1)); | ||||
|     byte y1 = beatsin8(5 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 24); | ||||
|     byte y2 = beatsin8(3 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 48 + 64); | ||||
|     byte x1 = beatsin8_t(2 + SEGMENT.speed/16, 0, (cols - 1)); | ||||
|     byte x2 = beatsin8_t(1 + SEGMENT.speed/16, 0, (rows - 1)); | ||||
|     byte y1 = beatsin8_t(5 + SEGMENT.speed/16, 0, (cols - 1), 0, i * 24); | ||||
|     byte y2 = beatsin8_t(3 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 48 + 64); | ||||
|     CRGB color = ColorFromPalette(SEGPALETTE, i * 255 / numLines + (SEGENV.aux0&0xFF), 255, LINEARBLEND); | ||||
|  | ||||
|     byte xsteps = abs8(x1 - y1) + 1; | ||||
| @@ -4972,8 +4959,8 @@ uint16_t mode_2Ddna(void) {         // dna originally by by ldirko at https://pa | ||||
|  | ||||
|   SEGMENT.fadeToBlackBy(64); | ||||
|   for (int i = 0; i < cols; i++) { | ||||
|     SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4    ), ColorFromPalette(SEGPALETTE, i*5+strip.now/17, beatsin8(5, 55, 255, 0, i*10), LINEARBLEND)); | ||||
|     SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4+128), ColorFromPalette(SEGPALETTE, i*5+128+strip.now/17, beatsin8(5, 55, 255, 0, i*10+128), LINEARBLEND)); | ||||
|     SEGMENT.setPixelColorXY(i, beatsin8_t(SEGMENT.speed/8, 0, rows-1, 0, i*4    ), ColorFromPalette(SEGPALETTE, i*5+strip.now/17, beatsin8_t(5, 55, 255, 0, i*10), LINEARBLEND)); | ||||
|     SEGMENT.setPixelColorXY(i, beatsin8_t(SEGMENT.speed/8, 0, rows-1, 0, i*4+128), ColorFromPalette(SEGPALETTE, i*5+128+strip.now/17, beatsin8_t(5, 55, 255, 0, i*10+128), LINEARBLEND)); | ||||
|   } | ||||
|   SEGMENT.blur(SEGMENT.intensity>>3); | ||||
|  | ||||
| @@ -5002,17 +4989,19 @@ uint16_t mode_2DDNASpiral() {               // By: ldirko  https://editor.soulma | ||||
|   SEGMENT.fadeToBlackBy(135); | ||||
|  | ||||
|   for (int i = 0; i < rows; i++) { | ||||
|     int x  = beatsin8(speeds, 0, cols - 1, 0, i * freq) + beatsin8(speeds - 7, 0, cols - 1, 0, i * freq + 128); | ||||
|     int x1 = beatsin8(speeds, 0, cols - 1, 0, 128 + i * freq) + beatsin8(speeds - 7, 0, cols - 1, 0, 128 + 64 + i * freq); | ||||
|     int x  = beatsin8_t(speeds, 0, cols - 1, 0, i * freq) + beatsin8_t(speeds - 7, 0, cols - 1, 0, i * freq + 128); | ||||
|     int x1 = beatsin8_t(speeds, 0, cols - 1, 0, 128 + i * freq) + beatsin8_t(speeds - 7, 0, cols - 1, 0, 128 + 64 + i * freq); | ||||
|     unsigned hue = (i * 128 / rows) + ms; | ||||
|     // skip every 4th row every now and then (fade it more) | ||||
|     if ((i + ms / 8) & 3) { | ||||
|       // draw a gradient line between x and x1 | ||||
|       x = x / 2; x1 = x1 / 2; | ||||
|       unsigned steps = abs8(x - x1) + 1; | ||||
|       bool positive = (x1 >= x);                         // direction of drawing | ||||
|       for (size_t k = 1; k <= steps; k++) { | ||||
|         unsigned rate = k * 255 / steps; | ||||
|         unsigned dx = lerp8by8(x, x1, rate); | ||||
|         //unsigned dx = lerp8by8(x, x1, rate); | ||||
|         unsigned dx = positive? (x + k-1) : (x - k+1);   // behaves the same as "lerp8by8" but does not create holes | ||||
|         //SEGMENT.setPixelColorXY(dx, i, ColorFromPalette(SEGPALETTE, hue, 255, LINEARBLEND).nscale8_video(rate)); | ||||
|         SEGMENT.addPixelColorXY(dx, i, ColorFromPalette(SEGPALETTE, hue, 255, LINEARBLEND)); // use setPixelColorXY for different look | ||||
|         SEGMENT.fadePixelColorXY(dx, i, rate); | ||||
| @@ -5102,9 +5091,9 @@ uint16_t mode_2DFrizzles(void) {                 // By: Stepko https://editor.so | ||||
|  | ||||
|   SEGMENT.fadeToBlackBy(16); | ||||
|   for (size_t i = 8; i > 0; i--) { | ||||
|     SEGMENT.addPixelColorXY(beatsin8(SEGMENT.speed/8 + i, 0, cols - 1), | ||||
|                             beatsin8(SEGMENT.intensity/8 - i, 0, rows - 1), | ||||
|                             ColorFromPalette(SEGPALETTE, beatsin8(12, 0, 255), 255, LINEARBLEND)); | ||||
|     SEGMENT.addPixelColorXY(beatsin8_t(SEGMENT.speed/8 + i, 0, cols - 1), | ||||
|                             beatsin8_t(SEGMENT.intensity/8 - i, 0, rows - 1), | ||||
|                             ColorFromPalette(SEGPALETTE, beatsin8_t(12, 0, 255), 255, LINEARBLEND)); | ||||
|   } | ||||
|   SEGMENT.blur(SEGMENT.custom1>>3); | ||||
|  | ||||
| @@ -5236,7 +5225,7 @@ uint16_t mode_2DHiphotic() {                        //  By: ldirko  https://edit | ||||
|  | ||||
|   for (int x = 0; x < cols; x++) { | ||||
|     for (int y = 0; y < rows; y++) { | ||||
|       SEGMENT.setPixelColorXY(x, y, SEGMENT.color_from_palette(sin8(cos8(x * SEGMENT.speed/16 + a / 3) + sin8(y * SEGMENT.intensity/16 + a / 4) + a), false, PALETTE_SOLID_WRAP, 0)); | ||||
|       SEGMENT.setPixelColorXY(x, y, SEGMENT.color_from_palette(sin8_t(cos8_t(x * SEGMENT.speed/16 + a / 3) + sin8_t(y * SEGMENT.intensity/16 + a / 4) + a), false, PALETTE_SOLID_WRAP, 0)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -5312,8 +5301,8 @@ uint16_t mode_2DJulia(void) {                           // An animated Julia set | ||||
|   reAl = -0.94299f;               // PixelBlaze example | ||||
|   imAg = 0.3162f; | ||||
|  | ||||
|   reAl += sin_t((float)strip.now/305.f)/20.f; | ||||
|   imAg += sin_t((float)strip.now/405.f)/20.f; | ||||
|   reAl += (float)sin16_t(strip.now * 34) / 655340.f; | ||||
|   imAg += (float)sin16_t(strip.now * 26) / 655340.f; | ||||
|  | ||||
|   dx = (xmax - xmin) / (cols);     // Scale the delta x and y values to our matrix size. | ||||
|   dy = (ymax - ymin) / (rows); | ||||
| @@ -5376,10 +5365,10 @@ uint16_t mode_2DLissajous(void) {            // By: Andrew Tuline | ||||
|  | ||||
|   //for (int i=0; i < 4*(cols+rows); i ++) { | ||||
|   for (int i=0; i < 256; i ++) { | ||||
|     //float xlocn = float(sin8(now/4+i*(SEGMENT.speed>>5))) / 255.0f; | ||||
|     //float ylocn = float(cos8(now/4+i*2)) / 255.0f; | ||||
|     uint_fast8_t xlocn = sin8(phase/2 + (i*SEGMENT.speed)/32); | ||||
|     uint_fast8_t ylocn = cos8(phase/2 + i*2); | ||||
|     //float xlocn = float(sin8_t(now/4+i*(SEGMENT.speed>>5))) / 255.0f; | ||||
|     //float ylocn = float(cos8_t(now/4+i*2)) / 255.0f; | ||||
|     uint_fast8_t xlocn = sin8_t(phase/2 + (i*SEGMENT.speed)/32); | ||||
|     uint_fast8_t ylocn = cos8_t(phase/2 + i*2); | ||||
|     xlocn = (cols < 2) ? 1 : (map(2*xlocn, 0,511, 0,2*(cols-1)) +1) /2;    // softhack007: "(2* ..... +1) /2" for proper rounding | ||||
|     ylocn = (rows < 2) ? 1 : (map(2*ylocn, 0,511, 0,2*(rows-1)) +1) /2;    // "rows > 1" is needed to avoid div/0 in map() | ||||
|     SEGMENT.setPixelColorXY((uint8_t)xlocn, (uint8_t)ylocn, SEGMENT.color_from_palette(strip.now/100+i, false, PALETTE_SOLID_WRAP, 0)); | ||||
| @@ -5479,8 +5468,8 @@ uint16_t mode_2Dmetaballs(void) {   // Metaballs by Stefan Petrick. Cannot have | ||||
|   int y3 = map(inoise8(strip.now * speed, 25355, 22685), 0, 255, 0, rows-1); | ||||
|  | ||||
|   // and one Lissajou function | ||||
|   int x1 = beatsin8(23 * speed, 0, cols-1); | ||||
|   int y1 = beatsin8(28 * speed, 0, rows-1); | ||||
|   int x1 = beatsin8_t(23 * speed, 0, cols-1); | ||||
|   int y1 = beatsin8_t(28 * speed, 0, rows-1); | ||||
|  | ||||
|   for (int y = 0; y < rows; y++) { | ||||
|     for (int x = 0; x < cols; x++) { | ||||
| @@ -5645,7 +5634,7 @@ uint16_t mode_2DPulser(void) {                       // By: ldirko   https://edi | ||||
|   SEGMENT.fadeToBlackBy(8 - (SEGMENT.intensity>>5)); | ||||
|   uint32_t a = strip.now / (18 - SEGMENT.speed / 16); | ||||
|   int x = (a / 14) % cols; | ||||
|   int y = map((sin8(a * 5) + sin8(a * 4) + sin8(a * 2)), 0, 765, rows-1, 0); | ||||
|   int y = map((sin8_t(a * 5) + sin8_t(a * 4) + sin8_t(a * 2)), 0, 765, rows-1, 0); | ||||
|   SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, map(y, 0, rows-1, 0, 255), 255, LINEARBLEND)); | ||||
|  | ||||
|   SEGMENT.blur(SEGMENT.intensity>>4); | ||||
| @@ -5671,10 +5660,10 @@ uint16_t mode_2DSindots(void) {                             // By: ldirko   http | ||||
|   SEGMENT.fadeToBlackBy(SEGMENT.custom1>>3); | ||||
|  | ||||
|   byte t1 = strip.now / (257 - SEGMENT.speed); // 20; | ||||
|   byte t2 = sin8(t1) / 4 * 2; | ||||
|   byte t2 = sin8_t(t1) / 4 * 2; | ||||
|   for (int i = 0; i < 13; i++) { | ||||
|     int x = sin8(t1 + i * SEGMENT.intensity/8)*(cols-1)/255;  // max index now 255x15/255=15! | ||||
|     int y = sin8(t2 + i * SEGMENT.intensity/8)*(rows-1)/255;  // max index now 255x15/255=15! | ||||
|     int x = sin8_t(t1 + i * SEGMENT.intensity/8)*(cols-1)/255;  // max index now 255x15/255=15! | ||||
|     int y = sin8_t(t2 + i * SEGMENT.intensity/8)*(rows-1)/255;  // max index now 255x15/255=15! | ||||
|     SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, i * 255 / 13, 255, LINEARBLEND)); | ||||
|   } | ||||
|   SEGMENT.blur(SEGMENT.custom2>>3); | ||||
| @@ -5701,12 +5690,12 @@ uint16_t mode_2Dsquaredswirl(void) {            // By: Mark Kriegsman. https://g | ||||
|   SEGMENT.blur(SEGMENT.custom3>>1); | ||||
|  | ||||
|   // Use two out-of-sync sine waves | ||||
|   int i = beatsin8(19, kBorderWidth, cols-kBorderWidth); | ||||
|   int j = beatsin8(22, kBorderWidth, cols-kBorderWidth); | ||||
|   int k = beatsin8(17, kBorderWidth, cols-kBorderWidth); | ||||
|   int m = beatsin8(18, kBorderWidth, rows-kBorderWidth); | ||||
|   int n = beatsin8(15, kBorderWidth, rows-kBorderWidth); | ||||
|   int p = beatsin8(20, kBorderWidth, rows-kBorderWidth); | ||||
|   int i = beatsin8_t(19, kBorderWidth, cols-kBorderWidth); | ||||
|   int j = beatsin8_t(22, kBorderWidth, cols-kBorderWidth); | ||||
|   int k = beatsin8_t(17, kBorderWidth, cols-kBorderWidth); | ||||
|   int m = beatsin8_t(18, kBorderWidth, rows-kBorderWidth); | ||||
|   int n = beatsin8_t(15, kBorderWidth, rows-kBorderWidth); | ||||
|   int p = beatsin8_t(20, kBorderWidth, rows-kBorderWidth); | ||||
|  | ||||
|   SEGMENT.addPixelColorXY(i, m, ColorFromPalette(SEGPALETTE, strip.now/29, 255, LINEARBLEND)); | ||||
|   SEGMENT.addPixelColorXY(j, n, ColorFromPalette(SEGPALETTE, strip.now/41, 255, LINEARBLEND)); | ||||
| @@ -5782,19 +5771,19 @@ uint16_t mode_2Dtartan(void) {          // By: Elliott Kember  https://editor.so | ||||
|  | ||||
|   uint8_t hue, bri; | ||||
|   size_t intensity; | ||||
|   int offsetX = beatsin16(3, -360, 360); | ||||
|   int offsetY = beatsin16(2, -360, 360); | ||||
|   int offsetX = beatsin16_t(3, -360, 360); | ||||
|   int offsetY = beatsin16_t(2, -360, 360); | ||||
|   int sharpness = SEGMENT.custom3 / 8; // 0-3 | ||||
|  | ||||
|   for (int x = 0; x < cols; x++) { | ||||
|     for (int y = 0; y < rows; y++) { | ||||
|       hue = x * beatsin16(10, 1, 10) + offsetY; | ||||
|       intensity = bri = sin8(x * SEGMENT.speed/2 + offsetX); | ||||
|       hue = x * beatsin16_t(10, 1, 10) + offsetY; | ||||
|       intensity = bri = sin8_t(x * SEGMENT.speed/2 + offsetX); | ||||
|       for (int i=0; i<sharpness; i++) intensity *= bri; | ||||
|       intensity >>= 8*sharpness; | ||||
|       SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, hue, intensity, LINEARBLEND)); | ||||
|       hue = y * 3 + offsetX; | ||||
|       intensity = bri = sin8(y * SEGMENT.intensity/2 + offsetY); | ||||
|       intensity = bri = sin8_t(y * SEGMENT.intensity/2 + offsetY); | ||||
|       for (int i=0; i<sharpness; i++) intensity *= bri; | ||||
|       intensity >>= 8*sharpness; | ||||
|       SEGMENT.addPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, hue, intensity, LINEARBLEND)); | ||||
| @@ -5829,9 +5818,9 @@ uint16_t mode_2Dspaceships(void) {    //// Space ships by stepko (c)05.02.21 [ht | ||||
|   SEGMENT.move(SEGENV.aux0, 1); | ||||
|  | ||||
|   for (size_t i = 0; i < 8; i++) { | ||||
|     int x = beatsin8(12 + i, 2, cols - 3); | ||||
|     int y = beatsin8(15 + i, 2, rows - 3); | ||||
|     CRGB color = ColorFromPalette(SEGPALETTE, beatsin8(12 + i, 0, 255), 255); | ||||
|     int x = beatsin8_t(12 + i, 2, cols - 3); | ||||
|     int y = beatsin8_t(15 + i, 2, rows - 3); | ||||
|     CRGB color = ColorFromPalette(SEGPALETTE, beatsin8_t(12 + i, 0, 255), 255); | ||||
|     SEGMENT.addPixelColorXY(x, y, color); | ||||
|     if (cols > 24 || rows > 24) { | ||||
|       SEGMENT.addPixelColorXY(x+1, y, color); | ||||
| @@ -6227,8 +6216,8 @@ uint16_t mode_2Ddriftrose(void) { | ||||
|   SEGMENT.fadeToBlackBy(32+(SEGMENT.speed>>3)); | ||||
|   for (size_t i = 1; i < 37; i++) { | ||||
|     float angle = radians(i * 10); | ||||
|     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; | ||||
|     uint32_t x = (CX + (sin_t(angle) * (beatsin8_t(i, 0, L*2)-L))) * 255.f; | ||||
|     uint32_t y = (CY + (cos_t(angle) * (beatsin8_t(i, 0, L*2)-L))) * 255.f; | ||||
|     SEGMENT.wu_pixel(x, y, CHSV(i * 10, 255, 255)); | ||||
|   } | ||||
|   SEGMENT.blur(SEGMENT.intensity>>4); | ||||
| @@ -6277,6 +6266,7 @@ uint16_t mode_2Dplasmarotozoom() { | ||||
|     } | ||||
|   } | ||||
|   *a -= 0.03f + float(SEGENV.speed-128)*0.0002f;  // rotation speed | ||||
|   if(*a < -6283.18530718f) *a += 6283.18530718f; // 1000*2*PI, protect sin/cos from very large input float values (will give wrong results) | ||||
|  | ||||
|   return FRAMETIME; | ||||
| } | ||||
| @@ -6424,8 +6414,8 @@ uint16_t mode_2DSwirl(void) { | ||||
|  | ||||
|   SEGMENT.blur(SEGMENT.custom1); | ||||
|  | ||||
|   int  i = beatsin8( 27*SEGMENT.speed/255, borderWidth, cols - borderWidth); | ||||
|   int  j = beatsin8( 41*SEGMENT.speed/255, borderWidth, rows - borderWidth); | ||||
|   int  i = beatsin8_t( 27*SEGMENT.speed/255, borderWidth, cols - borderWidth); | ||||
|   int  j = beatsin8_t( 41*SEGMENT.speed/255, borderWidth, rows - borderWidth); | ||||
|   int ni = (cols - 1) - i; | ||||
|   int nj = (cols - 1) - j; | ||||
|  | ||||
| @@ -6637,7 +6627,7 @@ uint16_t mode_juggles(void) {                   // Juggles. By Andrew Tuline. | ||||
|  | ||||
|   for (size_t i=0; i<SEGMENT.intensity/32+1U; i++) { | ||||
|     // if SEGLEN equals 1, we will always set color to the first and only pixel, but the effect is still good looking | ||||
|     SEGMENT.setPixelColor(beatsin16(SEGMENT.speed/4+i*2,0,SEGLEN-1), color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(strip.now/4+i*2, false, PALETTE_SOLID_WRAP, 0), my_sampleAgc)); | ||||
|     SEGMENT.setPixelColor(beatsin16_t(SEGMENT.speed/4+i*2,0,SEGLEN-1), color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(strip.now/4+i*2, false, PALETTE_SOLID_WRAP, 0), my_sampleAgc)); | ||||
|   } | ||||
|  | ||||
|   return FRAMETIME; | ||||
| @@ -6697,8 +6687,8 @@ uint16_t mode_midnoise(void) {                  // Midnoise. By Andrew Tuline. | ||||
|     SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0)); | ||||
|   } | ||||
|  | ||||
|   SEGENV.aux0=SEGENV.aux0+beatsin8(5,0,10); | ||||
|   SEGENV.aux1=SEGENV.aux1+beatsin8(4,0,10); | ||||
|   SEGENV.aux0=SEGENV.aux0+beatsin8_t(5,0,10); | ||||
|   SEGENV.aux1=SEGENV.aux1+beatsin8_t(4,0,10); | ||||
|  | ||||
|   return FRAMETIME; | ||||
| } // mode_midnoise() | ||||
| @@ -6757,8 +6747,8 @@ uint16_t mode_noisemeter(void) {                // Noisemeter. By Andrew Tuline. | ||||
|     SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0)); | ||||
|   } | ||||
|  | ||||
|   SEGENV.aux0+=beatsin8(5,0,10); | ||||
|   SEGENV.aux1+=beatsin8(4,0,10); | ||||
|   SEGENV.aux0+=beatsin8_t(5,0,10); | ||||
|   SEGENV.aux1+=beatsin8_t(4,0,10); | ||||
|  | ||||
|   return FRAMETIME; | ||||
| } // mode_noisemeter() | ||||
| @@ -6813,13 +6803,13 @@ uint16_t mode_plasmoid(void) {                  // Plasmoid. By Andrew Tuline. | ||||
|  | ||||
|   SEGMENT.fadeToBlackBy(32); | ||||
|  | ||||
|   plasmoip->thisphase += beatsin8(6,-4,4);                          // You can change direction and speed individually. | ||||
|   plasmoip->thatphase += beatsin8(7,-4,4);                          // Two phase values to make a complex pattern. By Andrew Tuline. | ||||
|   plasmoip->thisphase += beatsin8_t(6,-4,4);                          // You can change direction and speed individually. | ||||
|   plasmoip->thatphase += beatsin8_t(7,-4,4);                          // Two phase values to make a complex pattern. By Andrew Tuline. | ||||
|  | ||||
|   for (int i = 0; i < SEGLEN; i++) {                          // For each of the LED's in the strand, set a brightness based on a wave as follows. | ||||
|     // updated, similar to "plasma" effect - softhack007 | ||||
|     uint8_t thisbright = cubicwave8(((i*(1 + (3*SEGMENT.speed/32)))+plasmoip->thisphase) & 0xFF)/2; | ||||
|     thisbright += cos8(((i*(97 +(5*SEGMENT.speed/32)))+plasmoip->thatphase) & 0xFF)/2; // Let's munge the brightness a bit and animate it all with the phases. | ||||
|     thisbright += cos8_t(((i*(97 +(5*SEGMENT.speed/32)))+plasmoip->thatphase) & 0xFF)/2; // Let's munge the brightness a bit and animate it all with the phases. | ||||
|  | ||||
|     uint8_t colorIndex=thisbright; | ||||
|     if (volumeSmth * SEGMENT.intensity / 64 < thisbright) {thisbright = 0;} | ||||
| @@ -7278,7 +7268,7 @@ uint16_t mode_rocktaves(void) {                 // Rocktaves. Same note from eac | ||||
|   frTemp -= 132.0f;                                       // This should give us a base musical note of C3 | ||||
|   frTemp  = fabsf(frTemp * 2.1f);                         // Fudge factors to compress octave range starting at 0 and going to 255; | ||||
|  | ||||
|   unsigned i = map(beatsin8(8+octCount*4, 0, 255, 0, octCount*8), 0, 255, 0, SEGLEN-1); | ||||
|   unsigned i = map(beatsin8_t(8+octCount*4, 0, 255, 0, octCount*8), 0, 255, 0, SEGLEN-1); | ||||
|   i = constrain(i, 0U, SEGLEN-1U); | ||||
|   SEGMENT.addPixelColor(i, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette((uint8_t)frTemp, false, PALETTE_SOLID_WRAP, 0), volTemp)); | ||||
|  | ||||
| @@ -7528,8 +7518,9 @@ uint16_t mode_2DAkemi(void) { | ||||
|  | ||||
|   //add geq left and right | ||||
|   if (um_data && fftResult) { | ||||
|     for (int x=0; x < cols/8; x++) { | ||||
|       unsigned band = x * cols/8; | ||||
|     int xMax = cols/8; | ||||
|     for (int x=0; x < xMax; x++) { | ||||
|       unsigned band = map(x, 0, max(xMax,4), 0, 15);  // map 0..cols/8 to 16 GEQ bands | ||||
|       band = constrain(band, 0, 15); | ||||
|       int barHeight = map(fftResult[band], 0, 255, 0, 17*rows/32); | ||||
|       CRGB color = CRGB(SEGMENT.color_from_palette((band * 35), false, PALETTE_SOLID_WRAP, 0)); | ||||
| @@ -7564,12 +7555,12 @@ uint16_t mode_2Ddistortionwaves() { | ||||
|   unsigned a2 = a/2; | ||||
|   unsigned a3 = a/3; | ||||
|  | ||||
|   unsigned cx =  beatsin8(10-speed,0,cols-1)*scale; | ||||
|   unsigned cy =  beatsin8(12-speed,0,rows-1)*scale; | ||||
|   unsigned cx1 = beatsin8(13-speed,0,cols-1)*scale; | ||||
|   unsigned cy1 = beatsin8(15-speed,0,rows-1)*scale; | ||||
|   unsigned cx2 = beatsin8(17-speed,0,cols-1)*scale; | ||||
|   unsigned cy2 = beatsin8(14-speed,0,rows-1)*scale; | ||||
|   unsigned cx =  beatsin8_t(10-speed,0,cols-1)*scale; | ||||
|   unsigned cy =  beatsin8_t(12-speed,0,rows-1)*scale; | ||||
|   unsigned cx1 = beatsin8_t(13-speed,0,cols-1)*scale; | ||||
|   unsigned cy1 = beatsin8_t(15-speed,0,rows-1)*scale; | ||||
|   unsigned cx2 = beatsin8_t(17-speed,0,cols-1)*scale; | ||||
|   unsigned cy2 = beatsin8_t(14-speed,0,rows-1)*scale; | ||||
|    | ||||
|   unsigned xoffs = 0; | ||||
|   for (int x = 0; x < cols; x++) { | ||||
| @@ -7579,17 +7570,17 @@ uint16_t mode_2Ddistortionwaves() { | ||||
|     for (int y = 0; y < rows; y++) { | ||||
|        yoffs += scale; | ||||
|  | ||||
|       byte rdistort = cos8((cos8(((x<<3)+a )&255)+cos8(((y<<3)-a2)&255)+a3   )&255)>>1;  | ||||
|       byte gdistort = cos8((cos8(((x<<3)-a2)&255)+cos8(((y<<3)+a3)&255)+a+32 )&255)>>1;  | ||||
|       byte bdistort = cos8((cos8(((x<<3)+a3)&255)+cos8(((y<<3)-a) &255)+a2+64)&255)>>1;  | ||||
|       byte rdistort = cos8_t((cos8_t(((x<<3)+a )&255)+cos8_t(((y<<3)-a2)&255)+a3   )&255)>>1;  | ||||
|       byte gdistort = cos8_t((cos8_t(((x<<3)-a2)&255)+cos8_t(((y<<3)+a3)&255)+a+32 )&255)>>1;  | ||||
|       byte bdistort = cos8_t((cos8_t(((x<<3)+a3)&255)+cos8_t(((y<<3)-a) &255)+a2+64)&255)>>1;  | ||||
|  | ||||
|       byte valueR = rdistort+ w*  (a- ( ((xoffs - cx)  * (xoffs - cx)  + (yoffs - cy)  * (yoffs - cy))>>7  )); | ||||
|       byte valueG = gdistort+ w*  (a2-( ((xoffs - cx1) * (xoffs - cx1) + (yoffs - cy1) * (yoffs - cy1))>>7 )); | ||||
|       byte valueB = bdistort+ w*  (a3-( ((xoffs - cx2) * (xoffs - cx2) + (yoffs - cy2) * (yoffs - cy2))>>7 )); | ||||
|  | ||||
|       valueR = gamma8(cos8(valueR)); | ||||
|       valueG = gamma8(cos8(valueG)); | ||||
|       valueB = gamma8(cos8(valueB)); | ||||
|       valueR = gamma8(cos8_t(valueR)); | ||||
|       valueG = gamma8(cos8_t(valueG)); | ||||
|       valueB = gamma8(cos8_t(valueB)); | ||||
|  | ||||
|       SEGMENT.setPixelColorXY(x, y, RGBW32(valueR, valueG, valueB, 0));  | ||||
|     } | ||||
| @@ -7746,8 +7737,10 @@ uint16_t mode_2Doctopus() { | ||||
|     const int C_Y = (rows / 2) + ((SEGMENT.custom2 - 128)*rows)/255; | ||||
|     for (int x = 0; x < cols; x++) { | ||||
|       for (int y = 0; y < rows; y++) { | ||||
|         rMap[XY(x, y)].angle  = 40.7436f * atan2f((y - C_Y), (x - C_X));  // avoid 128*atan2()/PI | ||||
|         rMap[XY(x, y)].radius = hypotf((x - C_X), (y - C_Y)) * mapp;      //thanks Sutaburosu | ||||
|         int dx = (x - C_X); | ||||
|         int dy = (y - C_Y); | ||||
|         rMap[XY(x, y)].angle  = int(40.7436f * atan2_t(dy, dx));  // avoid 128*atan2()/PI | ||||
|         rMap[XY(x, y)].radius = sqrtf(dx * dx + dy * dy) * mapp; //thanks Sutaburosu | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| @@ -7757,8 +7750,8 @@ uint16_t mode_2Doctopus() { | ||||
|     for (int y = 0; y < rows; y++) { | ||||
|       byte angle = rMap[XY(x,y)].angle; | ||||
|       byte radius = rMap[XY(x,y)].radius; | ||||
|       //CRGB c = CHSV(SEGENV.step / 2 - radius, 255, sin8(sin8((angle * 4 - radius) / 4 + SEGENV.step) + radius - SEGENV.step * 2 + angle * (SEGMENT.custom3/3+1))); | ||||
|       unsigned intensity = sin8(sin8((angle * 4 - radius) / 4 + SEGENV.step/2) + radius - SEGENV.step + angle * (SEGMENT.custom3/4+1)); | ||||
|       //CRGB c = CHSV(SEGENV.step / 2 - radius, 255, sin8_t(sin8_t((angle * 4 - radius) / 4 + SEGENV.step) + radius - SEGENV.step * 2 + angle * (SEGMENT.custom3/3+1))); | ||||
|       unsigned intensity = sin8_t(sin8_t((angle * 4 - radius) / 4 + SEGENV.step/2) + radius - SEGENV.step + angle * (SEGMENT.custom3/4+1)); | ||||
|       intensity = map((intensity*intensity) & 0xFFFF, 0, 65535, 0, 255); // add a bit of non-linearity for cleaner display | ||||
|       CRGB c = ColorFromPalette(SEGPALETTE, SEGENV.step / 2 - radius, intensity); | ||||
|       SEGMENT.setPixelColorXY(x, y, c); | ||||
| @@ -7766,7 +7759,7 @@ uint16_t mode_2Doctopus() { | ||||
|   } | ||||
|   return FRAMETIME; | ||||
| } | ||||
| static const char _data_FX_MODE_2DOCTOPUS[] PROGMEM = "Octopus@!,,Offset X,Offset Y,Legs;;!;2;"; | ||||
| static const char _data_FX_MODE_2DOCTOPUS[] PROGMEM = "Octopus@!,,Offset X,Offset Y,Legs,fasttan;;!;2;"; | ||||
|  | ||||
|  | ||||
| //Waving Cell | ||||
| @@ -7783,7 +7776,7 @@ uint16_t mode_2Dwavingcell() { | ||||
|   uint8_t aY = SEGMENT.custom2/16 + 1; | ||||
|   uint8_t aZ = SEGMENT.custom3 + 1; | ||||
|   for (int x = 0; x < cols; x++) for (int y = 0; y <rows; y++) | ||||
|     SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, ((sin8((x*aX)+sin8((y+t)*aY))+cos8(y*aZ))+1)+t)); | ||||
|     SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, ((sin8_t((x*aX)+sin8_t((y+t)*aY))+cos8_t(y*aZ))+1)+t)); | ||||
|  | ||||
|   return FRAMETIME; | ||||
| } | ||||
|   | ||||
							
								
								
									
										70
									
								
								wled00/FX.h
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								wled00/FX.h
									
									
									
									
									
								
							| @@ -2,24 +2,10 @@ | ||||
|   WS2812FX.h - Library for WS2812 LED effects. | ||||
|   Harm Aldick - 2016 | ||||
|   www.aldick.org | ||||
|   LICENSE | ||||
|   The MIT License (MIT) | ||||
|  | ||||
|   Copyright (c) 2016  Harm Aldick | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   in the Software without restriction, including without limitation the rights | ||||
|   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|   copies of the Software, and to permit persons to whom the Software is | ||||
|   furnished to do so, subject to the following conditions: | ||||
|   The above copyright notice and this permission notice shall be included in | ||||
|   all copies or substantial portions of the Software. | ||||
|   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|   THE SOFTWARE. | ||||
|   Licensed under the EUPL v. 1.2 or later | ||||
|   Adapted from code originally licensed under the MIT license | ||||
|  | ||||
|   Modified for WLED | ||||
| */ | ||||
| @@ -61,6 +47,15 @@ | ||||
| #define FRAMETIME_FIXED  (1000/WLED_FPS) | ||||
| #define FRAMETIME        strip.getFrameTime() | ||||
|  | ||||
| // FPS calculation (can be defined as compile flag for debugging) | ||||
| #ifndef FPS_CALC_AVG | ||||
| #define FPS_CALC_AVG 7 // average FPS calculation over this many frames (moving average) | ||||
| #endif | ||||
| #ifndef FPS_MULTIPLIER | ||||
| #define FPS_MULTIPLIER 1 // dev option: multiplier to get sub-frame FPS without floats | ||||
| #endif | ||||
| #define FPS_CALC_SHIFT 7 // bit shift for fixed point math | ||||
|  | ||||
| /* each segment uses 82 bytes of SRAM memory, so if you're application fails because of | ||||
|   insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ | ||||
| #ifdef ESP8266 | ||||
| @@ -539,12 +534,12 @@ typedef struct Segment { | ||||
|     inline static const CRGBPalette16 &getCurrentPalette() { return Segment::_currentPalette; } | ||||
|  | ||||
|     void    setUp(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1); | ||||
|     bool    setColor(uint8_t slot, uint32_t c); //returns true if changed | ||||
|     void    setCCT(uint16_t k); | ||||
|     void    setOpacity(uint8_t o); | ||||
|     void    setOption(uint8_t n, bool val); | ||||
|     void    setMode(uint8_t fx, bool loadDefaults = false); | ||||
|     void    setPalette(uint8_t pal); | ||||
|     Segment &setColor(uint8_t slot, uint32_t c); | ||||
|     Segment &setCCT(uint16_t k); | ||||
|     Segment &setOpacity(uint8_t o); | ||||
|     Segment &setOption(uint8_t n, bool val); | ||||
|     Segment &setMode(uint8_t fx, bool loadDefaults = false); | ||||
|     Segment &setPalette(uint8_t pal); | ||||
|     uint8_t differs(Segment& b) const; | ||||
|     void    refreshLightCapabilities(); | ||||
|  | ||||
| @@ -559,7 +554,7 @@ typedef struct Segment { | ||||
|       * Call resetIfRequired before calling the next effect function. | ||||
|       * Safe to call from interrupts and network requests. | ||||
|       */ | ||||
|     inline void markForReset() { reset = true; }  // setOption(SEG_OPTION_RESET, true) | ||||
|     inline Segment &markForReset() { reset = true; return *this; }  // setOption(SEG_OPTION_RESET, true) | ||||
|  | ||||
|     // transition functions | ||||
|     void     startTransition(uint16_t dur);     // transition has to start before actual segment values change | ||||
| @@ -613,9 +608,15 @@ typedef struct Segment { | ||||
|     } | ||||
|  | ||||
|     // 2D matrix | ||||
|     [[gnu::hot]] uint16_t virtualWidth()  const; // segment width in virtual pixels (accounts for groupping and spacing) | ||||
|     [[gnu::hot]] uint16_t virtualHeight() const; // segment height in virtual pixels (accounts for groupping and spacing) | ||||
|     uint16_t nrOfVStrips() const;                // returns number of virtual vertical strips in 2D matrix (used to expand 1D effects into 2D) | ||||
|     [[gnu::hot]] unsigned virtualWidth()  const; // segment width in virtual pixels (accounts for groupping and spacing) | ||||
|     [[gnu::hot]] unsigned virtualHeight() const; // segment height in virtual pixels (accounts for groupping and spacing) | ||||
|     inline unsigned nrOfVStrips() const {        // returns number of virtual vertical strips in 2D matrix (used to expand 1D effects into 2D) | ||||
|     #ifndef WLED_DISABLE_2D | ||||
|       return (is2D() &&  map1D2D == M12_pBar) ? virtualWidth() : 1; | ||||
|     #else | ||||
|       return 1; | ||||
|     #endif | ||||
|     } | ||||
|   #ifndef WLED_DISABLE_2D | ||||
|     [[gnu::hot]] uint16_t XY(int x, int y);      // support function to get relative index within segment | ||||
|     [[gnu::hot]] void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color | ||||
| @@ -720,7 +721,11 @@ class WS2812FX {  // 96 bytes | ||||
| #ifndef WLED_DISABLE_2D | ||||
|       panels(1), | ||||
| #endif | ||||
| #ifdef WLED_AUTOSEGMENTS | ||||
|       autoSegments(true), | ||||
| #else | ||||
|       autoSegments(false), | ||||
| #endif | ||||
|       correctWB(false), | ||||
|       cctFromRgb(false), | ||||
|       // semi-private (just obscured) used in effect functions through macros | ||||
| @@ -733,7 +738,7 @@ class WS2812FX {  // 96 bytes | ||||
|       _transitionDur(750), | ||||
|       _targetFps(WLED_FPS), | ||||
|       _frametime(FRAMETIME_FIXED), | ||||
|       _cumulativeFps(2), | ||||
|       _cumulativeFps(50 << FPS_CALC_SHIFT), | ||||
|       _isServicing(false), | ||||
|       _isOffRefreshRequired(false), | ||||
|       _hasWhiteChannel(false), | ||||
| @@ -788,7 +793,8 @@ class WS2812FX {  // 96 bytes | ||||
|       setTargetFps(uint8_t fps), | ||||
|       setupEffectData();                          // add default effects to the list; defined in FX.cpp | ||||
|  | ||||
|     inline void restartRuntime()          { for (Segment &seg : _segments) seg.markForReset(); } | ||||
|     inline void resetTimebase()           { timebase = 0UL - millis(); } | ||||
|     inline void restartRuntime()          { for (Segment &seg : _segments) { seg.markForReset().resetIfRequired(); } } | ||||
|     inline void setTransitionMode(bool t) { for (Segment &seg : _segments) seg.startTransition(t ? _transitionDur : 0); } | ||||
|     inline void setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0)    { setColor(slot, RGBW32(r,g,b,w)); } | ||||
|     inline void setPixelColor(unsigned n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); } | ||||
| @@ -844,10 +850,8 @@ class WS2812FX {  // 96 bytes | ||||
|     inline uint16_t getLength() const       { return _length; }           // returns actual amount of LEDs on a strip (2D matrix may have less LEDs than W*H) | ||||
|     inline uint16_t getTransition() const   { return _transitionDur; }    // returns currently set transition time (in ms) | ||||
|  | ||||
|     uint32_t | ||||
|       now, | ||||
|       timebase, | ||||
|       getPixelColor(uint16_t) const; | ||||
|     unsigned long now, timebase; | ||||
|     uint32_t getPixelColor(unsigned) const; | ||||
|  | ||||
|     inline uint32_t getLastShow() const       { return _lastShow; }           // returns millis() timestamp of last strip.show() call | ||||
|     inline uint32_t segColor(uint8_t i) const { return _colors_t[i]; }        // returns currently valid color (for slot i) AKA SEGCOLOR(); may be blended between two colors while in transition | ||||
|   | ||||
| @@ -1,24 +1,9 @@ | ||||
| /* | ||||
|   FX_2Dfcn.cpp contains all 2D utility functions | ||||
|  | ||||
|   LICENSE | ||||
|   The MIT License (MIT) | ||||
|   Copyright (c) 2022  Blaz Kristan (https://blaz.at/home) | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   in the Software without restriction, including without limitation the rights | ||||
|   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|   copies of the Software, and to permit persons to whom the Software is | ||||
|   furnished to do so, subject to the following conditions: | ||||
|   The above copyright notice and this permission notice shall be included in | ||||
|   all copies or substantial portions of the Software. | ||||
|   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|   THE SOFTWARE. | ||||
|   Licensed under the EUPL v. 1.2 or later | ||||
|   Adapted from code originally licensed under the MIT license | ||||
|  | ||||
|   Parts of the code adapted from WLED Sound Reactive | ||||
| */ | ||||
| @@ -171,7 +156,7 @@ uint16_t IRAM_ATTR_YN Segment::XY(int x, int y) | ||||
| void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) | ||||
| { | ||||
|   if (!isActive()) return; // not active | ||||
|   if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return;  // if pixel would fall out of virtual segment just exit | ||||
|   if ((unsigned)x >= virtualWidth() || (unsigned)y >= virtualHeight() || x<0 || y<0) return;  // if pixel would fall out of virtual segment just exit | ||||
|  | ||||
|   uint8_t _bri_t = currentBri(); | ||||
|   if (_bri_t < 255) { | ||||
| @@ -266,7 +251,7 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa) | ||||
| // returns RGBW values of pixel | ||||
| uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const { | ||||
|   if (!isActive()) return 0; // not active | ||||
|   if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return 0;  // if pixel would fall out of virtual segment just exit | ||||
|   if ((unsigned)x >= virtualWidth() || (unsigned)y >= virtualHeight() || x<0 || y<0) return 0;  // if pixel would fall out of virtual segment just exit | ||||
|   if (reverse  ) x = virtualWidth()  - x - 1; | ||||
|   if (reverse_y) y = virtualHeight() - y - 1; | ||||
|   if (transpose) { std::swap(x,y); } // swap X & Y if segment transposed | ||||
|   | ||||
| @@ -2,24 +2,10 @@ | ||||
|   WS2812FX_fcn.cpp contains all utility functions | ||||
|   Harm Aldick - 2016 | ||||
|   www.aldick.org | ||||
|   LICENSE | ||||
|   The MIT License (MIT) | ||||
|  | ||||
|   Copyright (c) 2016  Harm Aldick | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   in the Software without restriction, including without limitation the rights | ||||
|   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|   copies of the Software, and to permit persons to whom the Software is | ||||
|   furnished to do so, subject to the following conditions: | ||||
|   The above copyright notice and this permission notice shall be included in | ||||
|   all copies or substantial portions of the Software. | ||||
|   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|   THE SOFTWARE. | ||||
|   Licensed under the EUPL v. 1.2 or later | ||||
|   Adapted from code originally licensed under the MIT license | ||||
|  | ||||
|   Modified heavily for WLED | ||||
| */ | ||||
| @@ -523,46 +509,53 @@ void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t | ||||
| } | ||||
|  | ||||
|  | ||||
| bool Segment::setColor(uint8_t slot, uint32_t c) { //returns true if changed | ||||
|   if (slot >= NUM_COLORS || c == colors[slot]) return false; | ||||
| Segment &Segment::setColor(uint8_t slot, uint32_t c) { | ||||
|   if (slot >= NUM_COLORS || c == colors[slot]) return *this; | ||||
|   if (!_isRGB && !_hasW) { | ||||
|     if (slot == 0 && c == BLACK) return false; // on/off segment cannot have primary color black | ||||
|     if (slot == 1 && c != BLACK) return false; // on/off segment cannot have secondary color non black | ||||
|     if (slot == 0 && c == BLACK) return *this; // on/off segment cannot have primary color black | ||||
|     if (slot == 1 && c != BLACK) return *this; // on/off segment cannot have secondary color non black | ||||
|   } | ||||
|   if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change | ||||
|   colors[slot] = c; | ||||
|   stateChanged = true; // send UDP/WS broadcast | ||||
|   return true; | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| void Segment::setCCT(uint16_t k) { | ||||
| Segment &Segment::setCCT(uint16_t k) { | ||||
|   if (k > 255) { //kelvin value, convert to 0-255 | ||||
|     if (k < 1900)  k = 1900; | ||||
|     if (k > 10091) k = 10091; | ||||
|     k = (k - 1900) >> 5; | ||||
|   } | ||||
|   if (cct == k) return; | ||||
|   if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change | ||||
|   cct = k; | ||||
|   stateChanged = true; // send UDP/WS broadcast | ||||
|   if (cct != k) { | ||||
|     //DEBUGFX_PRINTF_P(PSTR("- Starting CCT transition: %d\n"), k); | ||||
|     startTransition(strip.getTransition()); // start transition prior to change | ||||
|     cct = k; | ||||
|     stateChanged = true; // send UDP/WS broadcast | ||||
|   } | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| void Segment::setOpacity(uint8_t o) { | ||||
|   if (opacity == o) return; | ||||
|   if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change | ||||
|   opacity = o; | ||||
|   stateChanged = true; // send UDP/WS broadcast | ||||
| Segment &Segment::setOpacity(uint8_t o) { | ||||
|   if (opacity != o) { | ||||
|     //DEBUGFX_PRINTF_P(PSTR("- Starting opacity transition: %d\n"), o); | ||||
|     startTransition(strip.getTransition()); // start transition prior to change | ||||
|     opacity = o; | ||||
|     stateChanged = true; // send UDP/WS broadcast | ||||
|   } | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| void Segment::setOption(uint8_t n, bool val) { | ||||
| Segment &Segment::setOption(uint8_t n, bool val) { | ||||
|   bool prevOn = on; | ||||
|   if (fadeTransition && n == SEG_OPTION_ON && val != prevOn) startTransition(strip.getTransition()); // start transition prior to change | ||||
|   if (val) options |=   0x01 << n; | ||||
|   else     options &= ~(0x01 << n); | ||||
|   if (!(n == SEG_OPTION_SELECTED || n == SEG_OPTION_RESET)) stateChanged = true; // send UDP/WS broadcast | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| void Segment::setMode(uint8_t fx, bool loadDefaults) { | ||||
| Segment &Segment::setMode(uint8_t fx, bool loadDefaults) { | ||||
|   // skip reserved | ||||
|   while (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4) == 0) fx++; | ||||
|   if (fx >= strip.getModeCount()) fx = 0; // set solid mode | ||||
| @@ -594,9 +587,10 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) { | ||||
|     markForReset(); | ||||
|     stateChanged = true; // send UDP/WS broadcast | ||||
|   } | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| void Segment::setPalette(uint8_t pal) { | ||||
| Segment &Segment::setPalette(uint8_t pal) { | ||||
|   if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes | ||||
|   if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // custom palettes | ||||
|   if (pal != palette) { | ||||
| @@ -604,37 +598,24 @@ void Segment::setPalette(uint8_t pal) { | ||||
|     palette = pal; | ||||
|     stateChanged = true; // send UDP/WS broadcast | ||||
|   } | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| // 2D matrix | ||||
| uint16_t IRAM_ATTR Segment::virtualWidth() const { | ||||
| unsigned IRAM_ATTR Segment::virtualWidth() const { | ||||
|   unsigned groupLen = groupLength(); | ||||
|   unsigned vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen; | ||||
|   if (mirror) vWidth = (vWidth + 1) /2;  // divide by 2 if mirror, leave at least a single LED | ||||
|   return vWidth; | ||||
| } | ||||
|  | ||||
| uint16_t IRAM_ATTR Segment::virtualHeight() const { | ||||
| unsigned IRAM_ATTR Segment::virtualHeight() const { | ||||
|   unsigned groupLen = groupLength(); | ||||
|   unsigned vHeight = ((transpose ? width() : height()) + groupLen - 1) / groupLen; | ||||
|   if (mirror_y) vHeight = (vHeight + 1) /2;  // divide by 2 if mirror, leave at least a single LED | ||||
|   return vHeight; | ||||
| } | ||||
|  | ||||
| uint16_t IRAM_ATTR_YN Segment::nrOfVStrips() const { | ||||
|   unsigned vLen = 1; | ||||
| #ifndef WLED_DISABLE_2D | ||||
|   if (is2D()) { | ||||
|     switch (map1D2D) { | ||||
|       case M12_pBar: | ||||
|         vLen = virtualWidth(); | ||||
|         break; | ||||
|     } | ||||
|   } | ||||
| #endif | ||||
|   return vLen; | ||||
| } | ||||
|  | ||||
| // Constants for mapping mode "Pinwheel" | ||||
| #ifndef WLED_DISABLE_2D | ||||
| constexpr int Pinwheel_Steps_Small = 72;       // no holes up to 16x16 | ||||
| @@ -1201,10 +1182,7 @@ uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_ | ||||
| //do not call this method from system context (network callback) | ||||
| void WS2812FX::finalizeInit() { | ||||
|   //reset segment runtimes | ||||
|   for (segment &seg : _segments) { | ||||
|     seg.markForReset(); | ||||
|     seg.resetIfRequired(); | ||||
|   } | ||||
|   restartRuntime(); | ||||
|  | ||||
|   // for the lack of better place enumerate ledmaps here | ||||
|   // if we do it in json.cpp (serializeInfo()) we are getting flashes on LEDs | ||||
| @@ -1308,14 +1286,9 @@ void WS2812FX::finalizeInit() { | ||||
|     _isOffRefreshRequired |= bus->isOffRefreshRequired() && !bus->isPWM(); // use refresh bit for phase shift with analog | ||||
|     unsigned busEnd = bus->getStart() + bus->getLength(); | ||||
|     if (busEnd > _length) _length = busEnd; | ||||
|     #ifdef ESP8266 | ||||
|     // why do we need to reinitialise GPIO3??? | ||||
|     //if (!bus->isDigital() || bus->is2Pin()) continue; | ||||
|     //uint8_t pins[5]; | ||||
|     //if (!bus->getPins(pins)) continue; | ||||
|     //BusDigital* bd = static_cast<BusDigital*>(bus); | ||||
|     //if (pins[0] == 3) bd->reinit(); | ||||
|     #endif | ||||
|  | ||||
|     // This must be done after all buses have been created, as some kinds (parallel I2S) interact | ||||
|     bus->begin(); | ||||
|   } | ||||
|  | ||||
|   Segment::maxWidth  = _length; | ||||
| @@ -1351,7 +1324,7 @@ void WS2812FX::service() { | ||||
|     if (nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC)) | ||||
|     { | ||||
|       doShow = true; | ||||
|       unsigned delay = FRAMETIME; | ||||
|       unsigned frameDelay = FRAMETIME; | ||||
|  | ||||
|       if (!seg.freeze) { //only run effect function if not frozen | ||||
|         int oldCCT = BusManager::getSegmentCCT(); // store original CCT value (actually it is not Segment based) | ||||
| @@ -1371,7 +1344,7 @@ void WS2812FX::service() { | ||||
|         // overwritten by later effect. To enable seamless blending for every effect, additional LED buffer | ||||
|         // would need to be allocated for each effect and then blended together for each pixel. | ||||
|         [[maybe_unused]] uint8_t tmpMode = seg.currentMode();  // this will return old mode while in transition | ||||
|         delay = (*_mode[seg.mode])();         // run new/current mode | ||||
|         frameDelay = (*_mode[seg.mode])();         // run new/current mode | ||||
| #ifndef WLED_DISABLE_MODE_BLEND | ||||
|         if (modeBlending && seg.mode != tmpMode) { | ||||
|           Segment::tmpsegd_t _tmpSegData; | ||||
| @@ -1380,16 +1353,16 @@ void WS2812FX::service() { | ||||
|           _virtualSegmentLength = seg.virtualLength(); // update SEGLEN (mapping may have changed) | ||||
|           unsigned d2 = (*_mode[tmpMode])();  // run old mode | ||||
|           seg.restoreSegenv(_tmpSegData);     // restore mode state (will also update transitional state) | ||||
|           delay = MIN(delay,d2);              // use shortest delay | ||||
|           frameDelay = min(frameDelay,d2);              // use shortest delay | ||||
|           Segment::modeBlend(false);          // unset semaphore | ||||
|         } | ||||
| #endif | ||||
|         seg.call++; | ||||
|         if (seg.isInTransition() && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition | ||||
|         if (seg.isInTransition() && frameDelay > FRAMETIME) frameDelay = FRAMETIME; // force faster updates during transition | ||||
|         BusManager::setSegmentCCT(oldCCT); // restore old CCT for ABL adjustments | ||||
|       } | ||||
|  | ||||
|       seg.next_time = nowUp + delay; | ||||
|       seg.next_time = nowUp + frameDelay; | ||||
|     } | ||||
|     _segment_index++; | ||||
|   } | ||||
| @@ -1416,7 +1389,7 @@ void IRAM_ATTR WS2812FX::setPixelColor(unsigned i, uint32_t col) { | ||||
|   BusManager::setPixelColor(i, col); | ||||
| } | ||||
|  | ||||
| uint32_t IRAM_ATTR WS2812FX::getPixelColor(uint16_t i) const { | ||||
| uint32_t IRAM_ATTR WS2812FX::getPixelColor(unsigned i) const { | ||||
|   i = getMappedPixelIndex(i); | ||||
|   if (i >= _length) return 0; | ||||
|   return BusManager::getPixelColor(i); | ||||
| @@ -1434,10 +1407,12 @@ void WS2812FX::show() { | ||||
|  | ||||
|   unsigned long showNow = millis(); | ||||
|   size_t diff = showNow - _lastShow; | ||||
|   size_t fpsCurr = 200; | ||||
|   if (diff > 0) fpsCurr = 1000 / diff; | ||||
|   _cumulativeFps = (3 * _cumulativeFps + fpsCurr +2) >> 2;   // "+2" for proper rounding (2/4 = 0.5) | ||||
|   _lastShow = showNow; | ||||
|  | ||||
|   if (diff > 0) { // skip calculation if no time has passed | ||||
|     size_t fpsCurr = (1000 << FPS_CALC_SHIFT) / diff; // fixed point math | ||||
|     _cumulativeFps = (FPS_CALC_AVG * _cumulativeFps + fpsCurr + FPS_CALC_AVG / 2) / (FPS_CALC_AVG + 1);   // "+FPS_CALC_AVG/2" for proper rounding | ||||
|     _lastShow = showNow; | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -1454,7 +1429,7 @@ bool WS2812FX::isUpdating() const { | ||||
|  */ | ||||
| uint16_t WS2812FX::getFps() const { | ||||
|   if (millis() - _lastShow > 2000) return 0; | ||||
|   return _cumulativeFps +1; | ||||
|   return (FPS_MULTIPLIER * _cumulativeFps) >> FPS_CALC_SHIFT; // _cumulativeFps is stored in fixed point | ||||
| } | ||||
|  | ||||
| void WS2812FX::setTargetFps(uint8_t fps) { | ||||
|   | ||||
| @@ -150,7 +150,7 @@ BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com) | ||||
|   //_buffering = bc.doubleBuffer; | ||||
|   uint16_t lenToCreate = bc.count; | ||||
|   if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(bc.count); // only needs a third of "RGB" LEDs for NeoPixelBus | ||||
|   _busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr, _frequencykHz); | ||||
|   _busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr); | ||||
|   _valid = (_busPtr != nullptr); | ||||
|   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], is2Pin(bc.type)?_pins[1]:255, _iType, _milliAmpsPerLed, _milliAmpsMax); | ||||
| } | ||||
| @@ -410,9 +410,9 @@ std::vector<LEDType> BusDigital::getLEDTypes() { | ||||
|   }; | ||||
| } | ||||
|  | ||||
| void BusDigital::reinit() { | ||||
| void BusDigital::begin() { | ||||
|   if (!_valid) return; | ||||
|   PolyBus::begin(_busPtr, _iType, _pins); | ||||
|   PolyBus::begin(_busPtr, _iType, _pins, _frequencykHz); | ||||
| } | ||||
|  | ||||
| void BusDigital::cleanup() { | ||||
| @@ -910,7 +910,7 @@ void BusManager::on() { | ||||
|       if (busses[i]->isDigital() && busses[i]->getPins(pins)) { | ||||
|         if (pins[0] == LED_BUILTIN || pins[1] == LED_BUILTIN) { | ||||
|           BusDigital *bus = static_cast<BusDigital*>(busses[i]); | ||||
|           bus->reinit(); | ||||
|           bus->begin(); | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|   | ||||
| @@ -79,6 +79,7 @@ class Bus { | ||||
|  | ||||
|     virtual ~Bus() {} //throw the bus under the bus | ||||
|  | ||||
|     virtual void     begin() {}; | ||||
|     virtual void     show() = 0; | ||||
|     virtual bool     canShow() const                          { return true; } | ||||
|     virtual void     setStatusPixel(uint32_t c)                {} | ||||
| @@ -213,7 +214,7 @@ class BusDigital : public Bus { | ||||
|     uint16_t getLEDCurrent() const override  { return _milliAmpsPerLed; } | ||||
|     uint16_t getUsedCurrent() const override { return _milliAmpsTotal; } | ||||
|     uint16_t getMaxCurrent() const override  { return _milliAmpsMax; } | ||||
|     void reinit(); | ||||
|     void begin() override; | ||||
|     void cleanup(); | ||||
|  | ||||
|     static std::vector<LEDType> getLEDTypes(); | ||||
|   | ||||
| @@ -336,7 +336,7 @@ class PolyBus { | ||||
|  | ||||
|   // initialize SPI bus speed for DotStar methods | ||||
|   template <class T> | ||||
|   static void beginDotStar(void* busPtr, int8_t sck, int8_t miso, int8_t mosi, int8_t ss, uint16_t clock_kHz = 0U) { | ||||
|   static void beginDotStar(void* busPtr, int8_t sck, int8_t miso, int8_t mosi, int8_t ss, uint16_t clock_kHz /* 0 == use default */) { | ||||
|     T dotStar_strip = static_cast<T>(busPtr); | ||||
|     #ifdef ESP8266 | ||||
|     dotStar_strip->Begin(); | ||||
| @@ -363,7 +363,7 @@ class PolyBus { | ||||
|     tm1914_strip->SetPixelSettings(NeoTm1914Settings());  //NeoTm1914_Mode_DinFdinAutoSwitch, NeoTm1914_Mode_DinOnly, NeoTm1914_Mode_FdinOnly  | ||||
|   } | ||||
|  | ||||
|   static void begin(void* busPtr, uint8_t busType, uint8_t* pins, uint16_t clock_kHz = 0U) { | ||||
|   static void begin(void* busPtr, uint8_t busType, uint8_t* pins, uint16_t clock_kHz /* only used by DotStar */) { | ||||
|     switch (busType) { | ||||
|       case I_NONE: break; | ||||
|     #ifdef ESP8266 | ||||
| @@ -480,7 +480,7 @@ class PolyBus { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   static void* create(uint8_t busType, uint8_t* pins, uint16_t len, uint8_t channel, uint16_t clock_kHz = 0U) { | ||||
|   static void* create(uint8_t busType, uint8_t* pins, uint16_t len, uint8_t channel) { | ||||
|     #if defined(ARDUINO_ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3)) | ||||
|     // NOTE: "channel" is only used on ESP32 (and its variants) for RMT channel allocation | ||||
|     // since 0.15.0-b3 I2S1 is favoured for classic ESP32 and moved to position 0 (channel 0) so we need to subtract 1 for correct RMT allocation | ||||
| @@ -597,7 +597,7 @@ class PolyBus { | ||||
|       case I_HS_P98_3: busPtr = new B_HS_P98_3(len, pins[1], pins[0]); break; | ||||
|       case I_SS_P98_3: busPtr = new B_SS_P98_3(len, pins[1], pins[0]); break; | ||||
|     } | ||||
|     begin(busPtr, busType, pins, clock_kHz); | ||||
|  | ||||
|     return busPtr; | ||||
|   } | ||||
|  | ||||
| @@ -766,47 +766,47 @@ class PolyBus { | ||||
|     #endif | ||||
|     #ifdef ARDUINO_ARCH_ESP32 | ||||
|       // RMT buses | ||||
|       case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_UCS_3: (static_cast<B_32_RN_UCS_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_FW6_5: (static_cast<B_32_RN_FW6_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_2805_5: (static_cast<B_32_RN_2805_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_TM1914_3: (static_cast<B_32_RN_TM1914_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_SM16825_5: (static_cast<B_32_RN_SM16825_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_NEO_3: return (static_cast<B_32_RN_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_400_3: return (static_cast<B_32_RN_400_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_TM1_4: return (static_cast<B_32_RN_TM1_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_TM2_3: return (static_cast<B_32_RN_TM2_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_UCS_3: return (static_cast<B_32_RN_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_APA106_3: return (static_cast<B_32_RN_APA106_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_FW6_5: return (static_cast<B_32_RN_FW6_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_2805_5: return (static_cast<B_32_RN_2805_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_TM1914_3: return (static_cast<B_32_RN_TM1914_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_RN_SM16825_5: return (static_cast<B_32_RN_SM16825_5*>(busPtr))->CanShow(); break; | ||||
|       // I2S1 bus or paralell buses | ||||
|       #ifndef WLED_NO_I2S1_PIXELBUS | ||||
|       case I_32_I1_NEO_3: if (useParallelI2S) (static_cast<B_32_I1_NEO_3P*>(busPtr))->CanShow(); else (static_cast<B_32_I1_NEO_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_NEO_4: if (useParallelI2S) (static_cast<B_32_I1_NEO_4P*>(busPtr))->CanShow(); else (static_cast<B_32_I1_NEO_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_400_3: if (useParallelI2S) (static_cast<B_32_I1_400_3P*>(busPtr))->CanShow(); else (static_cast<B_32_I1_400_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_TM1_4: if (useParallelI2S) (static_cast<B_32_I1_TM1_4P*>(busPtr))->CanShow(); else (static_cast<B_32_I1_TM1_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_TM2_3: if (useParallelI2S) (static_cast<B_32_I1_TM2_3P*>(busPtr))->CanShow(); else (static_cast<B_32_I1_TM2_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_UCS_3: if (useParallelI2S) (static_cast<B_32_I1_UCS_3P*>(busPtr))->CanShow(); else (static_cast<B_32_I1_UCS_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_UCS_4: if (useParallelI2S) (static_cast<B_32_I1_UCS_4P*>(busPtr))->CanShow(); else (static_cast<B_32_I1_UCS_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_APA106_3: if (useParallelI2S) (static_cast<B_32_I1_APA106_3P*>(busPtr))->CanShow(); else (static_cast<B_32_I1_APA106_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_FW6_5: if (useParallelI2S) (static_cast<B_32_I1_FW6_5P*>(busPtr))->CanShow(); else (static_cast<B_32_I1_FW6_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_2805_5: if (useParallelI2S) (static_cast<B_32_I1_2805_5P*>(busPtr))->CanShow(); else (static_cast<B_32_I1_2805_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_TM1914_3: if (useParallelI2S) (static_cast<B_32_I1_TM1914_3P*>(busPtr))->CanShow(); else (static_cast<B_32_I1_TM1914_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_SM16825_5: if (useParallelI2S) (static_cast<B_32_I1_SM16825_5P*>(busPtr))->CanShow(); else (static_cast<B_32_I1_SM16825_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_NEO_3: if (useParallelI2S) return (static_cast<B_32_I1_NEO_3P*>(busPtr))->CanShow(); else return (static_cast<B_32_I1_NEO_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_NEO_4: if (useParallelI2S) return (static_cast<B_32_I1_NEO_4P*>(busPtr))->CanShow(); else return (static_cast<B_32_I1_NEO_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_400_3: if (useParallelI2S) return (static_cast<B_32_I1_400_3P*>(busPtr))->CanShow(); else return (static_cast<B_32_I1_400_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_TM1_4: if (useParallelI2S) return (static_cast<B_32_I1_TM1_4P*>(busPtr))->CanShow(); else return (static_cast<B_32_I1_TM1_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_TM2_3: if (useParallelI2S) return (static_cast<B_32_I1_TM2_3P*>(busPtr))->CanShow(); else return (static_cast<B_32_I1_TM2_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_UCS_3: if (useParallelI2S) return (static_cast<B_32_I1_UCS_3P*>(busPtr))->CanShow(); else return (static_cast<B_32_I1_UCS_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_UCS_4: if (useParallelI2S) return (static_cast<B_32_I1_UCS_4P*>(busPtr))->CanShow(); else return (static_cast<B_32_I1_UCS_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_APA106_3: if (useParallelI2S) return (static_cast<B_32_I1_APA106_3P*>(busPtr))->CanShow(); else return (static_cast<B_32_I1_APA106_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_FW6_5: if (useParallelI2S) return (static_cast<B_32_I1_FW6_5P*>(busPtr))->CanShow(); else return (static_cast<B_32_I1_FW6_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_2805_5: if (useParallelI2S) return (static_cast<B_32_I1_2805_5P*>(busPtr))->CanShow(); else return (static_cast<B_32_I1_2805_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_TM1914_3: if (useParallelI2S) return (static_cast<B_32_I1_TM1914_3P*>(busPtr))->CanShow(); else return (static_cast<B_32_I1_TM1914_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I1_SM16825_5: if (useParallelI2S) return (static_cast<B_32_I1_SM16825_5P*>(busPtr))->CanShow(); else return (static_cast<B_32_I1_SM16825_5*>(busPtr))->CanShow(); break; | ||||
|       #endif | ||||
|       // I2S0 bus | ||||
|       #ifndef WLED_NO_I2S0_PIXELBUS | ||||
|       case I_32_I0_NEO_3: (static_cast<B_32_I0_NEO_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_TM1_4: (static_cast<B_32_I0_TM1_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_TM2_3: (static_cast<B_32_I0_TM2_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_UCS_3: (static_cast<B_32_I0_UCS_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_FW6_5: (static_cast<B_32_I0_FW6_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_2805_5: (static_cast<B_32_I0_2805_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_TM1914_3: (static_cast<B_32_I0_TM1914_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_SM16825_5: (static_cast<B_32_I0_SM16825_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_NEO_3: return (static_cast<B_32_I0_NEO_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_NEO_4: return (static_cast<B_32_I0_NEO_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_400_3: return (static_cast<B_32_I0_400_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_TM1_4: return (static_cast<B_32_I0_TM1_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_TM2_3: return (static_cast<B_32_I0_TM2_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_UCS_3: return (static_cast<B_32_I0_UCS_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_UCS_4: return (static_cast<B_32_I0_UCS_4*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_APA106_3: return (static_cast<B_32_I0_APA106_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_FW6_5: return (static_cast<B_32_I0_FW6_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_2805_5: return (static_cast<B_32_I0_2805_5*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_TM1914_3: return (static_cast<B_32_I0_TM1914_3*>(busPtr))->CanShow(); break; | ||||
|       case I_32_I0_SM16825_5: return (static_cast<B_32_I0_SM16825_5*>(busPtr))->CanShow(); break; | ||||
|       #endif | ||||
|     #endif | ||||
|       case I_HS_DOT_3: return (static_cast<B_HS_DOT_3*>(busPtr))->CanShow(); break; | ||||
|   | ||||
| @@ -215,6 +215,7 @@ void handleAnalog(uint8_t b) | ||||
|         briLast = bri; | ||||
|         bri = 0; | ||||
|       } else { | ||||
|         if (bri == 0) strip.restartRuntime(); | ||||
|         bri = aRead; | ||||
|       } | ||||
|     } else if (macroDoublePress[b] == 249) { | ||||
|   | ||||
| @@ -53,7 +53,7 @@ | ||||
|   #else | ||||
|     #define WLED_MAX_ANALOG_CHANNELS (LEDC_CHANNEL_MAX*LEDC_SPEED_MODE_MAX) | ||||
|     #if defined(CONFIG_IDF_TARGET_ESP32C3)    // 2 RMT, 6 LEDC, only has 1 I2S but NPB does not support it ATM | ||||
|       #define WLED_MAX_BUSSES 4               // will allow 2 digital & 2 analog RGB | ||||
|       #define WLED_MAX_BUSSES 6               // will allow 2 digital & 2 analog RGB or 6 PWM white | ||||
|       #define WLED_MAX_DIGITAL_CHANNELS 2 | ||||
|       //#define WLED_MAX_ANALOG_CHANNELS 6 | ||||
|       #define WLED_MIN_VIRTUAL_BUSSES 3 | ||||
|   | ||||
| @@ -144,7 +144,7 @@ button { | ||||
| } | ||||
|  | ||||
| .huge { | ||||
| 	font-size: 42px; | ||||
| 	font-size: 60px !important; | ||||
| } | ||||
|  | ||||
| .segt, .plentry TABLE { | ||||
| @@ -584,6 +584,10 @@ button { | ||||
| 	z-index: 3; | ||||
| } | ||||
|  | ||||
| #rover .ibtn { | ||||
| 	margin: 5px; | ||||
| } | ||||
|  | ||||
| #ndlt { | ||||
| 	margin: 12px 0; | ||||
| } | ||||
| @@ -624,7 +628,7 @@ button { | ||||
|   padding-bottom: 8px; | ||||
| } | ||||
|  | ||||
| .infobtn { | ||||
| #info .ibtn { | ||||
| 	margin: 5px; | ||||
| } | ||||
|  | ||||
| @@ -848,7 +852,7 @@ input[type=range]::-moz-range-thumb { | ||||
| 	width: 135px; | ||||
| } | ||||
|  | ||||
| #nodes .infobtn { | ||||
| #nodes .ibtn { | ||||
| 	margin: 0; | ||||
| } | ||||
|  | ||||
| @@ -1036,7 +1040,7 @@ textarea { | ||||
|  | ||||
| .segname .flr, .pname .flr { | ||||
| 	transform: rotate(0deg); | ||||
| 	right: -6px; | ||||
| 	/*right: -6px;*/ | ||||
| } | ||||
|  | ||||
| /* segment power wrapper */ | ||||
| @@ -1331,6 +1335,11 @@ TD .checkmark, TD .radiomark { | ||||
| 	box-shadow: 0 0 10px 4px var(--c-1); | ||||
| } | ||||
|  | ||||
| .lstI .flr:hover { | ||||
|     background: var(--c-6); | ||||
|     border-radius: 100%; | ||||
| } | ||||
|  | ||||
| #pcont .selected:not([class*="expanded"]) { | ||||
| 	bottom: 52px; | ||||
| 	top: 42px; | ||||
| @@ -1524,7 +1533,7 @@ dialog { | ||||
| 	#info table .btn, #nodes table .btn { | ||||
| 		width: 200px; | ||||
| 	} | ||||
| 	#info .infobtn, #nodes .infobtn { | ||||
| 	#info .ibtn, #nodes .ibtn { | ||||
| 		width: 145px; | ||||
| 	} | ||||
| 	#info div, #nodes div, #nodes a.btn { | ||||
|   | ||||
| @@ -304,10 +304,10 @@ | ||||
| 	</div> | ||||
| 	<div id="kv">Loading...</div><br> | ||||
| 	<div> | ||||
| 		<button class="btn infobtn" onclick="requestJson()">Refresh</button> | ||||
| 		<button class="btn infobtn" onclick="toggleNodes()">Instance List</button> | ||||
| 		<button class="btn infobtn" onclick="window.open(getURL('/update'),'_self');">Update WLED</button> | ||||
| 		<button class="btn infobtn" id="resetbtn" onclick="cnfReset()">Reboot WLED</button> | ||||
| 		<button class="btn ibtn" onclick="requestJson()">Refresh</button> | ||||
| 		<button class="btn ibtn" onclick="toggleNodes()">Instance List</button> | ||||
| 		<button class="btn ibtn" onclick="window.open(getURL('/update'),'_self');">Update WLED</button> | ||||
| 		<button class="btn ibtn" id="resetbtn" onclick="cnfReset()">Reboot WLED</button> | ||||
| 	</div> | ||||
| 	<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> | ||||
| @@ -318,7 +318,7 @@ | ||||
| 	<div id="ndlt">WLED instances</div> | ||||
| 	<div id="kn">Loading...</div> | ||||
| 	<div style="position:sticky;bottom:0;"> | ||||
| 		<button class="btn infobtn" onclick="loadNodes()">Refresh</button> | ||||
| 		<button class="btn ibtn" onclick="loadNodes()">Refresh</button> | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| @@ -331,8 +331,8 @@ | ||||
| 	<div id="lv">?</div><br><br> | ||||
| 	To use built-in effects, use an override button below.<br> | ||||
| 	You can return to realtime mode by pressing the star in the top left corner.<br> | ||||
| 	<button class="btn" onclick="setLor(1)">Override once</button> | ||||
| 	<button class="btn" onclick="setLor(2)">Override until reboot</button><br> | ||||
| 	<button class="btn ibtn" onclick="setLor(1)">Override once</button> | ||||
| 	<button class="btn ibtn" onclick="setLor(2)">Override until reboot</button><br> | ||||
| 	<span class="h">For best performance, it is recommended to turn off the streaming source when not in use.</span> | ||||
| </div> | ||||
|  | ||||
|   | ||||
| @@ -2827,7 +2827,7 @@ function search(field, listId = null) { | ||||
|  | ||||
| 	// restore default preset sorting if no search term is entered | ||||
| 	if (!search) { | ||||
| 		if (listId === 'pcont')   { populatePresets(); return; } | ||||
| 		if (listId === 'pcont') { populatePresets(); return; } | ||||
| 		if (listId === 'pallist') { | ||||
| 			let id = parseInt(d.querySelector('#pallist input[name="palette"]:checked').value); // preserve selected palette | ||||
| 			populatePalettes(); | ||||
| @@ -2846,12 +2846,16 @@ function search(field, listId = null) { | ||||
|  | ||||
| 	// filter list items but leave (Default & Solid) always visible | ||||
| 	const listItems = gId(listId).querySelectorAll('.lstI'); | ||||
| 	listItems.forEach((listItem,i)=>{ | ||||
| 		if (listId!=='pcont' && i===0) return; | ||||
| 	listItems.forEach((listItem, i) => { | ||||
| 		if (listId !== 'pcont' && i === 0) return; | ||||
| 		const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase(); | ||||
| 		const searchIndex = listItemName.indexOf(field.value.toUpperCase()); | ||||
| 		listItem.style.display = (searchIndex < 0) ? 'none' : ''; | ||||
| 		listItem.dataset.searchIndex = searchIndex; | ||||
| 		if (searchIndex < 0) { | ||||
| 			listItem.dataset.searchIndex = Number.MAX_SAFE_INTEGER; | ||||
| 		} else { | ||||
| 			listItem.dataset.searchIndex = searchIndex; | ||||
| 		} | ||||
| 		listItem.style.display = (searchIndex < 0) && !listItem.classList.contains("selected") ? 'none' : ''; | ||||
| 	}); | ||||
|  | ||||
| 	// sort list items by search index and name | ||||
| @@ -2920,11 +2924,11 @@ function filterFx() { | ||||
| 	inputField.value = ''; | ||||
| 	inputField.focus(); | ||||
| 	clean(inputField.nextElementSibling); | ||||
| 	gId("fxlist").querySelectorAll('.lstI').forEach((listItem,i) => { | ||||
| 	gId("fxlist").querySelectorAll('.lstI').forEach((listItem, i) => { | ||||
| 		const listItemName = listItem.querySelector('.lstIname').innerText; | ||||
| 		let hide = false; | ||||
| 		gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { if (e.checked && !listItemName.includes(e.dataset.flt)) hide = i>0 /*true*/; }); | ||||
| 		listItem.style.display = hide ? 'none' : ''; | ||||
| 		gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { if (e.checked && !listItemName.includes(e.dataset.flt)) hide = i > 0 /*true*/; }); | ||||
| 		listItem.style.display = hide && !listItem.classList.contains("selected") ? 'none' : ''; | ||||
| 	}); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -42,15 +42,14 @@ | ||||
| 			if (loc) d.Sf.action = getURL('/settings/leds'); | ||||
| 		} | ||||
| 		function bLimits(b,v,p,m,l,o=5,d=2,a=6) { | ||||
| 			// maxB - max buses (can be changed if using ESP32 parallel I2S) | ||||
| 			// maxD - max digital channels (can be changed if using ESP32 parallel I2S) | ||||
| 			// maxA - max analog channels | ||||
| 			// maxV - min virtual buses | ||||
| 			// maxPB - max LEDs per bus | ||||
| 			// maxM - max LED memory | ||||
| 			// maxL - max LEDs (will serve to determine ESP >1664 == ESP32) | ||||
| 			// maxCO - max Color Order mappings | ||||
| 			oMaxB = maxB = b; maxD = d, maxA = a, maxV = v; maxM = m; maxPB = p; maxL = l; maxCO = o; | ||||
| 			oMaxB = maxB = b; // maxB - max buses (can be changed if using ESP32 parallel I2S) | ||||
| 			maxD  = d; // maxD - max digital channels (can be changed if using ESP32 parallel I2S) | ||||
| 			maxA  = a; // maxA - max analog channels | ||||
| 			maxV  = v; // maxV - min virtual buses | ||||
| 			maxPB = p; // maxPB - max LEDs per bus | ||||
| 			maxM  = m; // maxM - max LED memory | ||||
| 			maxL  = l; // maxL - max LEDs (will serve to determine ESP >1664 == ESP32) | ||||
| 			maxCO = o; // maxCO - max Color Order mappings | ||||
| 		} | ||||
| 		function pinsOK() { | ||||
| 			var ok = true; | ||||
| @@ -119,7 +118,12 @@ | ||||
| 			var en = d.Sf.ABL.checked; | ||||
| 			gId('abl').style.display = (en) ? 'inline':'none'; | ||||
| 			gId('psu2').style.display = (en) ? 'inline':'none'; | ||||
| 			if (!en) d.Sf.PPL.checked = false; | ||||
| 			if (!en) { | ||||
| 				// limiter disabled | ||||
| 				d.Sf.PPL.checked = false; | ||||
| //				d.Sf.querySelectorAll("#mLC select[name^=LAsel]").forEach((e)=>{e.selectedIndex = 0;}); // select default LED mA | ||||
| //				d.Sf.querySelectorAll("#mLC input[name^=LA]").forEach((e)=>{e.min = 0; e.value = 0;}); // set min & value to 0 | ||||
| 			} | ||||
| 			UI(); | ||||
| 		} | ||||
| 		// enable per port limiter and calculate current | ||||
| @@ -132,46 +136,51 @@ | ||||
| 			d.Sf.MA.min = abl && !ppl ? 250 : 0; | ||||
| 			gId("psuMA").style.display = ppl ? 'none' : 'inline'; | ||||
| 			gId("ppldis").style.display = ppl ? 'inline' : 'none'; | ||||
| 			// set PPL minimum value and clear actual PPL limit if ABL disabled | ||||
| 			// set PPL minimum value and clear actual PPL limit if ABL is disabled | ||||
| 			d.Sf.querySelectorAll("#mLC input[name^=MA]").forEach((i,x)=>{ | ||||
| 				var n = String.fromCharCode((x<10?48:55)+x); | ||||
| 				gId("PSU"+n).style.display = ppl ? "inline" : "none"; | ||||
| 				const t = parseInt(d.Sf["LT"+n].value); // LED type SELECT | ||||
| 				const c = parseInt(d.Sf["LC"+n].value); //get LED count | ||||
| 				i.min = ppl && !(isVir(t) || isAna(t)) ? 250 : 0; | ||||
| 				if (!abl || isVir(t) || isAna(t)) i.value = 0; | ||||
| 				i.min = ppl && isDig(t) ? 250 : 0; | ||||
| 				if (!abl || !isDig(t)) i.value = 0; | ||||
| 				else if (ppl) sumMA += parseInt(i.value,10); | ||||
| 				else if (sDI) i.value = Math.round(parseInt(d.Sf.MA.value,10)*c/sDI); | ||||
| 			}); | ||||
| 			if (ppl) d.Sf.MA.value = sumMA; // populate UI ABL value if PPL used | ||||
| 		} | ||||
| 		// enable and update LED Amps | ||||
| 		function enLA(s,n) | ||||
| 		{ | ||||
| 			const abl = d.Sf.ABL.checked; | ||||
| 			const t = parseInt(d.Sf["LT"+n].value); // LED type SELECT | ||||
| 			gId('LAdis'+n).style.display = s.selectedIndex==5 ? "inline" : "none"; | ||||
| 			if (s.value!=="0") d.Sf["LA"+n].value = s.value; | ||||
| 			d.Sf["LA"+n].min = (isVir(t) || isAna(t)) ? 0 : 1; | ||||
| 			gId('LAdis'+n).style.display = s.selectedIndex==5 ? "inline" : "none"; // show/hide custom mA field | ||||
| 			if (s.value!=="0") d.Sf["LA"+n].value = s.value; // set value from select object | ||||
| 			d.Sf["LA"+n].min = (!isDig(t) || !abl) ? 0 : 1; // set minimum value for validation | ||||
| 		} | ||||
| 		function setABL() | ||||
| 		{ | ||||
| 			d.Sf.ABL.checked = parseInt(d.Sf.MA.value) > 0; | ||||
| 			let en = parseInt(d.Sf.MA.value) > 0; | ||||
| 			// check if ABL is enabled (max mA entered per output) | ||||
| 			d.Sf.querySelectorAll("#mLC input[name^=MA]").forEach((i,n)=>{ | ||||
| 				if (parseInt(i.value) > 0) d.Sf.ABL.checked = true; | ||||
| 				if (parseInt(i.value) > 0) en = true; | ||||
| 			}); | ||||
| 			d.Sf.ABL.checked = en; | ||||
| 			// select appropriate LED current | ||||
| 			d.Sf.querySelectorAll("#mLC select[name^=LAsel]").forEach((sel,x)=>{ | ||||
| 				sel.value = 0; // set custom | ||||
| 				var n = String.fromCharCode((x<10?48:55)+x); | ||||
| 				switch (parseInt(d.Sf["LA"+n].value)) { | ||||
| 					case 0: break; // disable ABL | ||||
| 					case 15: sel.value = 15; break; | ||||
| 					case 30: sel.value = 30; break; | ||||
| 					case 35: sel.value = 35; break; | ||||
| 					case 55: sel.value = 55; break; | ||||
| 					case 255: sel.value = 255; break; | ||||
| 				} | ||||
| 				enLA(sel,n); | ||||
| 				if (en) | ||||
| 					switch (parseInt(d.Sf["LA"+n].value)) { | ||||
| 						case 0: break; // disable ABL | ||||
| 						case 15: sel.value = 15; break; | ||||
| 						case 30: sel.value = 30; break; | ||||
| 						case 35: sel.value = 35; break; | ||||
| 						case 55: sel.value = 55; break; | ||||
| 						case 255: sel.value = 255; break; | ||||
| 					} | ||||
| 				else sel.value = 0; | ||||
| 				enLA(sel,n); // configure individual limiter | ||||
| 			}); | ||||
| 			enABL(); | ||||
| 			gId('m1').innerHTML = maxM; | ||||
| @@ -202,7 +211,7 @@ | ||||
| 			let gRGBW = false, memu = 0; | ||||
| 			let busMA = 0; | ||||
| 			let sLC = 0, sPC = 0, sDI = 0, maxLC = 0; | ||||
| 			const ablEN = d.Sf.ABL.checked; | ||||
| 			const abl = d.Sf.ABL.checked; | ||||
| 			maxB = oMaxB; // TODO make sure we start with all possible buses | ||||
| 			let setPinConfig = (n,t) => { | ||||
| 				let p0d = "GPIO:"; | ||||
| @@ -249,12 +258,12 @@ | ||||
| 				var t = parseInt(s.value); | ||||
| 				memu += getMem(t, n); // calc memory | ||||
| 				setPinConfig(n,t); | ||||
| 				gId("abl"+n).style.display = (!ablEN || isVir(t) || isAna(t)) ? "none" : "inline"; | ||||
| 				if (change) { | ||||
| 				gId("abl"+n).style.display = (!abl || !isDig(t)) ? "none" : "inline"; // show/hide individual ABL settings | ||||
| 				if (change) { // did we change LED type? | ||||
| 					gId("rf"+n).checked = (gId("rf"+n).checked || t == 31); // LEDs require data in off state (mandatory for TM1814) | ||||
| 					if (isAna(t)) d.Sf["LC"+n].value = 1;                   // for sanity change analog count just to 1 LED | ||||
| 					d.Sf["LA"+n].min = (isVir(t) || isAna(t)) ? 0 : 1; | ||||
| 					d.Sf["MA"+n].min = (isVir(t) || isAna(t)) ? 0 : 250; | ||||
| 					d.Sf["LA"+n].min = (!isDig(t) || !abl) ? 0 : 1;         // set minimum value for LED mA | ||||
| 					d.Sf["MA"+n].min = (!isDig(t)) ? 0 : 250;               // set minimum value for PSU mA | ||||
| 				} | ||||
| 				gId("rf"+n).onclick = mustR(t) ? (()=>{return false}) : (()=>{});           // prevent change change of "Refresh" checkmark when mandatory | ||||
| 				gRGBW |= hasW(t);                                                           // RGBW checkbox | ||||
| @@ -294,7 +303,7 @@ | ||||
| 						if (s+c > sLC) sLC = s+c; //update total count | ||||
| 						if (c > maxLC) maxLC = c; //max per output | ||||
| 						if (!isVir(t)) sPC += c; //virtual out busses do not count towards physical LEDs | ||||
| 						if (!(isVir(t) || isAna(t))) { | ||||
| 						if (isDig(t)) { | ||||
| 							sDI += c; // summarize digital LED count | ||||
| 							let maPL = parseInt(d.Sf["LA"+n].value); | ||||
| 							if (maPL == 255) maPL = 12; | ||||
|   | ||||
| @@ -60,8 +60,8 @@ | ||||
| 		<hr> | ||||
| 		<h3>Backup & Restore</h3> | ||||
| 		<div class="warn">⚠ Restoring presets/configuration will OVERWRITE your current presets/configuration.<br> | ||||
| 		Incorrect upload or configuration may require a factory reset or re-flashing of your ESP.</div> | ||||
| 		For security reasons, passwords are not backed up. | ||||
| 		Incorrect upload or configuration may require a factory reset or re-flashing of your ESP.<br> | ||||
| 		For security reasons, passwords are not backed up.</div> | ||||
| 		<a class="btn lnk" id="bckcfg" href="/presets.json" download="presets">Backup presets</a><br> | ||||
| 		<div>Restore presets<br><input type="file" name="data" accept=".json"> <button type="button" onclick="uploadFile(d.Sf.data,'/presets.json');">Upload</button><br></div><br> | ||||
| 		<a class="btn lnk" id="bckpresets" href="/cfg.json" download="cfg">Backup configuration</a><br> | ||||
| @@ -72,10 +72,10 @@ | ||||
| 		<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> | ||||
| 		(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">EUPL v1.2 license</a></i><br><br> | ||||
| 		Server message: <span class="sip"> Response error! </span><hr> | ||||
| 		<div id="toast"></div> | ||||
| 		<button type="button" onclick="B()">Back</button><button type="submit">Save</button> | ||||
| 	</form> | ||||
| </body> | ||||
| </html> | ||||
| </html> | ||||
|   | ||||
| @@ -156,6 +156,7 @@ | ||||
| 			<option value="20">AKST/AKDT (Anchorage)</option> | ||||
| 			<option value="21">MX-CST</option> | ||||
| 			<option value="22">PKT (Pakistan)</option> | ||||
| 			<option value="23">BRT (Brasília)</option> | ||||
| 		</select><br> | ||||
| 		UTC offset: <input name="UO" type="number" min="-65500" max="65500" required> seconds (max. 18 hours)<br> | ||||
| 		Current local time is <span class="times">unknown</span>.<br> | ||||
|   | ||||
| @@ -17,7 +17,8 @@ | ||||
| 	<h2>WLED Software Update</h2> | ||||
| 	<form method='POST' action='./update' id='uf' enctype='multipart/form-data' onsubmit="U()"> | ||||
| 		Installed version: <span class="sip">##VERSION##</span><br> | ||||
| 		Download the latest binary: <a href="https://github.com/Aircoookie/WLED/releases" target="_blank"> | ||||
| 		Download the latest binary: <a href="https://github.com/Aircoookie/WLED/releases" target="_blank"  | ||||
| 		style="vertical-align: text-bottom; display: inline-flex;"> | ||||
| 		<img src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square"></a><br> | ||||
| 		<input type='file' name='update' required><br> <!--should have accept='.bin', but it prevents file upload from android app--> | ||||
| 		<button type="submit">Update!</button><br> | ||||
|   | ||||
| @@ -169,7 +169,6 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient = 0); | ||||
| void setValuesFromSegment(uint8_t s); | ||||
| void setValuesFromMainSeg(); | ||||
| void setValuesFromFirstSelectedSeg(); | ||||
| void resetTimebase(); | ||||
| void toggleOnOff(); | ||||
| void applyBri(); | ||||
| void applyFinalBri(); | ||||
| @@ -324,6 +323,10 @@ class Usermod { | ||||
|   protected: | ||||
|     // Shim for oappend(), which used to exist in utils.cpp | ||||
|     template<typename T> static inline void oappend(const T& t) { oappend_shim->print(t); }; | ||||
| #ifdef ESP8266 | ||||
|     // Handle print(PSTR()) without crashing by detecting PROGMEM strings | ||||
|     static void oappend(const char* c) { if ((intptr_t) c >= 0x40000000) oappend_shim->print(FPSTR(c)); else oappend_shim->print(c); }; | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| class UsermodManager { | ||||
| @@ -386,6 +389,9 @@ uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxL | ||||
| int16_t extractModeDefaults(uint8_t mode, const char *segVar); | ||||
| void checkSettingsPIN(const char *pin); | ||||
| uint16_t crc16(const unsigned char* data_p, size_t length); | ||||
| uint16_t beatsin88_t(accum88 beats_per_minute_88, uint16_t lowest = 0, uint16_t highest = 65535, uint32_t timebase = 0, uint16_t phase_offset = 0); | ||||
| uint16_t beatsin16_t(accum88 beats_per_minute, uint16_t lowest = 0, uint16_t highest = 65535, uint32_t timebase = 0, uint16_t phase_offset = 0); | ||||
| uint8_t beatsin8_t(accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255, uint32_t timebase = 0, uint8_t phase_offset = 0); | ||||
| um_data_t* simulateSound(uint8_t simulationId); | ||||
| void enumerateLedmaps(); | ||||
| uint8_t get_random_wheel_index(uint8_t pos); | ||||
| @@ -416,27 +422,37 @@ void clearEEPROM(); | ||||
| #endif | ||||
|  | ||||
| //wled_math.cpp | ||||
| #if defined(ESP8266) && !defined(WLED_USE_REAL_MATH) | ||||
|   template <typename T> T atan_t(T x); | ||||
|   float cos_t(float phi); | ||||
|   float sin_t(float x); | ||||
|   float tan_t(float x); | ||||
|   float acos_t(float x); | ||||
|   float asin_t(float x); | ||||
|   float floor_t(float x); | ||||
|   float fmod_t(float num, float denom); | ||||
| #else | ||||
|   #include <math.h> | ||||
|   #define sin_t sinf | ||||
|   #define cos_t cosf | ||||
|   #define tan_t tanf | ||||
|   #define asin_t asinf | ||||
|   #define acos_t acosf | ||||
|   #define atan_t atanf | ||||
|   #define fmod_t fmodf | ||||
|   #define floor_t floorf | ||||
| #endif | ||||
| //float cos_t(float phi); // use float math | ||||
| //float sin_t(float phi); | ||||
| //float tan_t(float x); | ||||
| int16_t sin16_t(uint16_t theta); | ||||
| int16_t cos16_t(uint16_t theta); | ||||
| uint8_t sin8_t(uint8_t theta); | ||||
| uint8_t cos8_t(uint8_t theta); | ||||
| float sin_approx(float theta); // uses integer math (converted to float), accuracy +/-0.0015 (compared to sinf()) | ||||
| float cos_approx(float theta); | ||||
| float tan_approx(float x); | ||||
| float atan2_t(float y, float x); | ||||
| float acos_t(float x); | ||||
| float asin_t(float x); | ||||
| template <typename T> T atan_t(T x); | ||||
| float floor_t(float x); | ||||
| float fmod_t(float num, float denom); | ||||
| #define sin_t sin_approx | ||||
| #define cos_t cos_approx | ||||
| #define tan_t tan_approx | ||||
|  | ||||
| /* | ||||
| #include <math.h>  // standard math functions. use a lot of flash | ||||
| #define sin_t sinf | ||||
| #define cos_t cosf | ||||
| #define tan_t tanf | ||||
| #define asin_t asinf | ||||
| #define acos_t acosf | ||||
| #define atan_t atanf | ||||
| #define fmod_t fmodf | ||||
| #define floor_t floorf | ||||
| */ | ||||
| //wled_serial.cpp | ||||
| void handleSerial(); | ||||
| void updateBaudRate(uint32_t rate); | ||||
|   | ||||
| @@ -123,6 +123,7 @@ void handleImprovPacket() { | ||||
|     } | ||||
|  | ||||
|     checksum += next; | ||||
|     checksum &= 0xFF; | ||||
|     packetByte++; | ||||
|   } | ||||
| } | ||||
| @@ -193,24 +194,22 @@ void sendImprovIPRPCResult(ImprovRPCType type) { | ||||
| } | ||||
|  | ||||
| void sendImprovInfoResponse() { | ||||
|   const char* bString =  | ||||
|     #ifdef ESP8266 | ||||
|       "esp8266" | ||||
|     #elif CONFIG_IDF_TARGET_ESP32C3 | ||||
|       "esp32-c3" | ||||
|     #elif CONFIG_IDF_TARGET_ESP32S2 | ||||
|       "esp32-s2" | ||||
|     #elif CONFIG_IDF_TARGET_ESP32S3 | ||||
|       "esp32-s3"; | ||||
|     #else // ESP32 | ||||
|       "esp32"; | ||||
|     #endif | ||||
|     ; | ||||
|  | ||||
|   char bString[32]; | ||||
|   #ifdef ESP8266 | ||||
|   strcpy(bString, "esp8266"); | ||||
|   #else // ESP32 | ||||
|   strncpy(bString, ESP.getChipModel(), 31); | ||||
|   #if CONFIG_IDF_TARGET_ESP32 | ||||
|   bString[5] = '\0'; // disregard chip revision for classic ESP32 | ||||
|   #else | ||||
|   bString[31] = '\0'; // just in case | ||||
|   #endif | ||||
|   strlwr(bString); | ||||
|   #endif | ||||
|   //Use serverDescription if it has been changed from the default "WLED", else mDNS name | ||||
|   bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0); | ||||
|   char vString[20]; | ||||
|   sprintf_P(vString, PSTR("0.15.0-b5/%i"), VERSION); | ||||
|   char vString[32]; | ||||
|   sprintf_P(vString, PSTR("%s/%i"), versionString, VERSION); | ||||
|   const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription}; | ||||
|  | ||||
|   sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str); | ||||
|   | ||||
| @@ -346,7 +346,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   int tr = -1; | ||||
|   long tr = -1; | ||||
|   if (!presetId || currentPlaylist < 0) { //do not apply transition time from preset if playlist active, as it would override playlist transition times | ||||
|     tr = root[F("transition")] | -1; | ||||
|     if (tr >= 0) { | ||||
| @@ -363,7 +363,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId) | ||||
|   } | ||||
|  | ||||
|   tr = root[F("tb")] | -1; | ||||
|   if (tr >= 0) strip.timebase = ((uint32_t)tr) - millis(); | ||||
|   if (tr >= 0) strip.timebase = (unsigned long)tr - millis(); | ||||
|  | ||||
|   JsonObject nl       = root["nl"]; | ||||
|   nightlightActive    = getBoolVal(nl["on"], nightlightActive); | ||||
| @@ -454,21 +454,25 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId) | ||||
|     handleSet(nullptr, apireq, false);    // may set stateChanged | ||||
|   } | ||||
|  | ||||
|   // applying preset (2 cases: a) API call includes all preset values ("pd"), b) API only specifies preset ID ("ps")) | ||||
|   // Applying preset from JSON API has 2 cases: a) "pd" AKA "preset direct" and b) "ps" AKA "preset select" | ||||
|   // a) "preset direct" can only be an integer value representing preset ID. "preset direct" assumes JSON API contains the rest of preset content (i.e. from UI call) | ||||
|   //    "preset direct" JSON can contain "ps" API (i.e. call from UI to cycle presets) in such case stateChanged has to be false (i.e. no "win" or "seg" API) | ||||
|   // b) "preset select" can be cycling ("1~5~""), random ("r" or "1~5r"), ID, etc. value allowed from JSON API. This type of call assumes no state changing content in API call | ||||
|   byte presetToRestore = 0; | ||||
|   // a) already applied preset content (requires "seg" or "win" but will ignore the rest) | ||||
|   if (!root[F("pd")].isNull() && stateChanged) { | ||||
|     // a) already applied preset content (requires "seg" or "win" but will ignore the rest) | ||||
|     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 presetCycCurr was set in handleSet() [set.cpp] | ||||
|     presetToRestore = currentPreset; // stateUpdated() will clear the preset, so we need to restore it after | ||||
|     DEBUG_PRINTF_P(PSTR("Preset direct: %d\n"), currentPreset); | ||||
|   } else if (!root["ps"].isNull()) { | ||||
|     ps = presetCycCurr; | ||||
|     if (root["win"].isNull() && getVal(root["ps"], &ps, 0, 0) && ps > 0 && ps < 251 && ps != currentPreset) { | ||||
|     // we have "ps" call (i.e. from button or external API call) or "pd" that includes "ps" (i.e. from UI call) | ||||
|     if (root["win"].isNull() && getVal(root["ps"], &presetCycCurr, 0, 0) && presetCycCurr > 0 && presetCycCurr < 251 && presetCycCurr != currentPreset) { | ||||
|       DEBUG_PRINTF_P(PSTR("Preset select: %d\n"), presetCycCurr); | ||||
|       // b) preset ID only or preset that does not change state (use embedded cycling limits if they exist in getVal()) | ||||
|       presetCycCurr = ps; | ||||
|       applyPreset(ps, callMode); // async load from file system (only preset ID was specified) | ||||
|       applyPreset(presetCycCurr, callMode); // async load from file system (only preset ID was specified) | ||||
|       return stateResponse; | ||||
|     } | ||||
|     } else presetCycCurr = currentPreset; // restore presetCycCurr | ||||
|   } | ||||
|  | ||||
|   JsonObject playlist = root[F("playlist")]; | ||||
|   | ||||
| @@ -47,17 +47,12 @@ void applyValuesToSelectedSegs() | ||||
| } | ||||
|  | ||||
|  | ||||
| void resetTimebase() | ||||
| { | ||||
|   strip.timebase = 0 - millis(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void toggleOnOff() | ||||
| { | ||||
|   if (bri == 0) | ||||
|   { | ||||
|     bri = briLast; | ||||
|     strip.restartRuntime(); | ||||
|   } else | ||||
|   { | ||||
|     briLast = bri; | ||||
| @@ -122,7 +117,7 @@ void stateUpdated(byte callMode) { | ||||
|     nightlightStartTime = millis(); | ||||
|   } | ||||
|   if (briT == 0) { | ||||
|     if (callMode != CALL_MODE_NOTIFICATION) resetTimebase(); //effect start from beginning | ||||
|     if (callMode != CALL_MODE_NOTIFICATION) strip.resetTimebase(); //effect start from beginning | ||||
|   } | ||||
|  | ||||
|   if (bri > 0) briLast = bri; | ||||
|   | ||||
| @@ -36,8 +36,9 @@ Timezone* tz; | ||||
| #define TZ_ANCHORAGE           20 | ||||
| #define TZ_MX_CENTRAL          21 | ||||
| #define TZ_PAKISTAN            22 | ||||
| #define TZ_BRASILIA            23 | ||||
|  | ||||
| #define TZ_COUNT               23 | ||||
| #define TZ_COUNT               24 | ||||
| #define TZ_INIT               255 | ||||
|  | ||||
| byte tzCurrent = TZ_INIT; //uninitialized | ||||
| @@ -135,6 +136,10 @@ static const std::pair<TimeChangeRule, TimeChangeRule> TZ_TABLE[] PROGMEM = { | ||||
|     /* TZ_PAKISTAN */ { | ||||
|       {Last, Sun, Mar, 1, 300},     //Pakistan Standard Time = UTC + 5 hours | ||||
|       {Last, Sun, Mar, 1, 300} | ||||
|     }, | ||||
|     /* TZ_BRASILIA */ { | ||||
|       {Last, Sun, Mar, 1, -180},    //Brasília Standard Time = UTC - 3 hours | ||||
|       {Last, Sun, Mar, 1, -180} | ||||
|     } | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -201,7 +201,12 @@ bool PinManager::isPinOk(byte gpio, bool output) | ||||
|     if (gpio > 18 && gpio < 21) return false;     // 19 + 20 = USB-JTAG. Not recommended for other uses. | ||||
|     #endif | ||||
|     if (gpio > 21 && gpio < 33) return false;     // 22 to 32: not connected + SPI FLASH | ||||
|     if (gpio > 32 && gpio < 38) return !psramFound(); // 33 to 37: not available if using _octal_ SPI Flash or _octal_ PSRAM | ||||
|     #if CONFIG_ESPTOOLPY_FLASHMODE_OPI            // 33-37: never available if using _octal_ Flash (opi_opi) | ||||
|     if (gpio > 32 && gpio < 38) return false; | ||||
|     #endif | ||||
|     #if CONFIG_SPIRAM_MODE_OCT                    // 33-37: not available if using _octal_ PSRAM (qio_opi), but free to use on _quad_ PSRAM (qio_qspi) | ||||
|     if (gpio > 32 && gpio < 38) return !psramFound(); | ||||
|     #endif | ||||
|     // 38 to 48 are for general use. Be careful about straping pins GPIO45 and GPIO46 - these may be pull-up or pulled-down on your board. | ||||
|   #elif defined(CONFIG_IDF_TARGET_ESP32S2) | ||||
|     // strapping pins: 0, 45 & 46 | ||||
|   | ||||
| @@ -143,6 +143,7 @@ void applyPresetWithFallback(uint8_t index, uint8_t callMode, uint8_t effectID, | ||||
|  | ||||
| void handlePresets() | ||||
| { | ||||
|   byte presetErrFlag = ERR_NONE; | ||||
|   if (presetToSave) { | ||||
|     strip.suspend(); | ||||
|     doSaveState(); | ||||
| @@ -166,14 +167,16 @@ void handlePresets() | ||||
|   #ifdef ARDUINO_ARCH_ESP32 | ||||
|   if (tmpPreset==255 && tmpRAMbuffer!=nullptr) { | ||||
|     deserializeJson(*pDoc,tmpRAMbuffer); | ||||
|     errorFlag = ERR_NONE; | ||||
|   } else | ||||
|   #endif | ||||
|   { | ||||
|   errorFlag = readObjectFromFileUsingId(getPresetsFileName(tmpPreset < 255), tmpPreset, pDoc) ? ERR_NONE : ERR_FS_PLOAD; | ||||
|   presetErrFlag = readObjectFromFileUsingId(getPresetsFileName(tmpPreset < 255), tmpPreset, pDoc) ? ERR_NONE : ERR_FS_PLOAD; | ||||
|   } | ||||
|   fdo = pDoc->as<JsonObject>(); | ||||
|  | ||||
|   // only reset errorflag if previous error was preset-related | ||||
|   if ((errorFlag == ERR_NONE) || (errorFlag == ERR_FS_PLOAD)) errorFlag = presetErrFlag; | ||||
|  | ||||
|   //HTTP API commands | ||||
|   const char* httpwin = fdo["win"]; | ||||
|   if (httpwin) { | ||||
|   | ||||
| @@ -215,6 +215,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) | ||||
|     //doInitBusses = busesChanged; // we will do that below to ensure all input data is processed | ||||
|  | ||||
|     // we will not bother with pre-allocating ColorOrderMappings vector | ||||
|     BusManager::getColorOrderMap().reset(); | ||||
|     for (int s = 0; s < WLED_MAX_COLOR_ORDER_MAPPINGS; s++) { | ||||
|       int offset = s < 10 ? 48 : 55; | ||||
|       char xs[4] = "XS"; xs[2] = offset+s; xs[3] = 0; //start LED | ||||
| @@ -1191,7 +1192,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply) | ||||
|  | ||||
|   // internal call, does not send XML response | ||||
|   pos = req.indexOf(F("IN")); | ||||
|   if (pos < 1) { | ||||
|   if ((request != nullptr) && (pos < 1)) { | ||||
|     auto response = request->beginResponseStream("text/xml"); | ||||
|     XML_response(*response); | ||||
|     request->send(response); | ||||
|   | ||||
| @@ -34,8 +34,8 @@ static const int enablePin = -1;		// disable the enable pin because it is not ne | ||||
| static const int rxPin = -1;       // disable the receiving pin because it is not needed - softhack007: Pin=-1 means "use default" not "disable" | ||||
| static const int txPin = 2;        // transmit DMX data over this pin (default is pin 2) | ||||
|  | ||||
| //DMX value array and size. Entry 0 will hold startbyte | ||||
| static uint8_t dmxData[dmxMaxChannel] = { 0 }; | ||||
| //DMX value array and size. Entry 0 will hold startbyte, so we need 512+1 elements | ||||
| static uint8_t dmxData[dmxMaxChannel+1] = { 0 }; | ||||
| static int chanSize = 0; | ||||
| #if !defined(DMX_SEND_ONLY) | ||||
| static int currentChannel = 0; | ||||
|   | ||||
| @@ -120,10 +120,8 @@ private: | ||||
|    | ||||
|   void encodeLightId(uint8_t idx, char* out) | ||||
|   { | ||||
|     uint8_t mac[6]; | ||||
|     WiFi.macAddress(mac); | ||||
|  | ||||
|     sprintf_P(out, PSTR("%02X:%02X:%02X:%02X:%02X:%02X:00:11-%02X"), mac[0],mac[1],mac[2],mac[3],mac[4],mac[5], idx); | ||||
|     String mymac = WiFi.macAddress(); | ||||
| 	sprintf_P(out, PSTR("%02X:%s:AB-%02X"), idx, mymac.c_str(), idx); | ||||
|   } | ||||
|  | ||||
|   // construct 'globally unique' Json dict key fitting into signed int | ||||
|   | ||||
| @@ -372,6 +372,39 @@ uint16_t crc16(const unsigned char* data_p, size_t length) { | ||||
|   return crc; | ||||
| } | ||||
|  | ||||
| // fastled beatsin: 1:1 replacements to remove the use of fastled sin16() | ||||
| // Generates a 16-bit sine wave at a given BPM that oscillates within a given range. see fastled for details. | ||||
| uint16_t beatsin88_t(accum88 beats_per_minute_88, uint16_t lowest, uint16_t highest, uint32_t timebase, uint16_t phase_offset) | ||||
| { | ||||
|     uint16_t beat = beat88( beats_per_minute_88, timebase); | ||||
|     uint16_t beatsin (sin16_t( beat + phase_offset) + 32768); | ||||
|     uint16_t rangewidth = highest - lowest; | ||||
|     uint16_t scaledbeat = scale16( beatsin, rangewidth); | ||||
|     uint16_t result = lowest + scaledbeat; | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| // Generates a 16-bit sine wave at a given BPM that oscillates within a given range. see fastled for details. | ||||
| uint16_t beatsin16_t(accum88 beats_per_minute, uint16_t lowest, uint16_t highest, uint32_t timebase, uint16_t phase_offset) | ||||
| { | ||||
|     uint16_t beat = beat16( beats_per_minute, timebase); | ||||
|     uint16_t beatsin = (sin16_t( beat + phase_offset) + 32768); | ||||
|     uint16_t rangewidth = highest - lowest; | ||||
|     uint16_t scaledbeat = scale16( beatsin, rangewidth); | ||||
|     uint16_t result = lowest + scaledbeat; | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| // Generates an 8-bit sine wave at a given BPM that oscillates within a given range. see fastled for details. | ||||
| uint8_t beatsin8_t(accum88 beats_per_minute, uint8_t lowest, uint8_t highest, uint32_t timebase, uint8_t phase_offset) | ||||
| { | ||||
|     uint8_t beat = beat8( beats_per_minute, timebase); | ||||
|     uint8_t beatsin = sin8_t( beat + phase_offset); | ||||
|     uint8_t rangewidth = highest - lowest; | ||||
|     uint8_t scaledbeat = scale8( beatsin, rangewidth); | ||||
|     uint8_t result = lowest + scaledbeat; | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // Begin simulateSound (to enable audio enhanced effects to display something) | ||||
| @@ -431,8 +464,8 @@ um_data_t* simulateSound(uint8_t simulationId) | ||||
|     default: | ||||
|     case UMS_BeatSin: | ||||
|       for (int i = 0; i<16; i++) | ||||
|         fftResult[i] = beatsin8(120 / (i+1), 0, 255); | ||||
|         // fftResult[i] = (beatsin8(120, 0, 255) + (256/16 * i)) % 256; | ||||
|         fftResult[i] = beatsin8_t(120 / (i+1), 0, 255); | ||||
|         // fftResult[i] = (beatsin8_t(120, 0, 255) + (256/16 * i)) % 256; | ||||
|         volumeSmth = fftResult[8]; | ||||
|       break; | ||||
|     case UMS_WeWillRockYou: | ||||
| @@ -469,12 +502,12 @@ um_data_t* simulateSound(uint8_t simulationId) | ||||
|       break; | ||||
|     case UMS_10_13: | ||||
|       for (int i = 0; i<16; i++) | ||||
|         fftResult[i] = inoise8(beatsin8(90 / (i+1), 0, 200)*15 + (ms>>10), ms>>3); | ||||
|         fftResult[i] = inoise8(beatsin8_t(90 / (i+1), 0, 200)*15 + (ms>>10), ms>>3); | ||||
|         volumeSmth = fftResult[8]; | ||||
|       break; | ||||
|     case UMS_14_3: | ||||
|       for (int i = 0; i<16; i++) | ||||
|         fftResult[i] = inoise8(beatsin8(120 / (i+1), 10, 30)*10 + (ms>>14), ms>>3); | ||||
|         fftResult[i] = inoise8(beatsin8_t(120 / (i+1), 10, 30)*10 + (ms>>14), ms>>3); | ||||
|       volumeSmth = fftResult[8]; | ||||
|       break; | ||||
|   } | ||||
|   | ||||
| @@ -219,6 +219,7 @@ void WLED::loop() | ||||
|       busConfigs[i] = nullptr; | ||||
|     } | ||||
|     strip.finalizeInit(); // also loads default ledmap if present | ||||
|     BusManager::setBrightness(bri); // fix re-initialised bus' brightness #4005 | ||||
|     if (aligned) strip.makeAutoSegments(); | ||||
|     else strip.fixInvalidSegments(); | ||||
|     doSerializeConfig = true; | ||||
| @@ -379,6 +380,12 @@ void WLED::setup() | ||||
|     case FM_QOUT: DEBUG_PRINT(F("(QOUT)"));break; | ||||
|     case FM_DIO:  DEBUG_PRINT(F("(DIO)")); break; | ||||
|     case FM_DOUT: DEBUG_PRINT(F("(DOUT)"));break; | ||||
|     #if defined(CONFIG_IDF_TARGET_ESP32S3) && CONFIG_ESPTOOLPY_FLASHMODE_OPI | ||||
|     case FM_FAST_READ: DEBUG_PRINT(F("(OPI)")); break; | ||||
|     #else | ||||
|     case FM_FAST_READ: DEBUG_PRINT(F("(fast_read)")); break; | ||||
|     #endif | ||||
|     case FM_SLOW_READ: DEBUG_PRINT(F("(slow_read)")); break; | ||||
|     default: break; | ||||
|   } | ||||
|   #endif | ||||
|   | ||||
| @@ -3,12 +3,12 @@ | ||||
| /* | ||||
|    Main sketch, global variable declarations | ||||
|    @title WLED project sketch | ||||
|    @version 0.15.0-b5 | ||||
|    @version 0.15.0-cr1 | ||||
|    @author Christian Schwinne | ||||
|  */ | ||||
|  | ||||
| // version code in format yymmddb (b = daily build) | ||||
| #define VERSION 2409170 | ||||
| #define VERSION 2411250 | ||||
|  | ||||
| //uncomment this if you have a "my_config.h" file you'd like to use | ||||
| //#define WLED_USE_MY_CONFIG | ||||
| @@ -36,12 +36,13 @@ | ||||
|   #undef WLED_ENABLE_ADALIGHT      // disable has priority over enable | ||||
| #endif | ||||
| //#define WLED_ENABLE_DMX          // uses 3.5kb | ||||
| //#define WLED_ENABLE_JSONLIVE     // peek LED output via /json/live (WS binary peek is always enabled) | ||||
| #ifndef WLED_DISABLE_LOXONE | ||||
|   #define WLED_ENABLE_LOXONE       // uses 1.2kb | ||||
| #endif | ||||
| #ifndef WLED_DISABLE_WEBSOCKETS | ||||
|   #define WLED_ENABLE_WEBSOCKETS | ||||
| #else | ||||
|   #define WLED_ENABLE_JSONLIVE     // peek LED output via /json/live (WS binary peek is always enabled) | ||||
| #endif | ||||
|  | ||||
| //#define WLED_DISABLE_ESPNOW      // Removes dependence on esp now | ||||
| @@ -263,12 +264,12 @@ using PSRAMDynamicJsonDocument = BasicJsonDocument<PSRAM_Allocator>; | ||||
|   #define WLED_VERSION dev | ||||
| #endif | ||||
| #ifndef WLED_RELEASE_NAME | ||||
|   #define WLED_RELEASE_NAME dev_release | ||||
|   #define WLED_RELEASE_NAME "Custom" | ||||
| #endif | ||||
|  | ||||
| // Global Variable definitions | ||||
| WLED_GLOBAL char versionString[] _INIT(TOSTRING(WLED_VERSION)); | ||||
| WLED_GLOBAL char releaseString[] _INIT(TOSTRING(WLED_RELEASE_NAME)); // somehow this will not work if using "const char releaseString[] | ||||
| WLED_GLOBAL char releaseString[] _INIT(WLED_RELEASE_NAME); // must include the quotes when defining, e.g -D WLED_RELEASE_NAME=\"ESP32_MULTI_USREMODS\" | ||||
| #define WLED_CODENAME "Kōsen" | ||||
|  | ||||
| // AP and OTA default passwords (for maximum security change them!) | ||||
| @@ -316,8 +317,6 @@ WLED_GLOBAL bool rlyOpenDrain _INIT(RLYODRAIN); | ||||
|   constexpr uint8_t hardwareTX = 1; | ||||
| #endif | ||||
|  | ||||
| //WLED_GLOBAL byte presetToApply _INIT(0); | ||||
|  | ||||
| WLED_GLOBAL char ntpServerName[33] _INIT("0.wled.pool.ntp.org");   // NTP server to use | ||||
|  | ||||
| // WiFi CONFIG (all these can be changed via web UI, no need to set them here) | ||||
|   | ||||
| @@ -10,16 +10,25 @@ | ||||
|  | ||||
| //#define WLED_DEBUG_MATH | ||||
|  | ||||
| // Note: cos_t, sin_t and tan_t are very accurate but slow | ||||
| // the math.h functions use several kB of flash and are to be avoided if possible | ||||
| // sin16_t / cos16_t are faster and much more accurate than the fastled variants | ||||
| // sin_approx and cos_approx are float wrappers for sin16_t/cos16_t and have an accuracy better than +/-0.0015 compared to sinf() | ||||
| // sin8_t / cos8_t are fastled replacements and use sin16_t / cos16_t. Slightly slower than fastled version but very accurate | ||||
|  | ||||
|  | ||||
| // Taylor series approximations, replaced with Bhaskara I's approximation | ||||
| /* | ||||
| #define modd(x, y) ((x) - (int)((x) / (y)) * (y)) | ||||
|  | ||||
| float cos_t(float phi) | ||||
| { | ||||
|   float x = modd(phi, TWO_PI); | ||||
|   float x = modd(phi, M_TWOPI); | ||||
|   if (x < 0) x = -1 * x; | ||||
|   int8_t sign = 1; | ||||
|   if (x > PI) | ||||
|   if (x > M_PI) | ||||
|   { | ||||
|       x -= PI; | ||||
|       x -= M_PI; | ||||
|       sign = -1; | ||||
|   } | ||||
|   float xx = x * x; | ||||
| @@ -31,8 +40,8 @@ float cos_t(float phi) | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| float sin_t(float x) { | ||||
|   float res =  cos_t(HALF_PI - x); | ||||
| float sin_t(float phi) { | ||||
|   float res =  cos_t(M_PI_2 - phi); | ||||
|   #ifdef WLED_DEBUG_MATH | ||||
|   Serial.printf("sin: %f,%f,%f,(%f)\n",x,res,sin(x),res-sin(x)); | ||||
|   #endif | ||||
| @@ -48,6 +57,80 @@ float tan_t(float x) { | ||||
|   #endif | ||||
|   return res; | ||||
| } | ||||
| */ | ||||
|  | ||||
| // 16-bit, integer based Bhaskara I's sine approximation: 16*x*(pi - x) / (5*pi^2 - 4*x*(pi - x)) | ||||
| // input is 16bit unsigned (0-65535), output is 16bit signed (-32767 to +32767) | ||||
| // optimized integer implementation by @dedehai | ||||
| int16_t sin16_t(uint16_t theta) { | ||||
|   int scale = 1; | ||||
|   if (theta > 0x7FFF) { | ||||
|     theta = 0xFFFF - theta; | ||||
|     scale = -1; // second half of the sine function is negative (pi - 2*pi) | ||||
|   } | ||||
|   uint32_t precal = theta * (0x7FFF - theta); | ||||
|   uint64_t numerator = (uint64_t)precal * (4 * 0x7FFF); // 64bit required | ||||
|   int32_t denominator = 1342095361 - precal; // 1342095361 is 5 * 0x7FFF^2 / 4 | ||||
|   int16_t result = numerator / denominator; | ||||
|   return result * scale; | ||||
| } | ||||
|  | ||||
| int16_t cos16_t(uint16_t theta) { | ||||
|   return sin16_t(theta + 0x4000); //cos(x) = sin(x+pi/2) | ||||
| } | ||||
|  | ||||
| uint8_t sin8_t(uint8_t theta) { | ||||
|   int32_t sin16 = sin16_t((uint16_t)theta * 257); // 255 * 257 = 0xFFFF | ||||
|   sin16 += 0x7FFF + 128; //shift result to range 0-0xFFFF, +128 for rounding | ||||
|   return min(sin16, int32_t(0xFFFF)) >> 8; // min performs saturation, and prevents overflow | ||||
| } | ||||
|  | ||||
| uint8_t cos8_t(uint8_t theta) { | ||||
|   return sin8_t(theta + 64); //cos(x) = sin(x+pi/2) | ||||
| } | ||||
|  | ||||
| float sin_approx(float theta) { | ||||
|   uint16_t scaled_theta = (int)(theta * (float)(0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) | ||||
|   int32_t result = sin16_t(scaled_theta); | ||||
|   float sin = float(result) / 0x7FFF; | ||||
|   return sin; | ||||
| } | ||||
|  | ||||
| float cos_approx(float theta) { | ||||
|   uint16_t scaled_theta = (int)(theta * (float)(0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) | ||||
|   int32_t result = sin16_t(scaled_theta + 0x4000); | ||||
|   float cos = float(result) / 0x7FFF; | ||||
|   return cos; | ||||
| } | ||||
|  | ||||
| float tan_approx(float x) { | ||||
|   float c = cos_approx(x); | ||||
|   if (c==0.0f) return 0; | ||||
|   float res = sin_approx(x) / c; | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| #define ATAN2_CONST_A 0.1963f | ||||
| #define ATAN2_CONST_B 0.9817f | ||||
|  | ||||
| // atan2_t approximation, with the idea from https://gist.github.com/volkansalma/2972237?permalink_comment_id=3872525#gistcomment-3872525 | ||||
| float atan2_t(float y, float x) { | ||||
| 	float abs_y = fabs(y); | ||||
|   float abs_x = fabs(x); | ||||
|   float r = (abs_x - abs_y) / (abs_y + abs_x + 1e-10f); // avoid division by zero by adding a small nubmer | ||||
|   float angle; | ||||
|   if(x < 0) { | ||||
|     r = -r; | ||||
|     angle = M_PI_2 + M_PI_4; | ||||
|   } | ||||
|   else | ||||
|     angle = M_PI_2 - M_PI_4; | ||||
|  | ||||
|   float add = (ATAN2_CONST_A * (r * r) - ATAN2_CONST_B) * r; | ||||
| 	angle += add; | ||||
|   angle = y < 0 ? -angle : angle; | ||||
| 	return angle; | ||||
| } | ||||
|  | ||||
| //https://stackoverflow.com/questions/3380628 | ||||
| // Absolute error <= 6.7e-5 | ||||
| @@ -60,10 +143,10 @@ float acos_t(float x) { | ||||
|   ret = ret * xabs; | ||||
|   ret = ret - 0.2121144f; | ||||
|   ret = ret * xabs; | ||||
|   ret = ret + HALF_PI; | ||||
|   ret = ret + M_PI_2; | ||||
|   ret = ret * sqrt(1.0f-xabs); | ||||
|   ret = ret - 2 * negate * ret; | ||||
|   float res = negate * PI + ret; | ||||
|   float res = negate * M_PI + ret; | ||||
|   #ifdef WLED_DEBUG_MATH | ||||
|   Serial.printf("acos: %f,%f,%f,(%f)\n",x,res,acos(x),res-acos(x)); | ||||
|   #endif | ||||
| @@ -71,7 +154,7 @@ float acos_t(float x) { | ||||
| } | ||||
|  | ||||
| float asin_t(float x) { | ||||
|   float res = HALF_PI - acos_t(x); | ||||
|   float res = M_PI_2 - acos_t(x); | ||||
|   #ifdef WLED_DEBUG_MATH | ||||
|   Serial.printf("asin: %f,%f,%f,(%f)\n",x,res,asin(x),res-asin(x)); | ||||
|   #endif | ||||
| @@ -87,7 +170,7 @@ float atan_t(float x) { | ||||
|   //For A/B/C, see https://stackoverflow.com/a/42542593 | ||||
|   static const double A { 0.0776509570923569 }; | ||||
|   static const double B { -0.287434475393028 }; | ||||
|   static const double C { ((HALF_PI/2) - A - B) }; | ||||
|   static const double C { ((M_PI_4) - A - B) }; | ||||
|   // polynominal factors for approximation between 1 and 5 | ||||
|   static const float C0 {  0.089494f }; | ||||
|   static const float C1 {  0.974207f }; | ||||
| @@ -102,7 +185,7 @@ float atan_t(float x) { | ||||
|   x = std::abs(x); | ||||
|   float res; | ||||
|   if (x > 5.0f) { // atan(x) converges to pi/2 - (1/x) for large values | ||||
|     res = HALF_PI - (1.0f/x); | ||||
|     res = M_PI_2 - (1.0f/x); | ||||
|   } else if (x > 1.0f) { //1 < x < 5 | ||||
|     float xx = x * x; | ||||
|     res = (C4*xx*xx)+(C3*xx*x)+(C2*xx)+(C1*x)+C0; | ||||
|   | ||||
| @@ -193,12 +193,12 @@ void createEditHandler(bool enable) { | ||||
|       editHandler = &server.addHandler(new SPIFFSEditor("","",WLED_FS));//http_username,http_password)); | ||||
|       #endif | ||||
|     #else | ||||
|       editHandler = &server.on(SET_F("/edit"), HTTP_GET, [](AsyncWebServerRequest *request){ | ||||
|       editHandler = &server.on(F("/edit"), HTTP_GET, [](AsyncWebServerRequest *request){ | ||||
|         serveMessage(request, 501, FPSTR(s_notimplemented), F("The FS editor is disabled in this build."), 254); | ||||
|       }); | ||||
|     #endif | ||||
|   } else { | ||||
|     editHandler = &server.on(SET_F("/edit"), HTTP_ANY, [](AsyncWebServerRequest *request){ | ||||
|     editHandler = &server.on(F("/edit"), HTTP_ANY, [](AsyncWebServerRequest *request){ | ||||
|       serveMessage(request, 401, FPSTR(s_accessdenied), FPSTR(s_unlock_cfg), 254); | ||||
|     }); | ||||
|   } | ||||
| @@ -427,11 +427,11 @@ void initServer() | ||||
|  | ||||
|  | ||||
| #ifdef WLED_ENABLE_DMX | ||||
|   server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){ | ||||
|   server.on(F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){ | ||||
|     request->send_P(200, FPSTR(CONTENT_TYPE_HTML), PAGE_dmxmap     , dmxProcessor); | ||||
|   }); | ||||
| #else | ||||
|   server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){ | ||||
|   server.on(F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){ | ||||
|     serveMessage(request, 501, FPSTR(s_notimplemented), F("DMX support is not enabled in this build."), 254); | ||||
|   }); | ||||
| #endif | ||||
|   | ||||
| @@ -83,7 +83,7 @@ void appendGPIOinfo(Print& settingsScript) { | ||||
|   // usermod pin reservations will become unnecessary when settings pages will read cfg.json directly | ||||
|   if (requestJSONBufferLock(6)) { | ||||
|     // if we can't allocate JSON buffer ignore usermod pins | ||||
|     JsonObject mods = pDoc->createNestedObject(F("um")); | ||||
|     JsonObject mods = pDoc->createNestedObject("um"); | ||||
|     UsermodManager::addToConfig(mods); | ||||
|     if (!mods.isNull()) fillUMPins(settingsScript, mods); | ||||
|     releaseJSONBufferLock(); | ||||
| @@ -91,35 +91,42 @@ void appendGPIOinfo(Print& settingsScript) { | ||||
|   settingsScript.print(F("];")); | ||||
|  | ||||
|   // add reserved (unusable) pins | ||||
|   bool firstPin = true; | ||||
|   settingsScript.print(F("d.rsvd=[")); | ||||
|   for (unsigned i = 0; i < WLED_NUM_PINS; i++) { | ||||
|     if (!PinManager::isPinOk(i, false)) {  // include readonly pins | ||||
|       settingsScript.print(i); settingsScript.print(","); | ||||
|       if (!firstPin) settingsScript.print(','); | ||||
|       settingsScript.print(i); | ||||
|       firstPin = false; | ||||
|     } | ||||
|   } | ||||
|   #ifdef WLED_ENABLE_DMX | ||||
|   settingsScript.print(F("2,")); // DMX hardcoded pin | ||||
|   if (!firstPin) settingsScript.print(','); | ||||
|   settingsScript.print(2); // DMX hardcoded pin | ||||
|   firstPin = false; | ||||
|   #endif | ||||
|   #if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST) | ||||
|   settingsScript.printf_P(PSTR(",%d"),hardwareTX); // debug output (TX) pin | ||||
|   if (!firstPin) settingsScript.print(','); | ||||
|   settingsScript.print(hardwareTX); // debug output (TX) pin | ||||
|   firstPin = false; | ||||
|   #endif | ||||
|   //Note: Using pin 3 (RX) disables Adalight / Serial JSON | ||||
|   #ifdef WLED_USE_ETHERNET | ||||
|   if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) { | ||||
|     for (unsigned p=0; p<WLED_ETH_RSVD_PINS_COUNT; p++) { settingsScript.printf(",%d", esp32_nonconfigurable_ethernet_pins[p].pin); } | ||||
|     if (ethernetBoards[ethernetType].eth_power>=0)     { settingsScript.printf(",%d", ethernetBoards[ethernetType].eth_power); } | ||||
|     if (ethernetBoards[ethernetType].eth_mdc>=0)       { settingsScript.printf(",%d", ethernetBoards[ethernetType].eth_mdc); } | ||||
|     if (ethernetBoards[ethernetType].eth_mdio>=0)      { settingsScript.printf(",%d", ethernetBoards[ethernetType].eth_mdio); } | ||||
|     switch (ethernetBoards[ethernetType].eth_clk_mode) { | ||||
|     if (!firstPin) settingsScript.print(','); | ||||
|     for (unsigned p=0; p<WLED_ETH_RSVD_PINS_COUNT; p++) { settingsScript.printf("%d,",esp32_nonconfigurable_ethernet_pins[p].pin); } | ||||
|     if (ethernetBoards[ethernetType].eth_power >= 0)    { settingsScript.printf("%d,",ethernetBoards[ethernetType].eth_power); } | ||||
|     if (ethernetBoards[ethernetType].eth_mdc >= 0)      { settingsScript.printf("%d,",ethernetBoards[ethernetType].eth_mdc); } | ||||
|     if (ethernetBoards[ethernetType].eth_mdio >= 0)     { settingsScript.printf("%d,",ethernetBoards[ethernetType].eth_mdio); } | ||||
|     switch (ethernetBoards[ethernetType].eth_clk_mode)  { | ||||
|       case ETH_CLOCK_GPIO0_IN: | ||||
|       case ETH_CLOCK_GPIO0_OUT: | ||||
|         settingsScript.print(F("0")); | ||||
|         settingsScript.print(0); | ||||
|         break; | ||||
|       case ETH_CLOCK_GPIO16_OUT: | ||||
|         settingsScript.print(F("16")); | ||||
|         settingsScript.print(16); | ||||
|         break; | ||||
|       case ETH_CLOCK_GPIO17_OUT: | ||||
|         settingsScript.print(F("17")); | ||||
|         settingsScript.print(17); | ||||
|         break; | ||||
|     } | ||||
|   } | ||||
| @@ -128,11 +135,11 @@ void appendGPIOinfo(Print& settingsScript) { | ||||
|  | ||||
|   // add info for read-only GPIO | ||||
|   settingsScript.print(F("d.ro_gpio=[")); | ||||
|   bool firstPin = true; | ||||
|   firstPin = true; | ||||
|   for (unsigned i = 0; i < WLED_NUM_PINS; i++) { | ||||
|     if (PinManager::isReadOnlyPin(i)) { | ||||
|       // No comma before the first pin | ||||
|       if (!firstPin) settingsScript.print(F(",")); | ||||
|       if (!firstPin) settingsScript.print(','); | ||||
|       settingsScript.print(i); | ||||
|       firstPin = false; | ||||
|     } | ||||
| @@ -140,9 +147,7 @@ void appendGPIOinfo(Print& settingsScript) { | ||||
|   settingsScript.print(F("];")); | ||||
|  | ||||
|   // add info about max. # of pins | ||||
|   settingsScript.print(F("d.max_gpio=")); | ||||
|   settingsScript.print(WLED_NUM_PINS); | ||||
|   settingsScript.print(F(";")); | ||||
|   settingsScript.printf_P(PSTR("d.max_gpio=%d;"),WLED_NUM_PINS); | ||||
| } | ||||
|  | ||||
| //get values for settings form in javascript | ||||
| @@ -152,6 +157,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) | ||||
|   DEBUG_PRINTF_P(PSTR("settings resp %u\n"), (unsigned)subPage); | ||||
|  | ||||
|   if (subPage <0 || subPage >10) return; | ||||
|   char nS[32]; | ||||
|  | ||||
|   if (subPage == SUBPAGE_MENU) | ||||
|   { | ||||
| @@ -172,7 +178,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) | ||||
|       char fpass[l+1]; //fill password field with *** | ||||
|       fpass[l] = 0; | ||||
|       memset(fpass,'*',l); | ||||
|       settingsScript.printf_P(PSTR("addWiFi(\"%s\",\",%s\",0x%X,0x%X,0x%X);"), | ||||
|       settingsScript.printf_P(PSTR("addWiFi(\"%s\",\"%s\",0x%X,0x%X,0x%X);"), | ||||
|         multiWiFi[n].clientSSID, | ||||
|         fpass, | ||||
|         (uint32_t) multiWiFi[n].staticIP, // explicit cast required as this is a struct | ||||
| @@ -227,7 +233,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) | ||||
|       sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]); | ||||
|  | ||||
|       #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET) | ||||
|       if (Network.isEthernet()) strcat_P(s ,SET_F(" (Ethernet)")); | ||||
|       if (Network.isEthernet()) strcat_P(s ,PSTR(" (Ethernet)")); | ||||
|       #endif | ||||
|       printSetClassElementHTML(settingsScript,PSTR("sip"),0,s); | ||||
|     } else | ||||
| @@ -259,11 +265,9 @@ void getSettingsJS(byte subPage, Print& settingsScript) | ||||
|  | ||||
|   if (subPage == SUBPAGE_LEDS) | ||||
|   { | ||||
|     char nS[32]; | ||||
|  | ||||
|     appendGPIOinfo(settingsScript); | ||||
|  | ||||
|     settingsScript.print(F("d.ledTypes=")); settingsScript.print(BusManager::getLEDTypesJSONString().c_str()); settingsScript.print(";"); | ||||
|     settingsScript.printf_P(PSTR("d.ledTypes=%s;"), BusManager::getLEDTypesJSONString().c_str()); | ||||
|  | ||||
|     // set limits | ||||
|     settingsScript.printf_P(PSTR("bLimits(%d,%d,%d,%d,%d,%d,%d,%d);"), | ||||
| @@ -399,7 +403,6 @@ void getSettingsJS(byte subPage, Print& settingsScript) | ||||
|  | ||||
|   if (subPage == SUBPAGE_SYNC) | ||||
|   { | ||||
|     [[maybe_unused]] char nS[32]; | ||||
|     printSetFormValue(settingsScript,PSTR("UP"),udpPort); | ||||
|     printSetFormValue(settingsScript,PSTR("U2"),udpPort2); | ||||
|   #ifndef WLED_DISABLE_ESPNOW | ||||
| @@ -465,7 +468,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) | ||||
|     printSetFormValue(settingsScript,PSTR("MG"),mqttGroupTopic); | ||||
|     printSetFormCheckbox(settingsScript,PSTR("BM"),buttonPublishMqtt); | ||||
|     printSetFormCheckbox(settingsScript,PSTR("RT"),retainMqttMsg); | ||||
|     settingsScript.printf_P(PSTR("d.Sf.MD.maxlength=%d;d.Sf.MG.maxlength=%d;d.Sf.MS.maxlength=%d;"), | ||||
|     settingsScript.printf_P(PSTR("d.Sf.MD.maxLength=%d;d.Sf.MG.maxLength=%d;d.Sf.MS.maxLength=%d;"), | ||||
|                   MQTT_MAX_TOPIC_LEN, MQTT_MAX_TOPIC_LEN, MQTT_MAX_SERVER_LEN); | ||||
|     #else | ||||
|     settingsScript.print(F("toggle('MQTT');"));    // hide MQTT settings | ||||
| @@ -501,7 +504,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) | ||||
|     #endif | ||||
|     printSetFormValue(settingsScript,PSTR("BD"),serialBaud); | ||||
|     #ifndef WLED_ENABLE_ADALIGHT | ||||
|     settingsScript.print(F("toggle('Serial);")); | ||||
|     settingsScript.print(F("toggle('Serial');")); | ||||
|     #endif | ||||
|   } | ||||
|  | ||||
| @@ -637,7 +640,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) | ||||
|     #if defined(ARDUINO_ARCH_ESP32) | ||||
|       ESP.getChipModel(), | ||||
|     #else | ||||
|       F("esp8266"), | ||||
|       "esp8266", | ||||
|     #endif | ||||
|       VERSION); | ||||
|  | ||||
| @@ -648,8 +651,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) | ||||
|   { | ||||
|     printSetFormValue(settingsScript,PSTR("SOMP"),strip.isMatrix); | ||||
|     #ifndef WLED_DISABLE_2D | ||||
|     settingsScript.printf_P(PSTR("maxPanels=%d;"),WLED_MAX_PANELS); | ||||
|     settingsScript.print(F("resetPanels();")); | ||||
|     settingsScript.printf_P(PSTR("maxPanels=%d;resetPanels();"),WLED_MAX_PANELS); | ||||
|     if (strip.isMatrix) { | ||||
|       if(strip.panels>0){ | ||||
|         printSetFormValue(settingsScript,PSTR("PW"),strip.panel[0].width); //Set generator Width and Height to first panel size for convenience | ||||
| @@ -658,12 +660,9 @@ void getSettingsJS(byte subPage, Print& settingsScript) | ||||
|       printSetFormValue(settingsScript,PSTR("MPC"),strip.panels); | ||||
|       // panels | ||||
|       for (unsigned i=0; i<strip.panels; i++) { | ||||
|         char n[5]; | ||||
|         settingsScript.print(F("addPanel(")); | ||||
|         settingsScript.print(itoa(i,n,10)); | ||||
|         settingsScript.print(F(");")); | ||||
|         settingsScript.printf_P(PSTR("addPanel(%d);"), i); | ||||
|         char pO[8] = { '\0' }; | ||||
|         snprintf_P(pO, 7, PSTR("P%d"), i);       // MAX_PANELS is 64 so pO will always only be 4 characters or less | ||||
|         snprintf_P(pO, 7, PSTR("P%d"), i);       // WLED_MAX_PANELS is 18 so pO will always only be 4 characters or less | ||||
|         pO[7] = '\0'; | ||||
|         unsigned l = strlen(pO); | ||||
|         // create P0B, P1B, ..., P63B, etc for other PxxX | ||||
|   | ||||
		Reference in New Issue
	
	Block a user