Merge remote-tracking branch 'upstream/0_15' into 0_15_trig_math

This commit is contained in:
Damian Schneider 2024-11-27 22:22:50 +01:00
commit a0a46850f5
66 changed files with 970 additions and 625 deletions

80
.github/workflows/build.yml vendored Normal file
View 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
View 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

View File

@ -1,94 +1,11 @@
name: WLED CI name: WLED CI
on: [push, pull_request] on:
push:
branches:
- '*'
pull_request:
jobs: jobs:
wled_build:
get_default_envs: uses: ./.github/workflows/build.yml
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

View File

@ -1,9 +1,35 @@
## WLED changelog ## WLED changelog
#### 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 #### Build 2409140
- Configure different kinds of busses at compile (#4107 by @PaoloTK) - Configure different kinds of busses at compile (#4107 by @PaoloTK)
- BREAKING: removes LEDPIN and DEFAULT_LED_TYPE compile overrides - BREAKING: removes LEDPIN and DEFAULT_LED_TYPE compile overrides
- Fetch LED types from Bus classes (dynamic UI) (#4129 by @netmindz, @blazoncek, @dedehai) - 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 #### Build 2409100
- WLED 0.15.0-b5 release - WLED 0.15.0-b5 release

307
LICENSE
View File

@ -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 This European Union Public Licence (the EUPL) applies to the Work (as
of this software and associated documentation files (the "Software"), to deal defined below) which is provided under the terms of this Licence. Any use of
in the Software without restriction, including without limitation the rights the Work, other than as authorised under this Licence is prohibited (to the
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell extent such use is covered by a right of the copyright holder of the Work).
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 The Work is provided under the terms of this Licence when the Licensor (as
copies or substantial portions of the Software. 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 Licensed under the EUPL
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE or has expressed by any other means his willingness to license under the EUPL.
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1. Definitions
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. 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.

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "wled", "name": "wled",
"version": "0.15.0-b5", "version": "0.15.0-b7",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "wled", "name": "wled",
"version": "0.15.0-b5", "version": "0.15.0-b7",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"clean-css": "^5.3.3", "clean-css": "^5.3.3",

View File

@ -1,6 +1,6 @@
{ {
"name": "wled", "name": "wled",
"version": "0.15.0-b5", "version": "0.15.0-b7",
"description": "Tools for WLED project", "description": "Tools for WLED project",
"main": "tools/cdata.js", "main": "tools/cdata.js",
"directories": { "directories": {
@ -27,5 +27,8 @@
"html-minifier-terser": "^7.2.0", "html-minifier-terser": "^7.2.0",
"inliner": "^1.13.1", "inliner": "^1.13.1",
"nodemon": "^3.1.7" "nodemon": "^3.1.7"
},
"engines": {
"node": ">=20.0.0"
} }
} }

View File

@ -19,8 +19,9 @@ def _create_dirs(dirs=["map", "release", "firmware"]):
os.makedirs(os.path.join(OUTPUT_DIR, d), exist_ok=True) os.makedirs(os.path.join(OUTPUT_DIR, d), exist_ok=True)
def create_release(source): def create_release(source):
release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME") release_name_def = _get_cpp_define_value(env, "WLED_RELEASE_NAME")
if release_name: if release_name_def:
release_name = release_name_def.replace("\\\"", "")
version = _get_cpp_define_value(env, "WLED_VERSION") version = _get_cpp_define_value(env, "WLED_VERSION")
release_file = os.path.join(OUTPUT_DIR, "release", f"WLED_{version}_{release_name}.bin") release_file = os.path.join(OUTPUT_DIR, "release", f"WLED_{version}_{release_name}.bin")
release_gz_file = release_file + ".gz" release_gz_file = release_file + ".gz"

View File

@ -197,6 +197,7 @@ build_flags =
; decrease code cache size and increase IRAM to fit all pixel functions ; 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 ;; 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 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 = lib_deps =
#https://github.com/lorol/LITTLEFS.git #https://github.com/lorol/LITTLEFS.git
@ -260,6 +261,7 @@ lib_deps =
${env.lib_deps} ${env.lib_deps}
# additional build flags for audioreactive # additional build flags for audioreactive
AR_build_flags = -D USERMOD_AUDIOREACTIVE AR_build_flags = -D USERMOD_AUDIOREACTIVE
-D sqrt_internal=sqrtf ;; -fsingle-precision-constant ;; forces ArduinoFFT to use float math (2x faster)
AR_lib_deps = kosme/arduinoFFT @ 2.0.1 AR_lib_deps = kosme/arduinoFFT @ 2.0.1
[esp32_idf_V4] [esp32_idf_V4]
@ -343,7 +345,7 @@ platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages} platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_4m1m} board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.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} lib_deps = ${esp8266.lib_deps}
monitor_filters = esp8266_exception_decoder monitor_filters = esp8266_exception_decoder
@ -352,13 +354,13 @@ extends = env:nodemcuv2
;; using platform version and build options from WLED 0.14.0 ;; using platform version and build options from WLED 0.14.0
platform = ${esp8266.platform_compat} platform = ${esp8266.platform_compat}
platform_packages = ${esp8266.platform_packages_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 ;; lib_deps = ${esp8266.lib_deps_compat} ;; experimental - use older NeoPixelBus 2.7.9
[env:nodemcuv2_160] [env:nodemcuv2_160]
extends = env:nodemcuv2 extends = env:nodemcuv2
board_build.f_cpu = 160000000L board_build.f_cpu = 160000000L
build_flags = ${common.build_flags} ${esp8266.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 -D USERMOD_AUDIOREACTIVE
[env:esp8266_2m] [env:esp8266_2m]
@ -367,7 +369,7 @@ platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages} platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k} board_build.ldscript = ${common.ldscript_2m512k}
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.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} lib_deps = ${esp8266.lib_deps}
[env:esp8266_2m_compat] [env:esp8266_2m_compat]
@ -375,12 +377,12 @@ extends = env:esp8266_2m
;; using platform version and build options from WLED 0.14.0 ;; using platform version and build options from WLED 0.14.0
platform = ${esp8266.platform_compat} platform = ${esp8266.platform_compat}
platform_packages = ${esp8266.platform_packages_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] [env:esp8266_2m_160]
extends = env:esp8266_2m extends = env:esp8266_2m
board_build.f_cpu = 160000000L board_build.f_cpu = 160000000L
build_flags = ${common.build_flags} ${esp8266.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 -D USERMOD_AUDIOREACTIVE
[env:esp01_1m_full] [env:esp01_1m_full]
@ -389,7 +391,7 @@ platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages} platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_1m128k} board_build.ldscript = ${common.ldscript_1m128k}
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.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 ; -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} 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 ;; using platform version and build options from WLED 0.14.0
platform = ${esp8266.platform_compat} platform = ${esp8266.platform_compat}
platform_packages = ${esp8266.platform_packages_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] [env:esp01_1m_full_160]
extends = env:esp01_1m_full extends = env:esp01_1m_full
board_build.f_cpu = 160000000L board_build.f_cpu = 160000000L
build_flags = ${common.build_flags} ${esp8266.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 USERMOD_AUDIOREACTIVE
; -D WLED_USE_REAL_MATH ;; may fix wrong sunset/sunrise times, at the cost of 7064 bytes FLASH and 975 bytes RAM ; -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 = ${esp32.platform}
platform_packages = ${esp32.platform_packages} platform_packages = ${esp32.platform_packages}
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32.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} ${esp32.AR_build_flags}
lib_deps = ${esp32.lib_deps} lib_deps = ${esp32.lib_deps}
${esp32.AR_lib_deps} ${esp32.AR_lib_deps}
@ -424,7 +426,7 @@ board = esp32dev
platform = ${esp32_idf_V4.platform} platform = ${esp32_idf_V4.platform}
platform_packages = ${esp32_idf_V4.platform_packages} platform_packages = ${esp32_idf_V4.platform_packages}
build_unflags = ${common.build_unflags} 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} ${esp32.AR_build_flags}
lib_deps = ${esp32_idf_V4.lib_deps} lib_deps = ${esp32_idf_V4.lib_deps}
${esp32.AR_lib_deps} ${esp32.AR_lib_deps}
@ -440,7 +442,7 @@ board = esp32dev
platform = ${esp32_idf_V4.platform} platform = ${esp32_idf_V4.platform}
platform_packages = ${esp32_idf_V4.platform_packages} platform_packages = ${esp32_idf_V4.platform_packages}
build_unflags = ${common.build_unflags} 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 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} ${esp32.AR_build_flags}
lib_deps = ${esp32_idf_V4.lib_deps} lib_deps = ${esp32_idf_V4.lib_deps}
${esp32.AR_lib_deps} ${esp32.AR_lib_deps}
@ -456,7 +458,7 @@ board_build.flash_mode = dio
;platform = ${esp32.platform} ;platform = ${esp32.platform}
;platform_packages = ${esp32.platform_packages} ;platform_packages = ${esp32.platform_packages}
;build_unflags = ${common.build_unflags} ;build_unflags = ${common.build_unflags}
;build_flags = ${common.build_flags} ${esp32.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} ; ${esp32.AR_build_flags}
;lib_deps = ${esp32.lib_deps} ;lib_deps = ${esp32.lib_deps}
; ${esp32.AR_lib_deps} ; ${esp32.AR_lib_deps}
@ -471,7 +473,7 @@ platform = ${esp32.platform}
platform_packages = ${esp32.platform_packages} platform_packages = ${esp32.platform_packages}
upload_speed = 921600 upload_speed = 921600
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32.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 ; -D WLED_DISABLE_ESPNOW ;; ESP-NOW requires wifi, may crash with ethernet only
${esp32.AR_build_flags} ${esp32.AR_build_flags}
lib_deps = ${esp32.lib_deps} lib_deps = ${esp32.lib_deps}
@ -487,7 +489,7 @@ board_build.f_flash = 80000000L
board_build.flash_mode = qio board_build.flash_mode = qio
board_build.partitions = ${esp32.extended_partitions} board_build.partitions = ${esp32.extended_partitions}
build_unflags = ${common.build_unflags} 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 -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 -D DATA_PINS=25
${esp32.AR_build_flags} ${esp32.AR_build_flags}
@ -501,7 +503,7 @@ platform_packages = ${esp32c3.platform_packages}
framework = arduino framework = arduino
board = esp32-c3-devkitm-1 board = esp32-c3-devkitm-1
board_build.partitions = ${esp32.default_partitions} 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 -D WLED_WATCHDOG_TIMEOUT=0
-DLOLIN_WIFI_FIX ; seems to work much better with this -DLOLIN_WIFI_FIX ; seems to work much better with this
-DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB -DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB
@ -518,7 +520,7 @@ platform = ${esp32s3.platform}
platform_packages = ${esp32s3.platform_packages} platform_packages = ${esp32s3.platform_packages}
upload_speed = 921600 upload_speed = 921600
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_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 CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0
;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip ;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
@ -541,7 +543,7 @@ platform = ${esp32s3.platform}
platform_packages = ${esp32s3.platform_packages} platform_packages = ${esp32s3.platform_packages}
upload_speed = 921600 upload_speed = 921600
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_8MB_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 CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0
;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip ;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
@ -554,6 +556,33 @@ board_build.f_flash = 80000000L
board_build.flash_mode = qio board_build.flash_mode = qio
monitor_filters = esp32_exception_decoder monitor_filters = esp32_exception_decoder
[env:esp32S3_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] [env:esp32s3_4M_qspi]
;; ESP32-S3, with 4MB FLASH and <= 4MB PSRAM (memory_type: qio_qspi) ;; ESP32-S3, with 4MB FLASH and <= 4MB PSRAM (memory_type: qio_qspi)
board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM
@ -561,7 +590,7 @@ platform = ${esp32s3.platform}
platform_packages = ${esp32s3.platform_packages} platform_packages = ${esp32s3.platform_packages}
upload_speed = 921600 upload_speed = 921600
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_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") -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
-DBOARD_HAS_PSRAM -DBOARD_HAS_PSRAM
-DLOLIN_WIFI_FIX ; seems to work much better with this -DLOLIN_WIFI_FIX ; seems to work much better with this
@ -582,7 +611,7 @@ board_build.partitions = ${esp32.default_partitions}
board_build.flash_mode = qio board_build.flash_mode = qio
board_build.f_flash = 80000000L board_build.f_flash = 80000000L
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=ESP32-S2 build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S2\"
-DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_CDC_ON_BOOT=1
-DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0
-DARDUINO_USB_DFU_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0

View File

@ -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. ; *** 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 ; 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 ; disable specific features
; -D WLED_DISABLE_OTA ; -D WLED_DISABLE_OTA
@ -111,7 +111,6 @@ build_flags = ${common.build_flags} ${esp8266.build_flags}
; ;
; Use 4 Line Display usermod with SPI display ; Use 4 Line Display usermod with SPI display
; -D USERMOD_FOUR_LINE_DISPLAY ; -D USERMOD_FOUR_LINE_DISPLAY
; -D USE_ALT_DISPlAY # mandatory
; -DFLD_SPI_DEFAULT ; -DFLD_SPI_DEFAULT
; -D FLD_TYPE=SSD1306_SPI64 ; -D FLD_TYPE=SSD1306_SPI64
; -D FLD_PIN_CLOCKSPI=14 ; -D FLD_PIN_CLOCKSPI=14
@ -377,7 +376,6 @@ build_flags = ${common.build_flags} ${esp32.build_flags}
-D USERMOD_DALLASTEMPERATURE -D USERMOD_DALLASTEMPERATURE
-D USERMOD_FOUR_LINE_DISPLAY -D USERMOD_FOUR_LINE_DISPLAY
-D TEMPERATURE_PIN=23 -D TEMPERATURE_PIN=23
-D USE_ALT_DISPlAY ; new versions of USERMOD_FOUR_LINE_DISPLAY and USERMOD_ROTARY_ENCODER_UI
-D USERMOD_AUDIOREACTIVE -D USERMOD_AUDIOREACTIVE
lib_deps = ${esp32.lib_deps} lib_deps = ${esp32.lib_deps}
OneWire@~2.3.5 OneWire@~2.3.5

View File

@ -61,7 +61,7 @@ See [here](https://kno.wled.ge/basics/compatible-hardware)!
## ✌️ Other ## ✌️ Other
Licensed under the MIT license Licensed under the EUPL v1.2 license
Credits [here](https://kno.wled.ge/about/contributors/)! Credits [here](https://kno.wled.ge/about/contributors/)!
Join the Discord server to discuss everything about WLED! Join the Discord server to discuss everything about WLED!
@ -80,5 +80,5 @@ If WLED really brightens up your day, you can [![](https://img.shields.io/badge/
If you are prone to photosensitive epilepsy, we recommended you do **not** use this software. If you are prone to photosensitive epilepsy, we recommended you do **not** use this software.
If you still want to try, don't use strobe, lighting or noise modes or high effect speed settings. If you still want to try, don't use strobe, lighting or noise modes or high effect speed settings.
As per the MIT license, I assume no liability for any damage to you or any other person or equipment. As per the EUPL license, I assume no liability for any damage to you or any other person or equipment.

View File

@ -101,6 +101,7 @@ function adoptVersionAndRepo(html) {
async function minify(str, type = "plain") { async function minify(str, type = "plain") {
const options = { const options = {
collapseWhitespace: true, collapseWhitespace: true,
conservativeCollapse: true, // preserve spaces in text
collapseBooleanAttributes: true, collapseBooleanAttributes: true,
collapseInlineTagWhitespace: true, collapseInlineTagWhitespace: true,
minifyCSS: true, minifyCSS: true,

View File

@ -425,10 +425,10 @@ class Animated_Staircase : public Usermod {
} }
void appendConfigData() { void appendConfigData() {
//oappend(SET_F("dd=addDropdown('staircase','selectfield');")); //oappend(F("dd=addDropdown('staircase','selectfield');"));
//oappend(SET_F("addOption(dd,'1st value',0);")); //oappend(F("addOption(dd,'1st value',0);"));
//oappend(SET_F("addOption(dd,'2nd value',1);")); //oappend(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("addInfo('staircase:selectfield',1,'additional info');")); // 0 is field type, 1 is actual field
} }

View File

@ -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); // 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*/ /* Dropdown for Celsius/Fahrenheit*/
oappend(SET_F("dd=addDropdown('")); oappend(F("dd=addDropdown('"));
oappend(UMOD_NAME); oappend(UMOD_NAME);
oappend(SET_F("','")); oappend(F("','"));
oappend(_nameTempScale); oappend(_nameTempScale);
oappend(SET_F("');")); oappend(F("');"));
oappend(SET_F("addOption(dd,'Celsius',0);")); oappend(F("addOption(dd,'Celsius',0);"));
oappend(SET_F("addOption(dd,'Fahrenheit',1);")); oappend(F("addOption(dd,'Fahrenheit',1);"));
/* i²C Address*/ /* i²C Address*/
oappend(SET_F("dd=addDropdown('")); oappend(F("dd=addDropdown('"));
oappend(UMOD_NAME); oappend(UMOD_NAME);
oappend(SET_F("','")); oappend(F("','"));
oappend(_nameI2CAdr); oappend(_nameI2CAdr);
oappend(SET_F("');")); oappend(F("');"));
oappend(SET_F("addOption(dd,'0x76',0x76);")); oappend(F("addOption(dd,'0x76',0x76);"));
oappend(SET_F("addOption(dd,'0x77',0x77);")); oappend(F("addOption(dd,'0x77',0x77);"));
} }
/** /**

View File

@ -478,29 +478,29 @@ class UsermodBattery : public Usermod
void appendConfigData() void appendConfigData()
{ {
// Total: 462 Bytes // Total: 462 Bytes
oappend(SET_F("td=addDropdown('Battery','type');")); // 34 Bytes oappend(F("td=addDropdown('Battery','type');")); // 34 Bytes
oappend(SET_F("addOption(td,'Unkown','0');")); // 28 Bytes oappend(F("addOption(td,'Unkown','0');")); // 28 Bytes
oappend(SET_F("addOption(td,'LiPo','1');")); // 26 Bytes oappend(F("addOption(td,'LiPo','1');")); // 26 Bytes
oappend(SET_F("addOption(td,'LiOn','2');")); // 26 Bytes oappend(F("addOption(td,'LiOn','2');")); // 26 Bytes
oappend(SET_F("addInfo('Battery:type',1,'<small style=\"color:orange\">requires reboot</small>');")); // 81 Bytes oappend(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(F("addInfo('Battery:min-voltage',1,'v');")); // 38 Bytes
oappend(SET_F("addInfo('Battery:max-voltage',1,'v');")); // 38 Bytes oappend(F("addInfo('Battery:max-voltage',1,'v');")); // 38 Bytes
oappend(SET_F("addInfo('Battery:interval',1,'ms');")); // 36 Bytes oappend(F("addInfo('Battery:interval',1,'ms');")); // 36 Bytes
oappend(SET_F("addInfo('Battery:HA-discovery',1,'');")); // 38 Bytes oappend(F("addInfo('Battery:HA-discovery',1,'');")); // 38 Bytes
oappend(SET_F("addInfo('Battery:auto-off:threshold',1,'%');")); // 45 Bytes oappend(F("addInfo('Battery:auto-off:threshold',1,'%');")); // 45 Bytes
oappend(SET_F("addInfo('Battery:indicator:threshold',1,'%');")); // 46 Bytes oappend(F("addInfo('Battery:indicator:threshold',1,'%');")); // 46 Bytes
oappend(SET_F("addInfo('Battery:indicator:duration',1,'s');")); // 45 Bytes oappend(F("addInfo('Battery:indicator:duration',1,'s');")); // 45 Bytes
// this option list would exeed the oappend() buffer // this option list would exeed the oappend() buffer
// a list of all presets to select one from // a list of all presets to select one from
// oappend(SET_F("bd=addDropdown('Battery:low-power-indicator', 'preset');")); // oappend(F("bd=addDropdown('Battery:low-power-indicator', 'preset');"));
// the loop generates: oappend(SET_F("addOption(bd, 'preset name', preset id);")); // the loop generates: oappend(F("addOption(bd, 'preset name', preset id);"));
// for(int8_t i=1; i < 42; i++) { // for(int8_t i=1; i < 42; i++) {
// oappend(SET_F("addOption(bd, 'Preset#")); // oappend(F("addOption(bd, 'Preset#"));
// oappendi(i); // oappendi(i);
// oappend(SET_F("',")); // oappend(F("',"));
// oappendi(i); // oappendi(i);
// oappend(SET_F(");")); // oappend(F(");"));
// } // }
} }

View File

@ -287,11 +287,11 @@ class MyExampleUsermod : public Usermod {
*/ */
void appendConfigData() override 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(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":great")); oappend(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(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":testString")); oappend(F("',1,'enter any string you want');"));
oappend(SET_F("dd=addDropdown('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F("','testInt');")); oappend(F("dd=addDropdown('")); oappend(String(FPSTR(_name)).c_str()); oappend(F("','testInt');"));
oappend(SET_F("addOption(dd,'Nothing',0);")); oappend(F("addOption(dd,'Nothing',0);"));
oappend(SET_F("addOption(dd,'Everything',42);")); oappend(F("addOption(dd,'Everything',42);"));
} }

View File

@ -149,11 +149,11 @@ public:
void appendConfigData() void appendConfigData()
{ {
// Display 'ms' next to the 'Loop Interval' setting // 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 // 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 // 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) bool readFromConfig(JsonObject &root)

View File

@ -511,8 +511,8 @@ void PIRsensorSwitch::addToConfig(JsonObject &root)
void PIRsensorSwitch::appendConfigData() void PIRsensorSwitch::appendConfigData()
{ {
oappend(SET_F("addInfo('PIRsensorSwitch:HA-discovery',1,'HA=Home Assistant');")); // 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(SET_F("addInfo('PIRsensorSwitch:override',1,'Cancel timer on change');")); // 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++) { for (int i = 0; i < PIR_SENSOR_MAX_SENSORS; i++) {
char str[128]; char str[128];
sprintf_P(str, PSTR("addInfo('PIRsensorSwitch:pin[]',%d,'','#%d');"), i, i); sprintf_P(str, PSTR("addInfo('PIRsensorSwitch:pin[]',%d,'','#%d');"), i, i);

View File

@ -377,10 +377,10 @@ class St7789DisplayUsermod : public Usermod {
void appendConfigData() override { void appendConfigData() override {
oappend(SET_F("addInfo('ST7789:pin[]',0,'','SPI CS');")); oappend(F("addInfo('ST7789:pin[]',0,'','SPI CS');"));
oappend(SET_F("addInfo('ST7789:pin[]',1,'','SPI DC');")); oappend(F("addInfo('ST7789:pin[]',1,'','SPI DC');"));
oappend(SET_F("addInfo('ST7789:pin[]',2,'','SPI RST');")); oappend(F("addInfo('ST7789:pin[]',2,'','SPI RST');"));
oappend(SET_F("addInfo('ST7789:pin[]',3,'','SPI BL');")); oappend(F("addInfo('ST7789:pin[]',3,'','SPI BL');"));
} }
/* /*

View File

@ -435,10 +435,10 @@ bool UsermodTemperature::readFromConfig(JsonObject &root) {
} }
void UsermodTemperature::appendConfigData() { void UsermodTemperature::appendConfigData() {
oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":")); oappend(String(FPSTR(_parasite)).c_str()); oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(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(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(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(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("',1,'<i>(for external MOSFET)</i>');")); // 0 is field type, 1 is actual field
} }
float UsermodTemperature::getTemperature() { float UsermodTemperature::getTemperature() {

View File

@ -191,8 +191,8 @@ constexpr uint16_t samplesFFT_2 = 256; // meaningfull part of FFT resul
#define LOG_256 5.54517744f // log(256) #define LOG_256 5.54517744f // log(256)
// These are the input and output vectors. Input vectors receive computed results from FFT. // 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* vReal = nullptr; // FFT sample inputs / freq output - these are our raw result bins
static float vImag[samplesFFT] = {0.0f}; // imaginary parts static float* vImag = nullptr; // imaginary parts
// Create FFT object // Create FFT object
// lib_deps += https://github.com/kosme/arduinoFFT#develop @ 1.9.2 // 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_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 // #define FFT_SQRT_APPROXIMATION // enables "quake3" style inverse sqrt - slower on ESP32
// Below options are forcing ArduinoFFT to use sqrtf() instead of sqrt() // 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 - since v2.0.0 this must be done in build_flags
#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);
#include <arduinoFFT.h> // FFT object is created in FFTcode
// Helper functions // Helper functions
// compute average of several FFT result bins // compute average of several FFT result bins
@ -226,6 +221,18 @@ void FFTcode(void * parameter)
{ {
DEBUGSR_PRINT("FFT started on core: "); DEBUGSR_PRINTLN(xPortGetCoreID()); 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 // see https://www.freertos.org/vtaskdelayuntil.html
const TickType_t xFrequency = FFT_MIN_CYCLE * portTICK_PERIOD_MS; 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 // get a fresh batch of samples from I2S
if (audioSource) audioSource->getSamples(vReal, samplesFFT); 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 defined(WLED_DEBUG) || defined(SR_DEBUG)
if (start < esp_timer_get_time()) { // filter out overflows if (start < esp_timer_get_time()) { // filter out overflows
@ -265,8 +273,6 @@ void FFTcode(void * parameter)
// find highest sample in the batch // find highest sample in the batch
float maxSample = 0.0f; // max sample from FFT batch float maxSample = 0.0f; // max sample from FFT batch
for (int i=0; i < samplesFFT; i++) { 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 // 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 ((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]); if (fabsf((float)vReal[i]) > maxSample) maxSample = fabsf((float)vReal[i]);
@ -297,7 +303,7 @@ void FFTcode(void * parameter)
#endif #endif
} else { // noise gate closed - only clear results as FFT was skipped. MIC samples are still valid when we do this. } 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_MajorPeak = 1;
FFT_Magnitude = 0.001; FFT_Magnitude = 0.001;
} }
@ -1879,57 +1885,59 @@ class AudioReactive : public Usermod {
} }
void appendConfigData() override void appendConfigData(Print& uiScript) override
{ {
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 #ifdef ARDUINO_ARCH_ESP32
oappend(SET_F("dd=addDropdown('AudioReactive','digitalmic:type');")); 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) #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 #endif
oappend(SET_F("addOption(dd,'Generic I2S',1);")); uiScript.print(F("addOption(dd,'Generic I2S',1);"));
oappend(SET_F("addOption(dd,'ES7243',2);")); uiScript.print(F("addOption(dd,'ES7243',2);"));
oappend(SET_F("addOption(dd,'SPH0654',3);")); uiScript.print(F("addOption(dd,'SPH0654',3);"));
oappend(SET_F("addOption(dd,'Generic I2S with Mclk',4);")); uiScript.print(F("addOption(dd,'Generic I2S with Mclk',4);"));
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) #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 #endif
oappend(SET_F("addOption(dd,'ES8388',6);")); uiScript.print(F("addOption(dd,'ES8388',6);"));
oappend(SET_F("dd=addDropdown('AudioReactive','config:AGC');")); uiScript.print(F("dd=addDropdown(ux,'config:AGC');"));
oappend(SET_F("addOption(dd,'Off',0);")); uiScript.print(F("addOption(dd,'Off',0);"));
oappend(SET_F("addOption(dd,'Normal',1);")); uiScript.print(F("addOption(dd,'Normal',1);"));
oappend(SET_F("addOption(dd,'Vivid',2);")); uiScript.print(F("addOption(dd,'Vivid',2);"));
oappend(SET_F("addOption(dd,'Lazy',3);")); uiScript.print(F("addOption(dd,'Lazy',3);"));
oappend(SET_F("dd=addDropdown('AudioReactive','dynamics:limiter');")); uiScript.print(F("dd=addDropdown(ux,'dynamics:limiter');"));
oappend(SET_F("addOption(dd,'Off',0);")); uiScript.print(F("addOption(dd,'Off',0);"));
oappend(SET_F("addOption(dd,'On',1);")); uiScript.print(F("addOption(dd,'On',1);"));
oappend(SET_F("addInfo('AudioReactive:dynamics:limiter',0,' On ');")); // 0 is field type, 1 is actual field uiScript.print(F("addInfo(ux+':dynamics:limiter',0,' On ');")); // 0 is field type, 1 is actual field
oappend(SET_F("addInfo('AudioReactive:dynamics:rise',1,'ms <i>(&#x266A; effects only)</i>');")); uiScript.print(F("addInfo(ux+':dynamics:rise',1,'ms <i>(&#x266A; effects only)</i>');"));
oappend(SET_F("addInfo('AudioReactive:dynamics:fall',1,'ms <i>(&#x266A; effects only)</i>');")); uiScript.print(F("addInfo(ux+':dynamics:fall',1,'ms <i>(&#x266A; effects only)</i>');"));
oappend(SET_F("dd=addDropdown('AudioReactive','frequency:scale');")); uiScript.print(F("dd=addDropdown(ux,'frequency:scale');"));
oappend(SET_F("addOption(dd,'None',0);")); uiScript.print(F("addOption(dd,'None',0);"));
oappend(SET_F("addOption(dd,'Linear (Amplitude)',2);")); uiScript.print(F("addOption(dd,'Linear (Amplitude)',2);"));
oappend(SET_F("addOption(dd,'Square Root (Energy)',3);")); uiScript.print(F("addOption(dd,'Square Root (Energy)',3);"));
oappend(SET_F("addOption(dd,'Logarithmic (Loudness)',1);")); uiScript.print(F("addOption(dd,'Logarithmic (Loudness)',1);"));
#endif #endif
oappend(SET_F("dd=addDropdown('AudioReactive','sync:mode');")); uiScript.print(F("dd=addDropdown(ux,'sync:mode');"));
oappend(SET_F("addOption(dd,'Off',0);")); uiScript.print(F("addOption(dd,'Off',0);"));
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
oappend(SET_F("addOption(dd,'Send',1);")); uiScript.print(F("addOption(dd,'Send',1);"));
#endif #endif
oappend(SET_F("addOption(dd,'Receive',2);")); uiScript.print(F("addOption(dd,'Receive',2);"));
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
oappend(SET_F("addInfo('AudioReactive:digitalmic:type',1,'<i>requires reboot!</i>');")); // 0 is field type, 1 is actual field uiScript.print(F("addInfo(ux+':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');")); uiScript.print(F("addInfo(uxp,0,'<i>sd/data/dout</i>','I2S SD');"));
oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',1,'<i>ws/clk/lrck</i>','I2S WS');")); uiScript.print(F("addInfo(uxp,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(uxp,2,'<i>sck/bclk</i>','I2S SCK');"));
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) #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 #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
#endif #endif
} }

View File

@ -30,7 +30,7 @@ There are however plans to create a lightweight audioreactive for the 8266, with
### using latest _arduinoFFT_ library version 2.x ### using latest _arduinoFFT_ library version 2.x
The latest arduinoFFT release version should be used for audioreactive. 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` * `lib_deps`= `kosme/arduinoFFT @ 2.0.1`
## Configuration ## Configuration

View File

@ -305,14 +305,14 @@ class BobLightUsermod : public Usermod {
} }
void appendConfigData() override { void appendConfigData() override {
//oappend(SET_F("dd=addDropdown('usermod','selectfield');")); //oappend(F("dd=addDropdown('usermod','selectfield');"));
//oappend(SET_F("addOption(dd,'1st value',0);")); //oappend(F("addOption(dd,'1st value',0);"));
//oappend(SET_F("addOption(dd,'2nd value',1);")); //oappend(F("addOption(dd,'2nd value',1);"));
oappend(SET_F("addInfo('BobLight:top',1,'LEDs');")); // 0 is field type, 1 is actual field oappend(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(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(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(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("addInfo('BobLight:pct',1,'Depth of scan [%]');")); // 0 is field type, 1 is actual field
} }
void addToConfig(JsonObject& root) override { void addToConfig(JsonObject& root) override {

View File

@ -264,7 +264,7 @@ void MultiRelay::handleOffTimer() {
void MultiRelay::InitHtmlAPIHandle() { // https://github.com/me-no-dev/ESPAsyncWebServer void MultiRelay::InitHtmlAPIHandle() { // https://github.com/me-no-dev/ESPAsyncWebServer
DEBUG_PRINTLN(F("Relays: Initialize HTML API")); 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")); DEBUG_PRINTLN(F("Relays: HTML API"));
String janswer; String janswer;
String error = ""; String error = "";
@ -765,10 +765,10 @@ void MultiRelay::addToConfig(JsonObject &root) {
} }
void MultiRelay::appendConfigData() { void MultiRelay::appendConfigData() {
oappend(SET_F("addInfo('MultiRelay:PCF8574-address',1,'<i>(not hex!)</i>');")); oappend(F("addInfo('MultiRelay:PCF8574-address',1,'<i>(not hex!)</i>');"));
oappend(SET_F("addInfo('MultiRelay:broadcast-sec',1,'(MQTT message)');")); oappend(F("addInfo('MultiRelay:broadcast-sec',1,'(MQTT message)');"));
//oappend(SET_F("addInfo('MultiRelay:relay-0:pin',1,'(use -1 for PCF8574)');")); //oappend(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("d.extra.push({'MultiRelay':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});"));
} }
/** /**

View File

@ -387,23 +387,23 @@ class PixelsDiceTrayUsermod : public Usermod {
// To work around this, add info text to the end of the preceding item. // 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. // 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 " "addInfo('DiceTray:ble_scan_duration',1,'<br><br><i>Set to \"*\" to "
"connect to any die.<br>Leave Blank to disable.</i><br><i " "connect to any die.<br>Leave Blank to disable.</i><br><i "
"class=\"warn\">Saving will replace \"*\" with die names.</i>','');")); "class=\"warn\">Saving will replace \"*\" with die names.</i>','');"));
#if USING_TFT_DISPLAY #if USING_TFT_DISPLAY
oappend(SET_F("ddr=addDropdown('DiceTray','rotation');")); oappend(F("ddr=addDropdown('DiceTray','rotation');"));
oappend(SET_F("addOption(ddr,'0 deg',0);")); oappend(F("addOption(ddr,'0 deg',0);"));
oappend(SET_F("addOption(ddr,'90 deg',1);")); oappend(F("addOption(ddr,'90 deg',1);"));
oappend(SET_F("addOption(ddr,'180 deg',2);")); oappend(F("addOption(ddr,'180 deg',2);"));
oappend(SET_F("addOption(ddr,'270 deg',3);")); oappend(F("addOption(ddr,'270 deg',3);"));
oappend(SET_F( oappend(F(
"addInfo('DiceTray:rotation',1,'<br><i class=\"warn\">DO NOT CHANGE " "addInfo('DiceTray:rotation',1,'<br><i class=\"warn\">DO NOT CHANGE "
"SPI PINS.</i><br><i class=\"warn\">CHANGES ARE IGNORED.</i>','');")); "SPI PINS.</i><br><i class=\"warn\">CHANGES ARE IGNORED.</i>','');"));
oappend(SET_F("addInfo('TFT:pin[]',0,'','SPI CS');")); oappend(F("addInfo('TFT:pin[]',0,'','SPI CS');"));
oappend(SET_F("addInfo('TFT:pin[]',1,'','SPI DC');")); oappend(F("addInfo('TFT:pin[]',1,'','SPI DC');"));
oappend(SET_F("addInfo('TFT:pin[]',2,'','SPI RST');")); oappend(F("addInfo('TFT:pin[]',2,'','SPI RST');"));
oappend(SET_F("addInfo('TFT:pin[]',3,'','SPI BL');")); oappend(F("addInfo('TFT:pin[]',3,'','SPI BL');"));
#endif #endif
} }

View File

@ -310,22 +310,22 @@ void ShtUsermod::onMqttConnect(bool sessionPresent) {
* @return void * @return void
*/ */
void ShtUsermod::appendConfigData() { void ShtUsermod::appendConfigData() {
oappend(SET_F("dd=addDropdown('")); oappend(F("dd=addDropdown('"));
oappend(_name); oappend(_name);
oappend(SET_F("','")); oappend(F("','"));
oappend(_shtType); oappend(_shtType);
oappend(SET_F("');")); oappend(F("');"));
oappend(SET_F("addOption(dd,'SHT30',0);")); oappend(F("addOption(dd,'SHT30',0);"));
oappend(SET_F("addOption(dd,'SHT31',1);")); oappend(F("addOption(dd,'SHT31',1);"));
oappend(SET_F("addOption(dd,'SHT35',2);")); oappend(F("addOption(dd,'SHT35',2);"));
oappend(SET_F("addOption(dd,'SHT85',3);")); oappend(F("addOption(dd,'SHT85',3);"));
oappend(SET_F("dd=addDropdown('")); oappend(F("dd=addDropdown('"));
oappend(_name); oappend(_name);
oappend(SET_F("','")); oappend(F("','"));
oappend(_unitOfTemp); oappend(_unitOfTemp);
oappend(SET_F("');")); oappend(F("');"));
oappend(SET_F("addOption(dd,'Celsius',0);")); oappend(F("addOption(dd,'Celsius',0);"));
oappend(SET_F("addOption(dd,'Fahrenheit',1);")); oappend(F("addOption(dd,'Fahrenheit',1);"));
} }
/** /**

View File

@ -96,7 +96,7 @@ void setup() {
jsonTransitionOnce = true; jsonTransitionOnce = true;
strip.setTransition(0); //no transition strip.setTransition(0); //no transition
effectCurrent = FX_MODE_COLOR_WIPE; effectCurrent = FX_MODE_COLOR_WIPE;
resetTimebase(); //make sure wipe starts from beginning strip.resetTimebase(); //make sure wipe starts from beginning
//set wipe direction //set wipe direction
Segment& seg = strip.getSegment(0); Segment& seg = strip.getSegment(0);

View File

@ -86,7 +86,7 @@ void startWipe()
bri = briLast; //turn on bri = briLast; //turn on
transitionDelayTemp = 0; //no transition transitionDelayTemp = 0; //no transition
effectCurrent = FX_MODE_COLOR_WIPE; effectCurrent = FX_MODE_COLOR_WIPE;
resetTimebase(); //make sure wipe starts from beginning strip.resetTimebase(); //make sure wipe starts from beginning
//set wipe direction //set wipe direction
Segment& seg = strip.getSegment(0); Segment& seg = strip.getSegment(0);

View File

@ -7,11 +7,12 @@ platform = ${esp32.platform}
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = build_flags =
${common.build_flags_esp32} ${common.build_flags_esp32}
-D USERMOD_FOUR_LINE_DISPLAY -D USE_ALT_DISPlAY -D USERMOD_FOUR_LINE_DISPLAY
-D USERMOD_ROTARY_ENCODER_UI -D ENCODER_DT_PIN=18 -D ENCODER_CLK_PIN=5 -D ENCODER_SW_PIN=19 -D FLD_TYPE=SH1106
upload_speed = 460800 -D I2CSCLPIN=27
-D I2CSDAPIN=26
lib_deps = lib_deps =
${esp32.lib_deps} ${esp32.lib_deps}
U8g2@~2.34.4 U8g2@~2.34.4
Wire Wire

View File

@ -1,16 +1,8 @@
# I2C/SPI 4 Line Display Usermod ALT # I2C/SPI 4 Line Display Usermod ALT
Thank you to the authors of the original version of these usermods. It would not have been possible without them! This usermod could be used in compination with `usermod_v2_rotary_encoder_ui_ALT`.
"usermod_v2_four_line_display"
"usermod_v2_rotary_encoder_ui"
The core of these usermods are a copy of the originals. The main changes are to the FourLineDisplay usermod. ## Functionalities
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.
Press the encoder to cycle through the options: Press the encoder to cycle through the options:
* Brightness * Brightness
@ -18,26 +10,18 @@ Press the encoder to cycle through the options:
* Intensity * Intensity
* Palette * Palette
* Effect * Effect
* Main Color (only if display is used) * Main Color
* Saturation (only if display is used) * 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) [See the pair of usermods in action](https://www.youtube.com/watch?v=ulZnBt9z3TI)
## Installation ## Installation
Please refer to the original `usermod_v2_rotary_encoder_ui` readme for the main instructions. Copy the example `platformio_override.sample.ini` to the root directory of your particular build.
Copy the example `platformio_override.sample.ini` from the usermod_v2_rotary_encoder_ui_ALT folder to the root directory of your particular build and rename it to `platformio_override.ini`.
This file should be placed in the same directory as `platformio.ini`.
Then, to activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE SENSITIVE) to the `usermods_list.cpp` file,
or add `-D USE_ALT_DISPlAY` to the original `platformio_override.ini.sample` file
## Configuration ## Configuration

View File

@ -1202,21 +1202,21 @@ void FourLineDisplayUsermod::onUpdateBegin(bool init) {
//} //}
void FourLineDisplayUsermod::appendConfigData() { void FourLineDisplayUsermod::appendConfigData() {
oappend(SET_F("dd=addDropdown('4LineDisplay','type');")); oappend(F("dd=addDropdown('4LineDisplay','type');"));
oappend(SET_F("addOption(dd,'None',0);")); oappend(F("addOption(dd,'None',0);"));
oappend(SET_F("addOption(dd,'SSD1306',1);")); oappend(F("addOption(dd,'SSD1306',1);"));
oappend(SET_F("addOption(dd,'SH1106',2);")); oappend(F("addOption(dd,'SH1106',2);"));
oappend(SET_F("addOption(dd,'SSD1306 128x64',3);")); oappend(F("addOption(dd,'SSD1306 128x64',3);"));
oappend(SET_F("addOption(dd,'SSD1305',4);")); oappend(F("addOption(dd,'SSD1305',4);"));
oappend(SET_F("addOption(dd,'SSD1305 128x64',5);")); oappend(F("addOption(dd,'SSD1305 128x64',5);"));
oappend(SET_F("addOption(dd,'SSD1309 128x64',9);")); oappend(F("addOption(dd,'SSD1309 128x64',9);"));
oappend(SET_F("addOption(dd,'SSD1306 SPI',6);")); oappend(F("addOption(dd,'SSD1306 SPI',6);"));
oappend(SET_F("addOption(dd,'SSD1306 SPI 128x64',7);")); oappend(F("addOption(dd,'SSD1306 SPI 128x64',7);"));
oappend(SET_F("addOption(dd,'SSD1309 SPI 128x64',8);")); oappend(F("addOption(dd,'SSD1309 SPI 128x64',8);"));
oappend(SET_F("addInfo('4LineDisplay:type',1,'<br><i class=\"warn\">Change may require reboot</i>','');")); oappend(F("addInfo('4LineDisplay:type',1,'<br><i class=\"warn\">Change may require reboot</i>','');"));
oappend(SET_F("addInfo('4LineDisplay:pin[]',0,'','SPI CS');")); oappend(F("addInfo('4LineDisplay:pin[]',0,'','SPI CS');"));
oappend(SET_F("addInfo('4LineDisplay:pin[]',1,'','SPI DC');")); oappend(F("addInfo('4LineDisplay:pin[]',1,'','SPI DC');"));
oappend(SET_F("addInfo('4LineDisplay:pin[]',2,'','SPI RST');")); oappend(F("addInfo('4LineDisplay:pin[]',2,'','SPI RST');"));
} }
/* /*

View File

@ -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

View File

@ -1,16 +1,8 @@
# Rotary Encoder UI Usermod ALT # 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! This usermod supports the UI of the `usermod_v2_rotary_encoder_ui_ALT`.
"usermod_v2_four_line_display"
"usermod_v2_rotary_encoder_ui"
The core of these usermods are a copy of the originals. The main changes are to the FourLineDisplay usermod. ## Functionalities
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.
Press the encoder to cycle through the options: Press the encoder to cycle through the options:
* Brightness * Brightness
@ -21,8 +13,7 @@ Press the encoder to cycle through the options:
* Main Color (only if display is used) * Main Color (only if display is used)
* Saturation (only if display is used) * Saturation (only if display is used)
Press and hold the encoder to display Network Info Press and hold the encoder to display Network Info. If AP is active, it will display the AP, SSID and Password
if AP is active, it will display the AP, SSID and Password
Also shows if the timer is enabled. Also shows if the timer is enabled.
@ -30,9 +21,7 @@ Also shows if the timer is enabled.
## Installation ## Installation
Copy the example `platformio_override.sample.ini` to the root directory of your particular build and rename it to `platformio_override.ini`. Copy the example `platformio_override.sample.ini` to the root directory of your particular build.
To activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE SENSITIVE) to the `usermods_list.cpp` file, or add `-D USE_ALT_DISPlAY` to your `platformio_override.ini` file
### Define Your Options ### 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 * `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 also tells this usermod that the display is available
(see the Four Line Display usermod `readme.md` for more details) (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_DT_PIN` - defaults to 18
* `ENCODER_CLK_PIN` - defaults to 5 * `ENCODER_CLK_PIN` - defaults to 5
* `ENCODER_SW_PIN` - defaults to 19 * `ENCODER_SW_PIN` - defaults to 19
@ -50,7 +38,7 @@ To activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE
### PlatformIO requirements ### PlatformIO requirements
Note: the Four Line Display usermod requires the libraries `U8g2` and `Wire`. No special requirements.
## Change Log ## Change Log

View File

@ -1090,8 +1090,8 @@ void RotaryEncoderUIUsermod::addToConfig(JsonObject &root) {
} }
void RotaryEncoderUIUsermod::appendConfigData() { void RotaryEncoderUIUsermod::appendConfigData() {
oappend(SET_F("addInfo('Rotary-Encoder:PCF8574-address',1,'<i>(not hex!)</i>');")); oappend(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("d.extra.push({'Rotary-Encoder':{pin:[['P0',100],['P1',101],['P2',102],['P3',103],['P4',104],['P5',105],['P6',106],['P7',107]]}});"));
} }
/** /**

View File

@ -433,8 +433,8 @@ class WordClockUsermod : public Usermod
void appendConfigData() void appendConfigData()
{ {
oappend(SET_F("addInfo('WordClockUsermod:ledOffset', 1, 'Number of LEDs before the letters');")); oappend(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:Norddeutsch', 1, 'Viertel vor instead of Dreiviertel');"));
} }
/* /*

View File

@ -54,13 +54,13 @@ class WireguardUsermod : public Usermod {
} }
void appendConfigData() { void appendConfigData() {
oappend(SET_F("addInfo('WireGuard:host',1,'Server Hostname');")); // 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(SET_F("addInfo('WireGuard:port',1,'Server Port');")); // 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(SET_F("addInfo('WireGuard:ip',1,'Device IP');")); // 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(SET_F("addInfo('WireGuard:psk',1,'Pre Shared Key (optional)');")); // 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(SET_F("addInfo('WireGuard:pem',1,'Private Key');")); // 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(SET_F("addInfo('WireGuard:pub',1,'Public 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(SET_F("addInfo('WireGuard:tz',1,'POSIX timezone string');")); // 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) { void addToConfig(JsonObject& root) {

View File

@ -2,24 +2,10 @@
WS2812FX.cpp contains all effect methods WS2812FX.cpp contains all effect methods
Harm Aldick - 2016 Harm Aldick - 2016
www.aldick.org www.aldick.org
LICENSE
The MIT License (MIT)
Copyright (c) 2016 Harm Aldick Copyright (c) 2016 Harm Aldick
Permission is hereby granted, free of charge, to any person obtaining a copy Licensed under the EUPL v. 1.2 or later
of this software and associated documentation files (the "Software"), to deal Adapted from code originally licensed under the MIT license
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.
Modified heavily for WLED Modified heavily for WLED
*/ */
@ -1980,7 +1966,7 @@ uint16_t mode_palette() {
const bool inputAnimateRotation = SEGMENT.check2; const bool inputAnimateRotation = SEGMENT.check2;
const bool inputAssumeSquare = SEGMENT.check3; 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 sinTheta = sinFunction(theta);
const mathType cosTheta = cosFunction(theta); const mathType cosTheta = cosFunction(theta);
@ -2030,8 +2016,8 @@ uint16_t mode_palette() {
colorIndex = ((inputSize - 112) * colorIndex) / 16; colorIndex = ((inputSize - 112) * colorIndex) / 16;
} }
// Finally, shift the palette a bit. // Finally, shift the palette a bit.
const int paletteOffset = (!inputAnimateShift) ? (inputShift-128) : (((strip.now * ((inputShift >> 3) +1)) & 0xFFFF) >> 8); const int paletteOffset = (!inputAnimateShift) ? (inputShift) : (((strip.now * ((inputShift >> 3) +1)) & 0xFFFF) >> 8);
colorIndex += paletteOffset; colorIndex -= paletteOffset;
const uint32_t color = SEGMENT.color_wheel((uint8_t)colorIndex); const uint32_t color = SEGMENT.color_wheel((uint8_t)colorIndex);
if (isMatrix) { if (isMatrix) {
SEGMENT.setPixelColorXY(x, y, color); SEGMENT.setPixelColorXY(x, y, color);
@ -2042,7 +2028,7 @@ uint16_t mode_palette() {
} }
return FRAMETIME; 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 // WLED limitation: Analog Clock overlay will NOT work when Fire2012 is active
@ -2520,9 +2506,9 @@ static uint16_t ripple_base() {
#endif #endif
{ {
int left = rippleorigin - propI -1; int left = rippleorigin - propI -1;
int right = rippleorigin + propI +3; int right = rippleorigin + propI +2;
for (int v = 0; v < 4; v++) { 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(left + v, color_blend(SEGMENT.getPixelColor(left + v), col, mag)); // TODO
SEGMENT.setPixelColor(right - v, color_blend(SEGMENT.getPixelColor(right - v), col, mag)); // TODO SEGMENT.setPixelColor(right - v, color_blend(SEGMENT.getPixelColor(right - v), col, mag)); // TODO
} }
@ -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 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 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; unsigned dataSize = sizeof(spark) * numSparks;
if (!SEGENV.allocateData(dataSize + sizeof(float))) return mode_static(); //allocation failed if (!SEGENV.allocateData(dataSize + sizeof(float))) return mode_static(); //allocation failed
float *dying_gravity = reinterpret_cast<float*>(SEGENV.data + dataSize); 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. * Size is proportional to the height.
*/ */
unsigned nSparks = flare->pos + random8(4); 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 // initialize sparks
if (SEGENV.aux0 == 2) { if (SEGENV.aux0 == 2) {
@ -4031,7 +4018,7 @@ uint16_t mode_pacifica()
// Increment the four "color index start" counters, one for each wave layer. // 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. // 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); uint32_t deltams = (FRAMETIME >> 2) + ((FRAMETIME * SEGMENT.speed) >> 7);
uint64_t deltat = (strip.now >> 2) + ((strip.now * SEGMENT.speed) >> 7); uint64_t deltat = (strip.now >> 2) + ((strip.now * SEGMENT.speed) >> 7);
strip.now = deltat; strip.now = deltat;
@ -4046,7 +4033,7 @@ uint16_t mode_pacifica()
sCIStart3 -= (deltams1 * beatsin88_t(501,5,7)); sCIStart3 -= (deltams1 * beatsin88_t(501,5,7));
sCIStart4 -= (deltams2 * beatsin88_t(257,4,6)); sCIStart4 -= (deltams2 * beatsin88_t(257,4,6));
SEGENV.aux0 = sCIStart1; SEGENV.aux1 = sCIStart2; 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 // Clear out the LED array to a dim background blue-green
//SEGMENT.fill(132618); //SEGMENT.fill(132618);
@ -4077,7 +4064,7 @@ uint16_t mode_pacifica()
c.green = scale8(c.green, 200); c.green = scale8(c.green, 200);
c |= CRGB( 2, 5, 7); c |= CRGB( 2, 5, 7);
SEGMENT.setPixelColor(i, c.red, c.green, c.blue); SEGMENT.setPixelColor(i, c);
} }
strip.now = nowOld; strip.now = nowOld;
@ -4644,7 +4631,7 @@ uint16_t mode_tv_simulator(void) {
return FRAMETIME; 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";
/* /*

View File

@ -2,24 +2,10 @@
WS2812FX.h - Library for WS2812 LED effects. WS2812FX.h - Library for WS2812 LED effects.
Harm Aldick - 2016 Harm Aldick - 2016
www.aldick.org www.aldick.org
LICENSE
The MIT License (MIT)
Copyright (c) 2016 Harm Aldick Copyright (c) 2016 Harm Aldick
Permission is hereby granted, free of charge, to any person obtaining a copy Licensed under the EUPL v. 1.2 or later
of this software and associated documentation files (the "Software"), to deal Adapted from code originally licensed under the MIT license
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.
Modified for WLED Modified for WLED
*/ */
@ -61,6 +47,15 @@
#define FRAMETIME_FIXED (1000/WLED_FPS) #define FRAMETIME_FIXED (1000/WLED_FPS)
#define FRAMETIME strip.getFrameTime() #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 /* each segment uses 82 bytes of SRAM memory, so if you're application fails because of
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
#ifdef ESP8266 #ifdef ESP8266
@ -539,12 +534,12 @@ typedef struct Segment {
inline static const CRGBPalette16 &getCurrentPalette() { return Segment::_currentPalette; } 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); 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 Segment &setColor(uint8_t slot, uint32_t c);
void setCCT(uint16_t k); Segment &setCCT(uint16_t k);
void setOpacity(uint8_t o); Segment &setOpacity(uint8_t o);
void setOption(uint8_t n, bool val); Segment &setOption(uint8_t n, bool val);
void setMode(uint8_t fx, bool loadDefaults = false); Segment &setMode(uint8_t fx, bool loadDefaults = false);
void setPalette(uint8_t pal); Segment &setPalette(uint8_t pal);
uint8_t differs(Segment& b) const; uint8_t differs(Segment& b) const;
void refreshLightCapabilities(); void refreshLightCapabilities();
@ -559,7 +554,7 @@ typedef struct Segment {
* Call resetIfRequired before calling the next effect function. * Call resetIfRequired before calling the next effect function.
* Safe to call from interrupts and network requests. * 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 // transition functions
void startTransition(uint16_t dur); // transition has to start before actual segment values change void startTransition(uint16_t dur); // transition has to start before actual segment values change
@ -613,9 +608,15 @@ typedef struct Segment {
} }
// 2D matrix // 2D matrix
[[gnu::hot]] uint16_t virtualWidth() const; // segment width in virtual pixels (accounts for groupping and spacing) [[gnu::hot]] unsigned 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) [[gnu::hot]] unsigned 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) 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 #ifndef WLED_DISABLE_2D
[[gnu::hot]] uint16_t XY(int x, int y); // support function to get relative index within segment [[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 [[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 #ifndef WLED_DISABLE_2D
panels(1), panels(1),
#endif #endif
#ifdef WLED_AUTOSEGMENTS
autoSegments(true),
#else
autoSegments(false), autoSegments(false),
#endif
correctWB(false), correctWB(false),
cctFromRgb(false), cctFromRgb(false),
// semi-private (just obscured) used in effect functions through macros // semi-private (just obscured) used in effect functions through macros
@ -733,7 +738,7 @@ class WS2812FX { // 96 bytes
_transitionDur(750), _transitionDur(750),
_targetFps(WLED_FPS), _targetFps(WLED_FPS),
_frametime(FRAMETIME_FIXED), _frametime(FRAMETIME_FIXED),
_cumulativeFps(2), _cumulativeFps(50 << FPS_CALC_SHIFT),
_isServicing(false), _isServicing(false),
_isOffRefreshRequired(false), _isOffRefreshRequired(false),
_hasWhiteChannel(false), _hasWhiteChannel(false),
@ -788,7 +793,8 @@ class WS2812FX { // 96 bytes
setTargetFps(uint8_t fps), setTargetFps(uint8_t fps),
setupEffectData(); // add default effects to the list; defined in FX.cpp 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 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 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)); } 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 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) inline uint16_t getTransition() const { return _transitionDur; } // returns currently set transition time (in ms)
uint32_t unsigned long now, timebase;
now, uint32_t getPixelColor(unsigned) const;
timebase,
getPixelColor(uint16_t) const;
inline uint32_t getLastShow() const { return _lastShow; } // returns millis() timestamp of last strip.show() call 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 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

View File

@ -1,24 +1,9 @@
/* /*
FX_2Dfcn.cpp contains all 2D utility functions FX_2Dfcn.cpp contains all 2D utility functions
LICENSE
The MIT License (MIT)
Copyright (c) 2022 Blaz Kristan (https://blaz.at/home) Copyright (c) 2022 Blaz Kristan (https://blaz.at/home)
Permission is hereby granted, free of charge, to any person obtaining a copy Licensed under the EUPL v. 1.2 or later
of this software and associated documentation files (the "Software"), to deal Adapted from code originally licensed under the MIT license
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.
Parts of the code adapted from WLED Sound Reactive 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) void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col)
{ {
if (!isActive()) return; // not active 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(); uint8_t _bri_t = currentBri();
if (_bri_t < 255) { 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 // returns RGBW values of pixel
uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const { uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const {
if (!isActive()) return 0; // not active if (!isActive()) return 0; // not active
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit if ((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 ) x = virtualWidth() - x - 1;
if (reverse_y) y = virtualHeight() - y - 1; if (reverse_y) y = virtualHeight() - y - 1;
if (transpose) { std::swap(x,y); } // swap X & Y if segment transposed if (transpose) { std::swap(x,y); } // swap X & Y if segment transposed

View File

@ -2,24 +2,10 @@
WS2812FX_fcn.cpp contains all utility functions WS2812FX_fcn.cpp contains all utility functions
Harm Aldick - 2016 Harm Aldick - 2016
www.aldick.org www.aldick.org
LICENSE
The MIT License (MIT)
Copyright (c) 2016 Harm Aldick Copyright (c) 2016 Harm Aldick
Permission is hereby granted, free of charge, to any person obtaining a copy Licensed under the EUPL v. 1.2 or later
of this software and associated documentation files (the "Software"), to deal Adapted from code originally licensed under the MIT license
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.
Modified heavily for WLED 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 Segment &Segment::setColor(uint8_t slot, uint32_t c) {
if (slot >= NUM_COLORS || c == colors[slot]) return false; if (slot >= NUM_COLORS || c == colors[slot]) return *this;
if (!_isRGB && !_hasW) { if (!_isRGB && !_hasW) {
if (slot == 0 && c == BLACK) return false; // on/off segment cannot have primary color black if (slot == 0 && c == BLACK) return *this; // 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 == 1 && c != BLACK) return *this; // on/off segment cannot have secondary color non black
} }
if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change
colors[slot] = c; colors[slot] = c;
stateChanged = true; // send UDP/WS broadcast 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 > 255) { //kelvin value, convert to 0-255
if (k < 1900) k = 1900; if (k < 1900) k = 1900;
if (k > 10091) k = 10091; if (k > 10091) k = 10091;
k = (k - 1900) >> 5; k = (k - 1900) >> 5;
} }
if (cct == k) return; if (cct != k) {
if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change //DEBUGFX_PRINTF_P(PSTR("- Starting CCT transition: %d\n"), k);
startTransition(strip.getTransition()); // start transition prior to change
cct = k; cct = k;
stateChanged = true; // send UDP/WS broadcast stateChanged = true; // send UDP/WS broadcast
} }
return *this;
}
void Segment::setOpacity(uint8_t o) { Segment &Segment::setOpacity(uint8_t o) {
if (opacity == o) return; if (opacity != o) {
if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change //DEBUGFX_PRINTF_P(PSTR("- Starting opacity transition: %d\n"), o);
startTransition(strip.getTransition()); // start transition prior to change
opacity = o; opacity = o;
stateChanged = true; // send UDP/WS broadcast 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; bool prevOn = on;
if (fadeTransition && n == SEG_OPTION_ON && val != prevOn) startTransition(strip.getTransition()); // start transition prior to change if (fadeTransition && n == SEG_OPTION_ON && val != prevOn) startTransition(strip.getTransition()); // start transition prior to change
if (val) options |= 0x01 << n; if (val) options |= 0x01 << n;
else options &= ~(0x01 << n); else options &= ~(0x01 << n);
if (!(n == SEG_OPTION_SELECTED || n == SEG_OPTION_RESET)) stateChanged = true; // send UDP/WS broadcast 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 // skip reserved
while (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4) == 0) fx++; while (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4) == 0) fx++;
if (fx >= strip.getModeCount()) fx = 0; // set solid mode if (fx >= strip.getModeCount()) fx = 0; // set solid mode
@ -594,9 +587,10 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
markForReset(); markForReset();
stateChanged = true; // send UDP/WS broadcast 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 && 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 > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // custom palettes
if (pal != palette) { if (pal != palette) {
@ -604,37 +598,24 @@ void Segment::setPalette(uint8_t pal) {
palette = pal; palette = pal;
stateChanged = true; // send UDP/WS broadcast stateChanged = true; // send UDP/WS broadcast
} }
return *this;
} }
// 2D matrix // 2D matrix
uint16_t IRAM_ATTR Segment::virtualWidth() const { unsigned IRAM_ATTR Segment::virtualWidth() const {
unsigned groupLen = groupLength(); unsigned groupLen = groupLength();
unsigned vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen; 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 if (mirror) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED
return vWidth; return vWidth;
} }
uint16_t IRAM_ATTR Segment::virtualHeight() const { unsigned IRAM_ATTR Segment::virtualHeight() const {
unsigned groupLen = groupLength(); unsigned groupLen = groupLength();
unsigned vHeight = ((transpose ? width() : height()) + groupLen - 1) / groupLen; 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 if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
return vHeight; 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" // Constants for mapping mode "Pinwheel"
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16 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) //do not call this method from system context (network callback)
void WS2812FX::finalizeInit() { void WS2812FX::finalizeInit() {
//reset segment runtimes //reset segment runtimes
for (segment &seg : _segments) { restartRuntime();
seg.markForReset();
seg.resetIfRequired();
}
// for the lack of better place enumerate ledmaps here // for the lack of better place enumerate ledmaps here
// if we do it in json.cpp (serializeInfo()) we are getting flashes on LEDs // 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 _isOffRefreshRequired |= bus->isOffRefreshRequired() && !bus->isPWM(); // use refresh bit for phase shift with analog
unsigned busEnd = bus->getStart() + bus->getLength(); unsigned busEnd = bus->getStart() + bus->getLength();
if (busEnd > _length) _length = busEnd; if (busEnd > _length) _length = busEnd;
#ifdef ESP8266
// why do we need to reinitialise GPIO3??? // This must be done after all buses have been created, as some kinds (parallel I2S) interact
//if (!bus->isDigital() || bus->is2Pin()) continue; bus->begin();
//uint8_t pins[5];
//if (!bus->getPins(pins)) continue;
//BusDigital* bd = static_cast<BusDigital*>(bus);
//if (pins[0] == 3) bd->reinit();
#endif
} }
Segment::maxWidth = _length; Segment::maxWidth = _length;
@ -1351,7 +1324,7 @@ void WS2812FX::service() {
if (nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC)) if (nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC))
{ {
doShow = true; doShow = true;
unsigned delay = FRAMETIME; unsigned frameDelay = FRAMETIME;
if (!seg.freeze) { //only run effect function if not frozen if (!seg.freeze) { //only run effect function if not frozen
int oldCCT = BusManager::getSegmentCCT(); // store original CCT value (actually it is not Segment based) 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 // 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. // 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 [[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 #ifndef WLED_DISABLE_MODE_BLEND
if (modeBlending && seg.mode != tmpMode) { if (modeBlending && seg.mode != tmpMode) {
Segment::tmpsegd_t _tmpSegData; Segment::tmpsegd_t _tmpSegData;
@ -1380,16 +1353,16 @@ void WS2812FX::service() {
_virtualSegmentLength = seg.virtualLength(); // update SEGLEN (mapping may have changed) _virtualSegmentLength = seg.virtualLength(); // update SEGLEN (mapping may have changed)
unsigned d2 = (*_mode[tmpMode])(); // run old mode unsigned d2 = (*_mode[tmpMode])(); // run old mode
seg.restoreSegenv(_tmpSegData); // restore mode state (will also update transitional state) 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 Segment::modeBlend(false); // unset semaphore
} }
#endif #endif
seg.call++; 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 BusManager::setSegmentCCT(oldCCT); // restore old CCT for ABL adjustments
} }
seg.next_time = nowUp + delay; seg.next_time = nowUp + frameDelay;
} }
_segment_index++; _segment_index++;
} }
@ -1416,7 +1389,7 @@ void IRAM_ATTR WS2812FX::setPixelColor(unsigned i, uint32_t col) {
BusManager::setPixelColor(i, 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); i = getMappedPixelIndex(i);
if (i >= _length) return 0; if (i >= _length) return 0;
return BusManager::getPixelColor(i); return BusManager::getPixelColor(i);
@ -1434,11 +1407,13 @@ void WS2812FX::show() {
unsigned long showNow = millis(); unsigned long showNow = millis();
size_t diff = showNow - _lastShow; size_t diff = showNow - _lastShow;
size_t fpsCurr = 200;
if (diff > 0) fpsCurr = 1000 / diff; if (diff > 0) { // skip calculation if no time has passed
_cumulativeFps = (3 * _cumulativeFps + fpsCurr +2) >> 2; // "+2" for proper rounding (2/4 = 0.5) 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; _lastShow = showNow;
} }
}
/** /**
* Returns a true value if any of the strips are still being updated. * Returns a true value if any of the strips are still being updated.
@ -1454,7 +1429,7 @@ bool WS2812FX::isUpdating() const {
*/ */
uint16_t WS2812FX::getFps() const { uint16_t WS2812FX::getFps() const {
if (millis() - _lastShow > 2000) return 0; 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) { void WS2812FX::setTargetFps(uint8_t fps) {

View File

@ -150,7 +150,7 @@ BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com)
//_buffering = bc.doubleBuffer; //_buffering = bc.doubleBuffer;
uint16_t lenToCreate = bc.count; uint16_t lenToCreate = bc.count;
if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(bc.count); // only needs a third of "RGB" LEDs for NeoPixelBus if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(bc.count); // only needs a third of "RGB" LEDs for NeoPixelBus
_busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr, _frequencykHz); _busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr);
_valid = (_busPtr != nullptr); _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); 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; if (!_valid) return;
PolyBus::begin(_busPtr, _iType, _pins); PolyBus::begin(_busPtr, _iType, _pins, _frequencykHz);
} }
void BusDigital::cleanup() { void BusDigital::cleanup() {
@ -910,7 +910,7 @@ void BusManager::on() {
if (busses[i]->isDigital() && busses[i]->getPins(pins)) { if (busses[i]->isDigital() && busses[i]->getPins(pins)) {
if (pins[0] == LED_BUILTIN || pins[1] == LED_BUILTIN) { if (pins[0] == LED_BUILTIN || pins[1] == LED_BUILTIN) {
BusDigital *bus = static_cast<BusDigital*>(busses[i]); BusDigital *bus = static_cast<BusDigital*>(busses[i]);
bus->reinit(); bus->begin();
break; break;
} }
} }

View File

@ -79,6 +79,7 @@ class Bus {
virtual ~Bus() {} //throw the bus under the bus virtual ~Bus() {} //throw the bus under the bus
virtual void begin() {};
virtual void show() = 0; virtual void show() = 0;
virtual bool canShow() const { return true; } virtual bool canShow() const { return true; }
virtual void setStatusPixel(uint32_t c) {} virtual void setStatusPixel(uint32_t c) {}
@ -213,7 +214,7 @@ class BusDigital : public Bus {
uint16_t getLEDCurrent() const override { return _milliAmpsPerLed; } uint16_t getLEDCurrent() const override { return _milliAmpsPerLed; }
uint16_t getUsedCurrent() const override { return _milliAmpsTotal; } uint16_t getUsedCurrent() const override { return _milliAmpsTotal; }
uint16_t getMaxCurrent() const override { return _milliAmpsMax; } uint16_t getMaxCurrent() const override { return _milliAmpsMax; }
void reinit(); void begin() override;
void cleanup(); void cleanup();
static std::vector<LEDType> getLEDTypes(); static std::vector<LEDType> getLEDTypes();

View File

@ -336,7 +336,7 @@ class PolyBus {
// initialize SPI bus speed for DotStar methods // initialize SPI bus speed for DotStar methods
template <class T> template <class T>
static void beginDotStar(void* busPtr, int8_t sck, int8_t miso, int8_t mosi, int8_t ss, uint16_t clock_kHz = 0U) { static void beginDotStar(void* busPtr, int8_t sck, int8_t miso, int8_t mosi, int8_t ss, uint16_t clock_kHz /* 0 == use default */) {
T dotStar_strip = static_cast<T>(busPtr); T dotStar_strip = static_cast<T>(busPtr);
#ifdef ESP8266 #ifdef ESP8266
dotStar_strip->Begin(); dotStar_strip->Begin();
@ -363,7 +363,7 @@ class PolyBus {
tm1914_strip->SetPixelSettings(NeoTm1914Settings()); //NeoTm1914_Mode_DinFdinAutoSwitch, NeoTm1914_Mode_DinOnly, NeoTm1914_Mode_FdinOnly 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) { switch (busType) {
case I_NONE: break; case I_NONE: break;
#ifdef ESP8266 #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)) #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 // 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 // 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_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; 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; return busPtr;
} }

View File

@ -215,6 +215,7 @@ void handleAnalog(uint8_t b)
briLast = bri; briLast = bri;
bri = 0; bri = 0;
} else { } else {
if (bri == 0) strip.restartRuntime();
bri = aRead; bri = aRead;
} }
} else if (macroDoublePress[b] == 249) { } else if (macroDoublePress[b] == 249) {

View File

@ -53,7 +53,7 @@
#else #else
#define WLED_MAX_ANALOG_CHANNELS (LEDC_CHANNEL_MAX*LEDC_SPEED_MODE_MAX) #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 #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_DIGITAL_CHANNELS 2
//#define WLED_MAX_ANALOG_CHANNELS 6 //#define WLED_MAX_ANALOG_CHANNELS 6
#define WLED_MIN_VIRTUAL_BUSSES 3 #define WLED_MIN_VIRTUAL_BUSSES 3

View File

@ -144,7 +144,7 @@ button {
} }
.huge { .huge {
font-size: 42px; font-size: 60px !important;
} }
.segt, .plentry TABLE { .segt, .plentry TABLE {
@ -584,6 +584,10 @@ button {
z-index: 3; z-index: 3;
} }
#rover .ibtn {
margin: 5px;
}
#ndlt { #ndlt {
margin: 12px 0; margin: 12px 0;
} }
@ -624,7 +628,7 @@ button {
padding-bottom: 8px; padding-bottom: 8px;
} }
.infobtn { #info .ibtn {
margin: 5px; margin: 5px;
} }
@ -848,7 +852,7 @@ input[type=range]::-moz-range-thumb {
width: 135px; width: 135px;
} }
#nodes .infobtn { #nodes .ibtn {
margin: 0; margin: 0;
} }
@ -1036,7 +1040,7 @@ textarea {
.segname .flr, .pname .flr { .segname .flr, .pname .flr {
transform: rotate(0deg); transform: rotate(0deg);
right: -6px; /*right: -6px;*/
} }
/* segment power wrapper */ /* segment power wrapper */
@ -1331,6 +1335,11 @@ TD .checkmark, TD .radiomark {
box-shadow: 0 0 10px 4px var(--c-1); box-shadow: 0 0 10px 4px var(--c-1);
} }
.lstI .flr:hover {
background: var(--c-6);
border-radius: 100%;
}
#pcont .selected:not([class*="expanded"]) { #pcont .selected:not([class*="expanded"]) {
bottom: 52px; bottom: 52px;
top: 42px; top: 42px;
@ -1524,7 +1533,7 @@ dialog {
#info table .btn, #nodes table .btn { #info table .btn, #nodes table .btn {
width: 200px; width: 200px;
} }
#info .infobtn, #nodes .infobtn { #info .ibtn, #nodes .ibtn {
width: 145px; width: 145px;
} }
#info div, #nodes div, #nodes a.btn { #info div, #nodes div, #nodes a.btn {

View File

@ -304,10 +304,10 @@
</div> </div>
<div id="kv">Loading...</div><br> <div id="kv">Loading...</div><br>
<div> <div>
<button class="btn infobtn" onclick="requestJson()">Refresh</button> <button class="btn ibtn" onclick="requestJson()">Refresh</button>
<button class="btn infobtn" onclick="toggleNodes()">Instance List</button> <button class="btn ibtn" onclick="toggleNodes()">Instance List</button>
<button class="btn infobtn" onclick="window.open(getURL('/update'),'_self');">Update WLED</button> <button class="btn ibtn" onclick="window.open(getURL('/update'),'_self');">Update WLED</button>
<button class="btn infobtn" id="resetbtn" onclick="cnfReset()">Reboot WLED</button> <button class="btn ibtn" id="resetbtn" onclick="cnfReset()">Reboot WLED</button>
</div> </div>
<br> <br>
<span class="h">Made with&#32;<span id="heart">&#10084;&#xFE0E;</span>&#32;by&#32;<a href="https://github.com/Aircoookie/" target="_blank">Aircoookie</a>&#32;and the&#32;<a href="https://wled.discourse.group/" target="_blank">WLED community</a></span> <span class="h">Made with&#32;<span id="heart">&#10084;&#xFE0E;</span>&#32;by&#32;<a href="https://github.com/Aircoookie/" target="_blank">Aircoookie</a>&#32;and the&#32;<a href="https://wled.discourse.group/" target="_blank">WLED community</a></span>
@ -318,7 +318,7 @@
<div id="ndlt">WLED instances</div> <div id="ndlt">WLED instances</div>
<div id="kn">Loading...</div> <div id="kn">Loading...</div>
<div style="position:sticky;bottom:0;"> <div style="position:sticky;bottom:0;">
<button class="btn infobtn" onclick="loadNodes()">Refresh</button> <button class="btn ibtn" onclick="loadNodes()">Refresh</button>
</div> </div>
</div> </div>
@ -331,8 +331,8 @@
<div id="lv">?</div><br><br> <div id="lv">?</div><br><br>
To use built-in effects, use an override button below.<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> 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 ibtn" onclick="setLor(1)">Override once</button>
<button class="btn" onclick="setLor(2)">Override until reboot</button><br> <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> <span class="h">For best performance, it is recommended to turn off the streaming source when not in use.</span>
</div> </div>

View File

@ -2850,8 +2850,12 @@ function search(field, listId = null) {
if (listId !== 'pcont' && i === 0) return; if (listId !== 'pcont' && i === 0) return;
const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase(); const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase();
const searchIndex = listItemName.indexOf(field.value.toUpperCase()); const searchIndex = listItemName.indexOf(field.value.toUpperCase());
listItem.style.display = (searchIndex < 0) ? 'none' : ''; if (searchIndex < 0) {
listItem.dataset.searchIndex = Number.MAX_SAFE_INTEGER;
} else {
listItem.dataset.searchIndex = searchIndex; listItem.dataset.searchIndex = searchIndex;
}
listItem.style.display = (searchIndex < 0) && !listItem.classList.contains("selected") ? 'none' : '';
}); });
// sort list items by search index and name // sort list items by search index and name
@ -2924,7 +2928,7 @@ function filterFx() {
const listItemName = listItem.querySelector('.lstIname').innerText; const listItemName = listItem.querySelector('.lstIname').innerText;
let hide = false; let hide = false;
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { if (e.checked && !listItemName.includes(e.dataset.flt)) hide = i > 0 /*true*/; }); 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' : ''; listItem.style.display = hide && !listItem.classList.contains("selected") ? 'none' : '';
}); });
} }

View File

@ -42,15 +42,14 @@
if (loc) d.Sf.action = getURL('/settings/leds'); if (loc) d.Sf.action = getURL('/settings/leds');
} }
function bLimits(b,v,p,m,l,o=5,d=2,a=6) { function bLimits(b,v,p,m,l,o=5,d=2,a=6) {
// maxB - max buses (can be changed if using ESP32 parallel I2S) oMaxB = maxB = b; // maxB - max buses (can be changed if using ESP32 parallel I2S)
// maxD - max digital channels (can be changed if using ESP32 parallel I2S) maxD = d; // maxD - max digital channels (can be changed if using ESP32 parallel I2S)
// maxA - max analog channels maxA = a; // maxA - max analog channels
// maxV - min virtual buses maxV = v; // maxV - min virtual buses
// maxPB - max LEDs per bus maxPB = p; // maxPB - max LEDs per bus
// maxM - max LED memory maxM = m; // maxM - max LED memory
// maxL - max LEDs (will serve to determine ESP >1664 == ESP32) maxL = l; // maxL - max LEDs (will serve to determine ESP >1664 == ESP32)
// maxCO - max Color Order mappings maxCO = o; // maxCO - max Color Order mappings
oMaxB = maxB = b; maxD = d, maxA = a, maxV = v; maxM = m; maxPB = p; maxL = l; maxCO = o;
} }
function pinsOK() { function pinsOK() {
var ok = true; var ok = true;
@ -119,7 +118,12 @@
var en = d.Sf.ABL.checked; var en = d.Sf.ABL.checked;
gId('abl').style.display = (en) ? 'inline':'none'; gId('abl').style.display = (en) ? 'inline':'none';
gId('psu2').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(); UI();
} }
// enable per port limiter and calculate current // enable per port limiter and calculate current
@ -132,37 +136,41 @@
d.Sf.MA.min = abl && !ppl ? 250 : 0; d.Sf.MA.min = abl && !ppl ? 250 : 0;
gId("psuMA").style.display = ppl ? 'none' : 'inline'; gId("psuMA").style.display = ppl ? 'none' : 'inline';
gId("ppldis").style.display = ppl ? 'inline' : 'none'; 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)=>{ d.Sf.querySelectorAll("#mLC input[name^=MA]").forEach((i,x)=>{
var n = String.fromCharCode((x<10?48:55)+x); var n = String.fromCharCode((x<10?48:55)+x);
gId("PSU"+n).style.display = ppl ? "inline" : "none"; gId("PSU"+n).style.display = ppl ? "inline" : "none";
const t = parseInt(d.Sf["LT"+n].value); // LED type SELECT const t = parseInt(d.Sf["LT"+n].value); // LED type SELECT
const c = parseInt(d.Sf["LC"+n].value); //get LED count const c = parseInt(d.Sf["LC"+n].value); //get LED count
i.min = ppl && !(isVir(t) || isAna(t)) ? 250 : 0; i.min = ppl && isDig(t) ? 250 : 0;
if (!abl || isVir(t) || isAna(t)) i.value = 0; if (!abl || !isDig(t)) i.value = 0;
else if (ppl) sumMA += parseInt(i.value,10); else if (ppl) sumMA += parseInt(i.value,10);
else if (sDI) i.value = Math.round(parseInt(d.Sf.MA.value,10)*c/sDI); 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 if (ppl) d.Sf.MA.value = sumMA; // populate UI ABL value if PPL used
} }
// enable and update LED Amps
function enLA(s,n) function enLA(s,n)
{ {
const abl = d.Sf.ABL.checked;
const t = parseInt(d.Sf["LT"+n].value); // LED type SELECT const t = parseInt(d.Sf["LT"+n].value); // LED type SELECT
gId('LAdis'+n).style.display = s.selectedIndex==5 ? "inline" : "none"; gId('LAdis'+n).style.display = s.selectedIndex==5 ? "inline" : "none"; // show/hide custom mA field
if (s.value!=="0") d.Sf["LA"+n].value = s.value; if (s.value!=="0") d.Sf["LA"+n].value = s.value; // set value from select object
d.Sf["LA"+n].min = (isVir(t) || isAna(t)) ? 0 : 1; d.Sf["LA"+n].min = (!isDig(t) || !abl) ? 0 : 1; // set minimum value for validation
} }
function setABL() 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) // check if ABL is enabled (max mA entered per output)
d.Sf.querySelectorAll("#mLC input[name^=MA]").forEach((i,n)=>{ 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 // select appropriate LED current
d.Sf.querySelectorAll("#mLC select[name^=LAsel]").forEach((sel,x)=>{ d.Sf.querySelectorAll("#mLC select[name^=LAsel]").forEach((sel,x)=>{
sel.value = 0; // set custom sel.value = 0; // set custom
var n = String.fromCharCode((x<10?48:55)+x); var n = String.fromCharCode((x<10?48:55)+x);
if (en)
switch (parseInt(d.Sf["LA"+n].value)) { switch (parseInt(d.Sf["LA"+n].value)) {
case 0: break; // disable ABL case 0: break; // disable ABL
case 15: sel.value = 15; break; case 15: sel.value = 15; break;
@ -171,7 +179,8 @@
case 55: sel.value = 55; break; case 55: sel.value = 55; break;
case 255: sel.value = 255; break; case 255: sel.value = 255; break;
} }
enLA(sel,n); else sel.value = 0;
enLA(sel,n); // configure individual limiter
}); });
enABL(); enABL();
gId('m1').innerHTML = maxM; gId('m1').innerHTML = maxM;
@ -202,7 +211,7 @@
let gRGBW = false, memu = 0; let gRGBW = false, memu = 0;
let busMA = 0; let busMA = 0;
let sLC = 0, sPC = 0, sDI = 0, maxLC = 0; let sLC = 0, sPC = 0, sDI = 0, maxLC = 0;
const ablEN = d.Sf.ABL.checked; const abl = d.Sf.ABL.checked;
maxB = oMaxB; // TODO make sure we start with all possible buses maxB = oMaxB; // TODO make sure we start with all possible buses
let setPinConfig = (n,t) => { let setPinConfig = (n,t) => {
let p0d = "GPIO:"; let p0d = "GPIO:";
@ -249,12 +258,12 @@
var t = parseInt(s.value); var t = parseInt(s.value);
memu += getMem(t, n); // calc memory memu += getMem(t, n); // calc memory
setPinConfig(n,t); setPinConfig(n,t);
gId("abl"+n).style.display = (!ablEN || isVir(t) || isAna(t)) ? "none" : "inline"; gId("abl"+n).style.display = (!abl || !isDig(t)) ? "none" : "inline"; // show/hide individual ABL settings
if (change) { 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) 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 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["LA"+n].min = (!isDig(t) || !abl) ? 0 : 1; // set minimum value for LED mA
d.Sf["MA"+n].min = (isVir(t) || isAna(t)) ? 0 : 250; 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 gId("rf"+n).onclick = mustR(t) ? (()=>{return false}) : (()=>{}); // prevent change change of "Refresh" checkmark when mandatory
gRGBW |= hasW(t); // RGBW checkbox gRGBW |= hasW(t); // RGBW checkbox
@ -294,7 +303,7 @@
if (s+c > sLC) sLC = s+c; //update total count if (s+c > sLC) sLC = s+c; //update total count
if (c > maxLC) maxLC = c; //max per output if (c > maxLC) maxLC = c; //max per output
if (!isVir(t)) sPC += c; //virtual out busses do not count towards physical LEDs 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 sDI += c; // summarize digital LED count
let maPL = parseInt(d.Sf["LA"+n].value); let maPL = parseInt(d.Sf["LA"+n].value);
if (maPL == 255) maPL = 12; if (maPL == 255) maPL = 12;

View File

@ -72,7 +72,7 @@
<a href="https://github.com/Aircoookie/WLED/wiki/Contributors-and-credits" target="_blank">Contributors, dependencies and special thanks</a><br> <a href="https://github.com/Aircoookie/WLED/wiki/Contributors-and-credits" target="_blank">Contributors, dependencies and special thanks</a><br>
A huge thank you to everyone who helped me create WLED!<br><br> A huge thank you to everyone who helped me create WLED!<br><br>
(c) 2016-2024 Christian Schwinne <br> (c) 2016-2024 Christian Schwinne <br>
<i>Licensed under the <a href="https://github.com/Aircoookie/WLED/blob/master/LICENSE" target="_blank">MIT license</a></i><br><br> <i>Licensed under the <a href="https://github.com/Aircoookie/WLED/blob/master/LICENSE" target="_blank">EUPL v1.2 license</a></i><br><br>
Server message: <span class="sip"> Response error! </span><hr> Server message: <span class="sip"> Response error! </span><hr>
<div id="toast"></div> <div id="toast"></div>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button> <button type="button" onclick="B()">Back</button><button type="submit">Save</button>

View File

@ -156,6 +156,7 @@
<option value="20">AKST/AKDT (Anchorage)</option> <option value="20">AKST/AKDT (Anchorage)</option>
<option value="21">MX-CST</option> <option value="21">MX-CST</option>
<option value="22">PKT (Pakistan)</option> <option value="22">PKT (Pakistan)</option>
<option value="23">BRT (Brasília)</option>
</select><br> </select><br>
UTC offset: <input name="UO" type="number" min="-65500" max="65500" required> seconds (max. 18 hours)<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> Current local time is <span class="times">unknown</span>.<br>

View File

@ -17,7 +17,8 @@
<h2>WLED Software Update</h2> <h2>WLED Software Update</h2>
<form method='POST' action='./update' id='uf' enctype='multipart/form-data' onsubmit="U()"> <form method='POST' action='./update' id='uf' enctype='multipart/form-data' onsubmit="U()">
Installed version: <span class="sip">##VERSION##</span><br> 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:&nbsp;<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> <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--> <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> <button type="submit">Update!</button><br>

View File

@ -169,7 +169,6 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient = 0);
void setValuesFromSegment(uint8_t s); void setValuesFromSegment(uint8_t s);
void setValuesFromMainSeg(); void setValuesFromMainSeg();
void setValuesFromFirstSelectedSeg(); void setValuesFromFirstSelectedSeg();
void resetTimebase();
void toggleOnOff(); void toggleOnOff();
void applyBri(); void applyBri();
void applyFinalBri(); void applyFinalBri();
@ -324,6 +323,10 @@ class Usermod {
protected: protected:
// Shim for oappend(), which used to exist in utils.cpp // Shim for oappend(), which used to exist in utils.cpp
template<typename T> static inline void oappend(const T& t) { oappend_shim->print(t); }; 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 { class UsermodManager {

View File

@ -194,24 +194,22 @@ void sendImprovIPRPCResult(ImprovRPCType type) {
} }
void sendImprovInfoResponse() { void sendImprovInfoResponse() {
const char* bString = char bString[32];
#ifdef ESP8266 #ifdef ESP8266
"esp8266" strcpy(bString, "esp8266");
#elif CONFIG_IDF_TARGET_ESP32C3
"esp32-c3"
#elif CONFIG_IDF_TARGET_ESP32S2
"esp32-s2"
#elif CONFIG_IDF_TARGET_ESP32S3
"esp32-s3";
#else // ESP32 #else // ESP32
"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 #endif
;
//Use serverDescription if it has been changed from the default "WLED", else mDNS name //Use serverDescription if it has been changed from the default "WLED", else mDNS name
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0); bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
char vString[20]; char vString[32];
sprintf_P(vString, PSTR("0.15.0-b5/%i"), VERSION); sprintf_P(vString, PSTR("%s/%i"), versionString, VERSION);
const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription}; const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription};
sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str); sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str);

View File

@ -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 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; tr = root[F("transition")] | -1;
if (tr >= 0) { if (tr >= 0) {
@ -363,7 +363,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
} }
tr = root[F("tb")] | -1; 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"]; JsonObject nl = root["nl"];
nightlightActive = getBoolVal(nl["on"], nightlightActive); nightlightActive = getBoolVal(nl["on"], nightlightActive);
@ -454,21 +454,25 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
handleSet(nullptr, apireq, false); // may set stateChanged 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; byte presetToRestore = 0;
// a) already applied preset content (requires "seg" or "win" but will ignore the rest)
if (!root[F("pd")].isNull() && stateChanged) { 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; 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 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()) { } else if (!root["ps"].isNull()) {
ps = presetCycCurr; // 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"], &ps, 0, 0) && ps > 0 && ps < 251 && ps != currentPreset) { 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()) // b) preset ID only or preset that does not change state (use embedded cycling limits if they exist in getVal())
presetCycCurr = ps; applyPreset(presetCycCurr, callMode); // async load from file system (only preset ID was specified)
applyPreset(ps, callMode); // async load from file system (only preset ID was specified)
return stateResponse; return stateResponse;
} } else presetCycCurr = currentPreset; // restore presetCycCurr
} }
JsonObject playlist = root[F("playlist")]; JsonObject playlist = root[F("playlist")];

View File

@ -47,17 +47,12 @@ void applyValuesToSelectedSegs()
} }
void resetTimebase()
{
strip.timebase = 0 - millis();
}
void toggleOnOff() void toggleOnOff()
{ {
if (bri == 0) if (bri == 0)
{ {
bri = briLast; bri = briLast;
strip.restartRuntime();
} else } else
{ {
briLast = bri; briLast = bri;
@ -122,7 +117,7 @@ void stateUpdated(byte callMode) {
nightlightStartTime = millis(); nightlightStartTime = millis();
} }
if (briT == 0) { 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; if (bri > 0) briLast = bri;

View File

@ -36,8 +36,9 @@ Timezone* tz;
#define TZ_ANCHORAGE 20 #define TZ_ANCHORAGE 20
#define TZ_MX_CENTRAL 21 #define TZ_MX_CENTRAL 21
#define TZ_PAKISTAN 22 #define TZ_PAKISTAN 22
#define TZ_BRASILIA 23
#define TZ_COUNT 23 #define TZ_COUNT 24
#define TZ_INIT 255 #define TZ_INIT 255
byte tzCurrent = TZ_INIT; //uninitialized byte tzCurrent = TZ_INIT; //uninitialized
@ -135,6 +136,10 @@ static const std::pair<TimeChangeRule, TimeChangeRule> TZ_TABLE[] PROGMEM = {
/* TZ_PAKISTAN */ { /* TZ_PAKISTAN */ {
{Last, Sun, Mar, 1, 300}, //Pakistan Standard Time = UTC + 5 hours {Last, Sun, Mar, 1, 300}, //Pakistan Standard Time = UTC + 5 hours
{Last, Sun, Mar, 1, 300} {Last, Sun, Mar, 1, 300}
},
/* TZ_BRASILIA */ {
{Last, Sun, Mar, 1, -180}, //Brasília Standard Time = UTC - 3 hours
{Last, Sun, Mar, 1, -180}
} }
}; };

View File

@ -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. if (gpio > 18 && gpio < 21) return false; // 19 + 20 = USB-JTAG. Not recommended for other uses.
#endif #endif
if (gpio > 21 && gpio < 33) return false; // 22 to 32: not connected + SPI FLASH if (gpio > 21 && gpio < 33) return false; // 22 to 32: not connected + SPI FLASH
if (gpio > 32 && gpio < 38) return !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. // 38 to 48 are for general use. Be careful about straping pins GPIO45 and GPIO46 - these may be pull-up or pulled-down on your board.
#elif defined(CONFIG_IDF_TARGET_ESP32S2) #elif defined(CONFIG_IDF_TARGET_ESP32S2)
// strapping pins: 0, 45 & 46 // strapping pins: 0, 45 & 46

View File

@ -143,6 +143,7 @@ void applyPresetWithFallback(uint8_t index, uint8_t callMode, uint8_t effectID,
void handlePresets() void handlePresets()
{ {
byte presetErrFlag = ERR_NONE;
if (presetToSave) { if (presetToSave) {
strip.suspend(); strip.suspend();
doSaveState(); doSaveState();
@ -166,14 +167,16 @@ void handlePresets()
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
if (tmpPreset==255 && tmpRAMbuffer!=nullptr) { if (tmpPreset==255 && tmpRAMbuffer!=nullptr) {
deserializeJson(*pDoc,tmpRAMbuffer); deserializeJson(*pDoc,tmpRAMbuffer);
errorFlag = ERR_NONE;
} else } else
#endif #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>(); 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 //HTTP API commands
const char* httpwin = fdo["win"]; const char* httpwin = fdo["win"];
if (httpwin) { if (httpwin) {

View File

@ -215,6 +215,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
//doInitBusses = busesChanged; // we will do that below to ensure all input data is processed //doInitBusses = busesChanged; // we will do that below to ensure all input data is processed
// we will not bother with pre-allocating ColorOrderMappings vector // we will not bother with pre-allocating ColorOrderMappings vector
BusManager::getColorOrderMap().reset();
for (int s = 0; s < WLED_MAX_COLOR_ORDER_MAPPINGS; s++) { for (int s = 0; s < WLED_MAX_COLOR_ORDER_MAPPINGS; s++) {
int offset = s < 10 ? 48 : 55; int offset = s < 10 ? 48 : 55;
char xs[4] = "XS"; xs[2] = offset+s; xs[3] = 0; //start LED 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 // internal call, does not send XML response
pos = req.indexOf(F("IN")); pos = req.indexOf(F("IN"));
if (pos < 1) { if ((request != nullptr) && (pos < 1)) {
auto response = request->beginResponseStream("text/xml"); auto response = request->beginResponseStream("text/xml");
XML_response(*response); XML_response(*response);
request->send(response); request->send(response);

View File

@ -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 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) 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 //DMX value array and size. Entry 0 will hold startbyte, so we need 512+1 elements
static uint8_t dmxData[dmxMaxChannel] = { 0 }; static uint8_t dmxData[dmxMaxChannel+1] = { 0 };
static int chanSize = 0; static int chanSize = 0;
#if !defined(DMX_SEND_ONLY) #if !defined(DMX_SEND_ONLY)
static int currentChannel = 0; static int currentChannel = 0;

View File

@ -120,10 +120,8 @@ private:
void encodeLightId(uint8_t idx, char* out) void encodeLightId(uint8_t idx, char* out)
{ {
uint8_t mac[6]; String mymac = WiFi.macAddress();
WiFi.macAddress(mac); sprintf_P(out, PSTR("%02X:%s:AB-%02X"), idx, mymac.c_str(), idx);
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);
} }
// construct 'globally unique' Json dict key fitting into signed int // construct 'globally unique' Json dict key fitting into signed int

View File

@ -380,6 +380,12 @@ void WLED::setup()
case FM_QOUT: DEBUG_PRINT(F("(QOUT)"));break; case FM_QOUT: DEBUG_PRINT(F("(QOUT)"));break;
case FM_DIO: DEBUG_PRINT(F("(DIO)")); break; case FM_DIO: DEBUG_PRINT(F("(DIO)")); break;
case FM_DOUT: DEBUG_PRINT(F("(DOUT)"));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; default: break;
} }
#endif #endif

View File

@ -3,12 +3,12 @@
/* /*
Main sketch, global variable declarations Main sketch, global variable declarations
@title WLED project sketch @title WLED project sketch
@version 0.15.0-b5 @version 0.15.0-b7
@author Christian Schwinne @author Christian Schwinne
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2409170 #define VERSION 2410270
//uncomment this if you have a "my_config.h" file you'd like to use //uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG //#define WLED_USE_MY_CONFIG
@ -36,12 +36,13 @@
#undef WLED_ENABLE_ADALIGHT // disable has priority over enable #undef WLED_ENABLE_ADALIGHT // disable has priority over enable
#endif #endif
//#define WLED_ENABLE_DMX // uses 3.5kb //#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 #ifndef WLED_DISABLE_LOXONE
#define WLED_ENABLE_LOXONE // uses 1.2kb #define WLED_ENABLE_LOXONE // uses 1.2kb
#endif #endif
#ifndef WLED_DISABLE_WEBSOCKETS #ifndef WLED_DISABLE_WEBSOCKETS
#define WLED_ENABLE_WEBSOCKETS #define WLED_ENABLE_WEBSOCKETS
#else
#define WLED_ENABLE_JSONLIVE // peek LED output via /json/live (WS binary peek is always enabled)
#endif #endif
//#define WLED_DISABLE_ESPNOW // Removes dependence on esp now //#define WLED_DISABLE_ESPNOW // Removes dependence on esp now
@ -263,12 +264,12 @@ using PSRAMDynamicJsonDocument = BasicJsonDocument<PSRAM_Allocator>;
#define WLED_VERSION dev #define WLED_VERSION dev
#endif #endif
#ifndef WLED_RELEASE_NAME #ifndef WLED_RELEASE_NAME
#define WLED_RELEASE_NAME dev_release #define WLED_RELEASE_NAME "Custom"
#endif #endif
// Global Variable definitions // Global Variable definitions
WLED_GLOBAL char versionString[] _INIT(TOSTRING(WLED_VERSION)); 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" #define WLED_CODENAME "Kōsen"
// AP and OTA default passwords (for maximum security change them!) // 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; constexpr uint8_t hardwareTX = 1;
#endif #endif
//WLED_GLOBAL byte presetToApply _INIT(0);
WLED_GLOBAL char ntpServerName[33] _INIT("0.wled.pool.ntp.org"); // NTP server to use 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) // WiFi CONFIG (all these can be changed via web UI, no need to set them here)

View File

@ -193,12 +193,12 @@ void createEditHandler(bool enable) {
editHandler = &server.addHandler(new SPIFFSEditor("","",WLED_FS));//http_username,http_password)); editHandler = &server.addHandler(new SPIFFSEditor("","",WLED_FS));//http_username,http_password));
#endif #endif
#else #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); serveMessage(request, 501, FPSTR(s_notimplemented), F("The FS editor is disabled in this build."), 254);
}); });
#endif #endif
} else { } 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); serveMessage(request, 401, FPSTR(s_accessdenied), FPSTR(s_unlock_cfg), 254);
}); });
} }
@ -427,11 +427,11 @@ void initServer()
#ifdef WLED_ENABLE_DMX #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); request->send_P(200, FPSTR(CONTENT_TYPE_HTML), PAGE_dmxmap , dmxProcessor);
}); });
#else #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); serveMessage(request, 501, FPSTR(s_notimplemented), F("DMX support is not enabled in this build."), 254);
}); });
#endif #endif

View File

@ -172,7 +172,7 @@ void getSettingsJS(byte subPage, Print& settingsScript)
char fpass[l+1]; //fill password field with *** char fpass[l+1]; //fill password field with ***
fpass[l] = 0; fpass[l] = 0;
memset(fpass,'*',l); 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, multiWiFi[n].clientSSID,
fpass, fpass,
(uint32_t) multiWiFi[n].staticIP, // explicit cast required as this is a struct (uint32_t) multiWiFi[n].staticIP, // explicit cast required as this is a struct
@ -227,7 +227,7 @@ void getSettingsJS(byte subPage, Print& settingsScript)
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]); sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET) #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 #endif
printSetClassElementHTML(settingsScript,PSTR("sip"),0,s); printSetClassElementHTML(settingsScript,PSTR("sip"),0,s);
} else } else
@ -465,7 +465,7 @@ void getSettingsJS(byte subPage, Print& settingsScript)
printSetFormValue(settingsScript,PSTR("MG"),mqttGroupTopic); printSetFormValue(settingsScript,PSTR("MG"),mqttGroupTopic);
printSetFormCheckbox(settingsScript,PSTR("BM"),buttonPublishMqtt); printSetFormCheckbox(settingsScript,PSTR("BM"),buttonPublishMqtt);
printSetFormCheckbox(settingsScript,PSTR("RT"),retainMqttMsg); 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); MQTT_MAX_TOPIC_LEN, MQTT_MAX_TOPIC_LEN, MQTT_MAX_SERVER_LEN);
#else #else
settingsScript.print(F("toggle('MQTT');")); // hide MQTT settings settingsScript.print(F("toggle('MQTT');")); // hide MQTT settings
@ -501,7 +501,7 @@ void getSettingsJS(byte subPage, Print& settingsScript)
#endif #endif
printSetFormValue(settingsScript,PSTR("BD"),serialBaud); printSetFormValue(settingsScript,PSTR("BD"),serialBaud);
#ifndef WLED_ENABLE_ADALIGHT #ifndef WLED_ENABLE_ADALIGHT
settingsScript.print(F("toggle('Serial);")); settingsScript.print(F("toggle('Serial');"));
#endif #endif
} }