Compare commits

..

93 Commits
16_x ... main

Author SHA1 Message Date
Brandon502
69d494ad40 GoL missing return. (#5523) 2026-04-22 06:11:59 +02:00
Damian Schneider
01328a65c1 Fix blending style options list filter for iOS (#5513)
* fix blending style options list filter for iOS
* fix default fallback
2026-04-20 19:06:33 +02:00
Damian Schneider
a2d970e155 better packet queuing & pacing for custom palette live preview (#5515)
* better packet queuing / pacing for custom palette live preview
* fix leak
* remove window prefix from variables
2026-04-20 18:58:09 +02:00
Frank Möhle
cb666cedc5 Highlight target branch for pull requests
Emphasize the importance of targeting the main branch for PRs.
2026-04-20 15:23:06 +02:00
Frank Möhle
5e0a0a7561 Update rules for PR descriptions and change logs
Added a guideline to prevent agents from overwriting PR descriptions (see https://github.com/orgs/community/discussions/187027).
2026-04-20 14:19:21 +02:00
Frank Möhle
3af2ae5f2f Merge pull request #5516 from kilrah/fix_dmx_ident
Add identifier string for DMX realtime mode
2026-04-19 18:36:25 +02:00
Kilrah
259bf3c0f8 Add identifier string for DMX realtime mode
(cherry picked from commit b4ae421fc3)
2026-04-18 16:47:06 +02:00
Damian Schneider
5e49a1cffb bugfixes in PS effects
- fix PS Sparkler for large setups: need 32bit random position, 16bit is not enough
- fix PS Fireworks 1D: need to `break` if no particles are available or it can lead to stalls on large setups
- do not use collisions by default PS Fuzzy Noise: its very slow on larger setups
2026-04-17 15:26:57 +02:00
Damian Schneider
910caae463 use fast path in blendSegment to bump up FPS (#5464)
* use fast path in blendSegment to bump up FPS
2026-04-16 07:45:00 +02:00
Will Miles
35ce05a73b Merge pull request #5502 from willmmiles/dynarray-fixes
Dynarray fixes - fixes usermods on C3s
2026-04-15 20:18:07 -04:00
Frank Möhle
ba377d7c29 Disable docstrings and unit tests in .coderabbit.yaml
Disable docstring generation and unit tests in CodeRabbit configuration.
2026-04-13 23:12:01 +02:00
Will Miles
6d7c1d0bbd Improve usermod validation warnings 2026-04-13 01:38:30 -04:00
Damian Schneider
96510614a3 mask out flag bits in DDP type for compatibility 2026-04-12 19:49:45 +02:00
Damian Schneider
1185886eab add search icon back(#5500) 2026-04-12 19:07:16 +02:00
Will Miles
a94a3f7003 Fix up usermod validation again
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 11:38:23 -04:00
Will Miles
144f1f13a8 dynarray: Support ESP-IDF 2026-04-12 11:38:23 -04:00
Will Miles
5a7aa8d8a8 validate_modules: Improve performance
Use readelf instead of nm for great speed.
2026-04-12 11:38:23 -04:00
Will Miles
42b91f2122 Fix usermod count for LTO 2026-04-12 11:38:23 -04:00
Will Miles
a966c41bc2 dynarray: Directly apply linker fix
Rather than append a linker file, we edit the upstream supplied ones to
add our section to the binaries.  Works better on all platforms.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-12 11:38:23 -04:00
Will Tatam
36ebcb50f7 Merge pull request #5493 from LordMike/patch-2
Refactor wled-tools discover_devices for deduplication and clarity
2026-04-12 08:15:24 +01:00
Frank Möhle
3149a80dcf Refine early return guard clause in error handling
Update error handling guard clause to include time check.

The simpler "!enabled || strip.isUpdating()" pattern regularly causes usermods to stop responding when many LEDs are driven.
2026-04-12 00:21:48 +02:00
Frank Möhle
bab31833f0 Update naming conventions in cpp.instructions.md
Add PascalCase convention for enum values.
2026-04-12 00:09:22 +02:00
Frank Möhle
48b0ba0643 Update AI markers and string storage recommendations
Clarified usage of AI markers and added advice on string storage for ESP platforms.
2026-04-11 23:58:30 +02:00
Frank Möhle
0198a614b9 Fix formatting of AI attribution instructions
markdown was wrong
2026-04-11 23:52:19 +02:00
Frank Möhle
14f2ca4223 Use same AI: comment as suggested in other agent instructions
Exact comment text
2026-04-11 23:50:53 +02:00
Will Tatam
7932a249e0 Add AGENTS.md 2026-04-11 11:35:20 +01:00
Will Miles
474e1fe2e5 Serialize fxdata without ArduinoJSON (#5461)
* Serialize fxdata without ArduinoJSON

Eliminates size limit.  Fixes #5458

* Fix off-by-one in fxdata serializer

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Remove declaration of removed function

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Factor out streaming JSON primitives

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 12:26:48 +02:00
Will Tatam
7aec31f039 Upload then add notes 2026-04-11 09:19:50 +01:00
Will Tatam
e2dd6303ea Merge pull request #5465 from netmindz/usage-extended
New extended data for usage report
2026-04-11 08:20:09 +01:00
Will Tatam
7242e9d842 remove i2c and spi 2026-04-11 08:19:36 +01:00
Will Tatam
ab0cde110f apply code review feedback 2026-04-11 08:16:10 +01:00
Frank Möhle
c735feb90a Merge branch 'main' into usage-extended 2026-04-11 08:52:16 +02:00
Frank Möhle
a6faf942f1 Revise AI transparency guidelines in CONTRIBUTING.md
Updated transparency guideline for AI-generated code comments.
2026-04-10 21:52:33 +02:00
Will Tatam
370e4c8e2f Merge pull request #5489 from wled/copilot/fix-wled-discovery-issues
Fix Alexa/Hue discovery by correcting SSDP response to match UPnP spec
2026-04-10 18:25:31 +01:00
Frank
8e90242e95 coderabbit tinkering
* disable poem
* disable docstring tool (confusing for users)
* don't review if title contains "WIP"
* auto-assign labels to the PR
2026-04-10 16:55:28 +02:00
Michael Bisbjerg
97dacb6a04 Undo space removals 2026-04-10 16:20:51 +02:00
Frank
061920bb9c adding an (exhaustive) reference guide for esp-idf
this guide is only for reference and reading - right now the content is not liked for AI agents - neither coderabbit nor copilot will automaticially use the file.
2026-04-10 13:56:26 +02:00
Michael Bisbjerg
97704e08de Refactor discover_devices for deduplication and clarity
Refactor discover_devices function to deduplicate device entries and improve readability.
2026-04-10 12:08:42 +02:00
Frank Möhle
a51aec6f19 Fix typo in pull request expectations section 2026-04-10 02:49:28 +02:00
Frank Möhle
c21ed0714f Fix formatting of platformio.ini modification requirement 2026-04-10 02:44:15 +02:00
Frank Möhle
a2dce56809 Update pull request expectations: approval needed to modify platformio.ini
Clarify approval requirement for modifications to platformio.ini
2026-04-10 02:43:40 +02:00
Frank Möhle
036f5199e5 Clean up PR review instructions in .coderabbit.yaml
Removed not working instructions for PR review practices.
2026-04-10 02:32:38 +02:00
Frank Möhle
1914e4ee3b Add reminder for clear pull request descriptions
Emphasized the requirement for clear pull request descriptions.
It's already mentioned 8n the general instructions file, but copilot still was overwriting the iinial description (good) with a delta-checklist on rework (bad).
2026-04-09 18:46:30 +02:00
copilot-swe-agent[bot]
9c072ec921 fix: restore lost inline comments on CACHE-CONTROL and USN lines
Agent-Logs-Url: https://github.com/wled/WLED/sessions/545fc8ab-87c8-4cf5-aa9d-f99915b68beb

Co-authored-by: softhack007 <91616163+softhack007@users.noreply.github.com>
2026-04-09 15:10:40 +00:00
Frank Möhle
cf4dfe958e Update build instructions with comment preservation reminder
Added a reminder to preserve or update comments after modifying source code files.
2026-04-09 12:27:57 +02:00
copilot-swe-agent[bot]
2cccbd175c docs: improve EUI-64 bridge ID comment per code review
Agent-Logs-Url: https://github.com/wled/WLED/sessions/c3fb311b-1349-48b1-abfd-6a4aca8c7a77

Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com>
2026-04-09 05:57:45 +00:00
copilot-swe-agent[bot]
cb61c4fe7d fix: improve Alexa/Hue discovery SSDP response compatibility
Fix SSDP M-SEARCH response in Espalexa to match real Philips Hue
bridge behavior and UPnP spec, addressing Alexa discovery failures:

1. Fix ST header capitalization: basic:1 → Basic:1 (UPnP spec)
2. Fix USN format to include full device type URN
3. Fix hue-bridgeid to use uppercase EUI-64 format (16 hex chars)
4. Increase CACHE-CONTROL max-age from 100s to 86400 (24 hours)

Fixes #5488, relates to #4875

Agent-Logs-Url: https://github.com/wled/WLED/sessions/c3fb311b-1349-48b1-abfd-6a4aca8c7a77

Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com>
2026-04-09 05:54:20 +00:00
copilot-swe-agent[bot]
4a0a4c632b Initial plan 2026-04-09 05:47:55 +00:00
Frank Möhle
5b2ae15d8d Update ESP32 options in bug issue template 2026-04-09 01:38:30 +02:00
Frank Möhle
44ddc21530 Update bug issue template with new options 2026-04-09 01:34:48 +02:00
Frank Möhle
063592c845 Refine PR review guidelines in .coderabbit.yaml
clarify "limit to top5"
a few typos fixed
2026-04-09 00:53:46 +02:00
Frank Möhle
4955af0a11 Limit suggested improvements to 'Top 5' in instructions
Updated the instructions to limit suggested improvements to 'Top 5' in multiple sections.
2026-04-09 00:43:19 +02:00
Frank Möhle
9df5d056b9 Remove redundancy in feedback guideline
the "summarize good practices" is now moved in .coderabbit.yaml. Removing it here to prevent "logic looping" and distraction.
2026-04-09 00:35:16 +02:00
Frank Möhle
3486e3bcbb Enhance PR review instructions in .coderabbit.yaml
Extend guidelines for PR reviews : including summarizing good practices and prioritizing improvements.
2026-04-09 00:25:09 +02:00
Frank Möhle
91eb69643d Enhance PR review guidelines in .coderabbit.yaml
Added guidelines for PR reviews and improvement suggestions.
2026-04-09 00:08:41 +02:00
Copilot
48b27d12ac docs: add canonical feature-flag list to copilot-instructions to catch misspellings (#5487)
Misspelled WLED_ENABLE_* / WLED_DISABLE_* flags are silently ignored by the preprocessor, causing features to be incorrectly included or excluded with no compiler warning (e.g. WLED_IR_DISABLE instead of WLED_DISABLE_INFRARED).

This PR adds an AI rule that enforces checking of feature flags against a curated list.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: softhack007 <91616163+softhack007@users.noreply.github.com>
2026-04-08 23:05:12 +02:00
Frank Möhle
78c1051cbb hiding reference to contributing.md from AI
contributing.md makes reference out to this file again
2026-04-08 21:28:29 +02:00
Frank Möhle
2302863386 copilot-instructions rework, new C++ coding guide for AI reviews (#5480)
* comprehensive C++, Web UI, and CI/CD conventions, a condensed setup/build guide, and a new agent-mode build/test workflow with ordered commands, timeouts, validation gates, manual web validation, and troubleshooting steps.

* repository-level AI review/configuration rules, workflow best-practices, safeguards to detect and flag edits to generated web assets, and alignment checks linking AI-facing rules with human-only reference sections.

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-04-08 21:06:48 +02:00
Damian Schneider
7560811480 bugfix in pixelforge (no blur by default), fix glitch in animated gifs for C3 2026-04-07 23:29:31 +02:00
Frank Möhle
12f6fbc005 robustness: Rewind file pointer before writing initial data
if the presets.json file initially contains ``{}`` (valid JSON, could be created by user edit), we need to first rewind the file. Otherwise the result would be ``{}{"0":{}}`` (ivalid JSON)
2026-04-05 22:11:00 +02:00
Will Miles
c819814904 Merge pull request #5476 from willmmiles/ipv6-filter-oops
Fix leak in blockRouterAdvertisements
2026-04-04 21:10:55 -04:00
Will Miles
0ef5ee74d4 Fix leak in blockRouterAdvertisements 2026-04-04 15:50:22 -04:00
Frank Möhle
51862e3572 Update guidelines for AI-generated code and PR expectations
Based on new instructions in wled-mm. More to come in a separate  PR :-)
2026-04-04 10:23:22 +02:00
Will Tatam
35c1f415c3 Merge branch 'main' into usage-extended 2026-04-03 15:35:08 +01:00
Will Tatam
cf03f1a16e Refactor hardware data mapping with structured arrays for LED features, peripherals, and integrations 2026-04-03 15:16:49 +01:00
Damian Schneider
aaf51927a6 bugfix: do not restrict segment inputs to allow trailing strips 2026-04-03 14:21:50 +02:00
Damian Schneider
72a43c6431 hotfix: critical bug in candle FX, integer issue in flow FX 2026-04-02 18:44:19 +02:00
Frank Möhle
7c6828d443 Clarified links in the contribution guidelines to indicate they are part of AI instructions.
Clarified links in the contribution guidelines to indicate they are part of AI instructions.
2026-04-01 19:27:09 +02:00
Frank Möhle
f8f46736ec Clarify IDE support in contributing guidelines
Updated contributing guidelines to specify that Arduino IDE is no longer supported and recommended using VSCode with PlatformIO.
2026-04-01 19:16:40 +02:00
Frank Möhle
e4f8534cf0 Enhance CONTRIBUTING.md with developer resources
Added important developer information and links to CONTRIBUTING.md to assist contributors.
2026-04-01 19:12:18 +02:00
Frank Möhle
79ecffe0f3 own heading for usermods
Updated instructions for adding a new usermod.
2026-04-01 19:04:00 +02:00
Frank Möhle
1fb636d8ea Update section title for development workflow
small clarification (AI prompt micro-tuning)
2026-04-01 18:57:18 +02:00
Frank Möhle
e04c855e6c grammar correction 2026-04-01 18:51:53 +02:00
Frank Möhle
6a627a86b7 Update usermod instructions in copilot documentation
Added instructions for adding new usermods and activating them.
2026-04-01 18:48:28 +02:00
Frank Möhle
746df24011 tiny edit 2026-04-01 18:33:19 +02:00
Frank Möhle
da64f71ce2 repository structure clarifications 2026-04-01 18:32:10 +02:00
Frank Möhle
8972b6bfe2 Update repository structure
adding more details: wled00/src, lib/, usermods/
2026-04-01 18:22:04 +02:00
Will Tatam
8241468fe2 Merge pull request #5451 from wled/dependabot/pip/requests-2.33.0
Bump requests from 2.32.4 to 2.33.0
2026-04-01 08:43:55 +01:00
Will Tatam
e9b740a915 Merge pull request #5454 from wled/dependabot/npm_and_yarn/brace-expansion-5.0.5
Bump brace-expansion from 5.0.3 to 5.0.5
2026-04-01 07:43:39 +01:00
Will Tatam
548bb6ffd5 Merge pull request #5449 from wled/dependabot/npm_and_yarn/picomatch-2.3.2
Bump picomatch from 2.3.1 to 2.3.2
2026-04-01 07:42:59 +01:00
Will Tatam
3d2fac0ad4 New extended data for usage report 2026-03-30 20:18:42 +01:00
Frank
a5f28d0fcb fix for HUB75 builds
replaces the last remaining FastLED.h with fstled_slim.h
2026-03-30 11:40:58 +02:00
Frank Möhle
fb8f8f0b08 Clarify 16_x branch description
Updated description of the 16_x branch for clarity.
We are not at "feature-freeze" yet
2026-03-30 02:34:43 +02:00
Frank Möhle
53fdf9a89c Update version numbers in copilot instructions 2026-03-30 01:39:44 +02:00
Frank Möhle
a1316034c1 Fix typo in version tag comment 2026-03-30 01:38:20 +02:00
Frank Möhle
75df4affa8 moving stuff around 2026-03-30 01:35:59 +02:00
Frank Möhle
820c841376 add tag scheme information for old/historical versions 2026-03-30 01:28:18 +02:00
Frank Möhle
34d50710b3 Update copilot-instructions with branch structure overview
Added basic project branch and release structure section to AI information
2026-03-30 01:18:19 +02:00
Frank Möhle
d0d62d9493 Clarify instructions to always use the correct source code branch
Updated instructions for providing references in analysis results.
2026-03-30 00:16:05 +02:00
Will Tatam
89b2bc2992 17.0.0-dev 2026-03-29 22:38:13 +01:00
dependabot[bot]
e019d36221 Bump brace-expansion from 5.0.3 to 5.0.5
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 5.0.3 to 5.0.5.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/v5.0.3...v5.0.5)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 5.0.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-27 00:59:09 +00:00
dependabot[bot]
3bcb0c902e Bump requests from 2.32.4 to 2.33.0
Bumps [requests](https://github.com/psf/requests) from 2.32.4 to 2.33.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.32.4...v2.33.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-version: 2.33.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-26 16:33:00 +00:00
dependabot[bot]
75b679814b Bump picomatch from 2.3.1 to 2.3.2
Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-25 22:25:54 +00:00
11 changed files with 134 additions and 52 deletions

View File

@@ -59,12 +59,13 @@ body:
options:
- ESP8266
- ESP32
- ESP32-S3
- ESP32 with ethernet
- ESP32-S2
- ESP32-S3
- ESP32-C3
- Other
- ESP32-C6 (experimental)
- ESP32-C5 (experimental)
- ESP32-C6 (experimental)
- ESP32-P4 (experimental)
validations:
required: true
- type: textarea

View File

@@ -18,6 +18,14 @@ jobs:
- uses: actions/download-artifact@v4
with:
merge-multiple: true
- name: Create draft release
uses: softprops/action-gh-release@v1
with:
body: "Release assets uploaded. Release notes pending..."
draft: True
files: |
*.bin
*.bin.gz
- name: "✏️ Generate release changelog"
id: changelog
uses: janheinrichmerker/action-github-changelog-generator@v2.4
@@ -27,12 +35,9 @@ jobs:
maxIssues: 500
# Exclude issues that were closed without resolution from changelog
excludeLabels: 'stale,wontfix,duplicate,invalid,external,question,use-as-is,not_planned'
- name: Create draft release
- name: Update release description
uses: softprops/action-gh-release@v1
with:
body: ${{ steps.changelog.outputs.changelog }}
draft: True
files: |
*.bin
*.bin.gz

16
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "wled",
"version": "16.0.0-beta",
"version": "17.0.0-dev",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "wled",
"version": "16.0.0-beta",
"version": "17.0.0-dev",
"license": "ISC",
"dependencies": {
"clean-css": "^5.3.3",
@@ -132,9 +132,9 @@
}
},
"node_modules/brace-expansion": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.3.tgz",
"integrity": "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==",
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
"integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
@@ -611,9 +611,9 @@
}
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"license": "MIT",
"engines": {
"node": ">=8.6"

View File

@@ -1,6 +1,6 @@
{
"name": "wled",
"version": "16.0.0-beta",
"version": "17.0.0-dev",
"description": "Tools for WLED project",
"main": "tools/cdata.js",
"directories": {

View File

@@ -2,6 +2,7 @@
# This is implemented as a pio post-script to ensure that we can
# place our linker script at the correct point in the command arguments.
Import("env")
import shutil
from pathlib import Path
# Linker script fragment injected into the rodata output section of whichever
@@ -18,7 +19,13 @@ DYNARRAY_INJECTION = (
def inject_before_marker(path, marker):
"""Patch a linker script file in-place, inserting DYNARRAY_INJECTION before marker."""
original = path.read_text()
path.write_text(original.replace(marker, DYNARRAY_INJECTION + marker, 1))
marker_pos = original.find(marker)
if marker_pos < 0:
raise RuntimeError(
f"DYNARRAY injection marker not found in linker script: path={path}, marker={marker!r}"
)
patched = original[:marker_pos] + DYNARRAY_INJECTION + original[marker_pos:]
path.write_text(patched)
if env.get("PIOPLATFORM") == "espressif32":
@@ -38,7 +45,6 @@ if env.get("PIOPLATFORM") == "espressif32":
# leaves the ASSERTs satisfied.
build_dir = Path(env.subst("$BUILD_DIR"))
patched_path = build_dir / "dynarray_sections.ld"
import shutil
shutil.copy(sections_ld_path, patched_path)
inject_before_marker(patched_path, "_rodata_end = ABSOLUTE(.);")

View File

@@ -37,14 +37,14 @@ def check_elf_modules(elf_path: Path, env, module_lib_builders) -> set[str]:
Returns the set of build_dir basenames for confirmed modules.
"""
readelf_path = _get_readelf_path(env)
secho(f"INFO: Checking for usermod compilation units...")
try:
result = subprocess.run(
[readelf_path, "--debug-dump=info", "--dwarf-depth=1", str(elf_path)],
capture_output=True, text=True, errors="ignore", timeout=120,
)
output = result.stdout
if result.returncode != 0 or result.stderr.strip():
secho(f"WARNING: readelf exited {result.returncode}: {result.stderr.strip()}", fg="yellow", err=True)
except (subprocess.TimeoutExpired, FileNotFoundError, OSError) as e:
secho(f"WARNING: readelf failed ({e}); skipping per-module validation", fg="yellow", err=True)
return {Path(b.build_dir).name for b in module_lib_builders} # conservative pass
@@ -143,20 +143,27 @@ def validate_map_file(source, target, env):
Exit(1)
# Identify the WLED module builders, set by load_usermods.py
module_lib_builders = env['WLED_MODULES']
module_lib_builders = env.get('WLED_MODULES')
if module_lib_builders is None:
secho("ERROR: WLED_MODULES not set — ensure load_usermods.py is run as a pre: script", fg="red", err=True)
Exit(1)
# Extract the values we care about
modules = {Path(builder.build_dir).name: builder.name for builder in module_lib_builders}
secho(f"INFO: {len(modules)} libraries linked as WLED optional/user modules")
secho(f"INFO: {len(modules)} libraries included as WLED optional/user modules")
# Now parse the map file
map_file_contents = read_lines(map_file_path)
usermod_object_count = count_usermod_objects(map_file_contents)
secho(f"INFO: {usermod_object_count} usermod object entries")
secho(f"INFO: {usermod_object_count} usermod object entries found")
elf_path = build_dir / env.subst("${PROGNAME}.elf")
confirmed_modules = check_elf_modules(elf_path, env, module_lib_builders)
if confirmed_modules:
secho(f"INFO: Code from usermod libraries found in binary: {', '.join(confirmed_modules)}")
# else - if there's no usermods found, don't generate a message. If we're legitimately missing all entries, the error report on the
# next line will trip; and if the usermod set is expected to be empty, then there's no need for yet another null message.
missing_modules = [modname for mdir, modname in modules.items() if mdir not in confirmed_modules]
if missing_modules:

View File

@@ -38,7 +38,7 @@ pyelftools==0.32
# via platformio
pyserial==3.5
# via platformio
requests==2.32.4
requests==2.33.0
# via platformio
semantic-version==2.10.0
# via platformio

View File

@@ -141,8 +141,16 @@ discover_devices() {
exit 1
fi
# Map avahi responses to strings seperated by 0x1F (unit separator)
mapfile -t raw_devices < <(avahi-browse _wled._tcp --terminate -r -p | awk -F';' '/^=/ {print $7"\x1F"$8"\x1F"$9}')
# Map avahi responses to strings separated by 0x1F (unit separator), deduplicated
mapfile -t raw_devices < <(
avahi-browse _wled._tcp --terminate -r -p |
awk -F';' '
/^=/ {
key = $7 "\x1F" $8 "\x1F" $9
if (!seen[key]++) print key
}
'
)
local devices_array=()
for device in "${raw_devices[@]}"; do

View File

@@ -296,17 +296,17 @@ void FFTcode(void * parameter)
ArduinoFFT<float> FFT = ArduinoFFT<float>(valFFT, vImag, samplesFFT, SAMPLE_RATE, true);
#elif !defined(UM_AUDIOREACTIVE_USE_INTEGER_FFT)
// allocate and initialize FFT buffers on first call
// note: free() is never used on these pointers. If it ever is implemented, this implementation can cause memory leaks (need to free raw pointers)
if (valFFT == nullptr) {
valFFT = (float*)heap_caps_aligned_calloc(16, 2 * samplesFFT, sizeof(float), MALLOC_CAP_8BIT); // SIMD requires aligned memory to 16-byte boundary. note in IDF5 there is MALLOC_CAP_SIMD available
if ((valFFT == nullptr)) return; // something went wrong
float* raw_buffer = (float*)heap_caps_malloc((2 * samplesFFT * sizeof(float)) + 16, MALLOC_CAP_8BIT);
if ((raw_buffer == nullptr)) return; // something went wrong
valFFT = (float*)(((uintptr_t)raw_buffer + 15) & ~15); // SIMD requires aligned memory to 16-byte boundary. note in IDF5 there is MALLOC_CAP_SIMD available
}
// create window
if (windowFFT == nullptr) {
windowFFT = (float*)heap_caps_aligned_calloc(16, samplesFFT, sizeof(float), MALLOC_CAP_8BIT); // SIMD requires aligned memory to 16-byte boundary. note in IDF5 there is MALLOC_CAP_SIMD available
if ((windowFFT == nullptr)) {
heap_caps_free(valFFT); valFFT = nullptr;
return; // something went wrong
}
float* raw_buffer = (float*)heap_caps_malloc((samplesFFT * sizeof(float)) + 16, MALLOC_CAP_8BIT);
if ((raw_buffer == nullptr)) return; // something went wrong
windowFFT = (float*)(((uintptr_t)raw_buffer + 15) & ~15); // SIMD requires aligned memory to 16-byte boundary
}
if (dsps_fft2r_init_fc32(NULL, samplesFFT) != ESP_OK) return; // initialize FFT tables
// create window function for FFT
@@ -316,20 +316,16 @@ void FFTcode(void * parameter)
dsps_wind_flat_top_f32(windowFFT, samplesFFT);
#endif
#else
// use integer FFT - allocate and initialize integer FFT buffers on first call, 4 bytes aligned (just in case, even if not strictly needed for int16_t)
if (valFFT == nullptr) valFFT = (int16_t*) heap_caps_aligned_calloc(4, samplesFFT * 2, sizeof(int16_t), MALLOC_CAP_8BIT);
// allocate and initialize integer FFT buffers on first call
if (valFFT == nullptr) valFFT = (int16_t*) calloc(sizeof(int16_t), samplesFFT * 2);
if ((valFFT == nullptr)) return; // something went wrong
// create window
if (windowFFT == nullptr) windowFFT = (int16_t*) heap_caps_aligned_calloc(4, samplesFFT, sizeof(int16_t), MALLOC_CAP_8BIT);
// create window function for FFT
float *windowFloat = (float*) heap_caps_aligned_calloc(4, samplesFFT, sizeof(float), MALLOC_CAP_8BIT); // temporary buffer for window function
if (windowFloat == nullptr || windowFFT == nullptr || valFFT == nullptr) { // something went wrong
if (windowFloat) heap_caps_free(windowFloat);
if (windowFFT) heap_caps_free(windowFFT); windowFFT = nullptr;
if (valFFT) heap_caps_free(valFFT); valFFT = nullptr;
return;
}
if (windowFFT == nullptr) windowFFT = (int16_t*) calloc(sizeof(int16_t), samplesFFT);
if ((windowFFT == nullptr)) return; // something went wrong
if (dsps_fft2r_init_sc16(NULL, samplesFFT) != ESP_OK) return; // initialize FFT tables
// create window function for FFT
float *windowFloat = (float*) calloc(sizeof(float), samplesFFT); // temporary buffer for window function
if ((windowFloat == nullptr)) return; // something went wrong
#ifdef FFT_PREFER_EXACT_PEAKS
dsps_wind_blackman_harris_f32(windowFloat, samplesFFT);
#else
@@ -339,7 +335,7 @@ void FFTcode(void * parameter)
for (int i = 0; i < samplesFFT; i++) {
windowFFT[i] = (int16_t)(windowFloat[i] * 32767.0f);
}
heap_caps_free(windowFloat); // free temporary buffer
free(windowFloat); // free temporary buffer
#endif
// see https://www.freertos.org/vtaskdelayuntil.html
@@ -472,6 +468,7 @@ void FFTcode(void * parameter)
}
FFT_Magnitude = FFT_Magnitude_int * 512; // scale to match raw float value
FFT_MajorPeak = FFT_MajorPeak_int;
FFT_Magnitude = FFT_Magnitude_int;
#endif
#endif
FFT_MajorPeak = constrain(FFT_MajorPeak, 1.0f, 11025.0f); // restrict value to range expected by effects

View File

@@ -1367,6 +1367,7 @@ static uint8_t _dummy (uint8_t a, uint8_t b) { return a; } // dummy (same as
void WS2812FX::blendSegment(const Segment &topSegment) const {
typedef uint8_t(*FuncType)(uint8_t, uint8_t);
// function pointer array: fill with _dummy if using special case: avoid OOB access and always provide a valid path
// note: making the function array static const uses more ram and comes at no significant speed gain
FuncType funcs[] = {
_dummy, _dummy, _dummy, _subtract,
_difference, _average, _dummy, _divide,
@@ -1398,14 +1399,71 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
const size_t matrixSize = Segment::maxWidth * Segment::maxHeight;
const size_t startIndx = XY(topSegment.start, topSegment.startY);
const size_t stopIndx = startIndx + length;
const unsigned progress = topSegment.progress();
const unsigned progInv = 0xFFFFU - progress;
uint8_t opacity = topSegment.currentBri(); // returns transitioned opacity for style FADE
uint8_t cct = topSegment.currentCCT();
if (gammaCorrectCol) opacity = gamma8inv(opacity); // use inverse gamma on brightness for correct color scaling after gamma correction (see #5343 for details)
Segment::setClippingRect(0, 0); // disable clipping by default
const Segment *segO = topSegment.getOldSegment();
const bool hasGrouping = topSegment.groupLength() != 1;
// fast path: handle the default case - no transitions, no grouping/spacing, no mirroring, no CCT
if (!segO && blendingStyle == TRANSITION_FADE && !hasGrouping && !topSegment.mirror && !topSegment.mirror_y) {
if (isMatrix && stopIndx <= matrixSize && !_pixelCCT) {
#ifndef WLED_DISABLE_2D
// Calculate pointer steps to avoid 'if' and 'XY()' inside loops
int x_inc = 1;
int y_inc = Segment::maxWidth;
int start_offset = XY(topSegment.start, topSegment.startY);
// adjust starting position and steps based on Reverse/Transpose
// note: transpose is handled in separate loop so it is still fast and no branching is needed in default path
if (!topSegment.transpose) {
if (topSegment.reverse) { start_offset += (width - 1); x_inc = -1; }
if (topSegment.reverse_y) { start_offset += (height - 1) * Segment::maxWidth; y_inc = -Segment::maxWidth; }
for (int y = 0; y < height; y++) {
uint32_t* pRow = &_pixels[start_offset + y * y_inc];
const int y_width = y * width;
for (int x = 0; x < width; x++) {
uint32_t* p = pRow + x * x_inc;
uint32_t c_a = topSegment.getPixelColorRaw(x + y_width);
*p = color_blend(*p, segblend(c_a, *p), opacity);
}
}
} else { // transposed
for (int y = 0; y < height; y++) {
const int px = topSegment.reverse ? (height - y - 1) : y; // source pixel: swap y into x, reverse if needed
for (int x = 0; x < width; x++) {
const int py = topSegment.reverse_y ? (width - x - 1) : x; // source pixel: swap x into y, reverse if needed
const uint32_t c_a = topSegment.getPixelColorRaw(px + py * height); // height = virtual width
const size_t idx = XY(topSegment.start + x, topSegment.startY + y); // write logical (non swapped) pixel coordinate
_pixels[idx] = color_blend(_pixels[idx], segblend(c_a, _pixels[idx]), opacity);
}
}
}
return;
#endif
} else if (!isMatrix) {
// 1D fast path, include CCT as it is more common on 1D setups
uint32_t* strip = _pixels;
int start = topSegment.start;
int off = topSegment.offset;
for (int i = 0; i < length; i++) {
uint32_t c_a = topSegment.getPixelColorRaw(i);
int p = topSegment.reverse ? (length - i - 1) : i;
int idx = start + p + off;
if (idx >= topSegment.stop) idx -= length;
strip[idx] = color_blend(strip[idx], segblend(c_a, strip[idx]), opacity);
if (_pixelCCT) _pixelCCT[idx] = cct;
}
return;
}
}
// slow path: handle transitions, grouping/spacing, segments with clipping and CCT pixels
Segment::setClippingRect(0, 0); // disable clipping by default
const unsigned progress = topSegment.progress();
const unsigned progInv = 0xFFFFU - progress;
const unsigned dw = (blendingStyle==TRANSITION_OUTSIDE_IN ? progInv : progress) * width / 0xFFFFU + 1;
const unsigned dh = (blendingStyle==TRANSITION_OUTSIDE_IN ? progInv : progress) * height / 0xFFFFU + 1;
const unsigned orgBS = blendingStyle;
@@ -1466,7 +1524,6 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
#ifndef WLED_DISABLE_2D
const int nCols = topSegment.virtualWidth();
const int nRows = topSegment.virtualHeight();
const Segment *segO = topSegment.getOldSegment();
const int oCols = segO ? segO->virtualWidth() : nCols;
const int oRows = segO ? segO->virtualHeight() : nRows;
@@ -1562,8 +1619,8 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
}
#endif
} else {
// 1D Slow Path
const int nLen = topSegment.virtualLength();
const Segment *segO = topSegment.getOldSegment();
const int oLen = segO ? segO->virtualLength() : nLen;
const auto setMirroredPixel = [&](int i, uint32_t c, uint8_t o) {
@@ -1643,7 +1700,7 @@ void WS2812FX::show() {
if (realtimeMode == REALTIME_MODE_INACTIVE || useMainSegmentOnly || realtimeOverride > REALTIME_OVERRIDE_NONE) {
// clear frame buffer
for (size_t i = 0; i < totalLen; i++) _pixels[i] = BLACK; // memset(_pixels, 0, sizeof(uint32_t) * getLengthTotal());
memset(_pixels, 0, sizeof(uint32_t) * totalLen);
// blend all segments into (cleared) buffer
for (Segment &seg : _segments) if (seg.isActive() && (seg.on || seg.isInTransition())) {
blendSegment(seg); // blend segment's buffer into frame buffer

View File

@@ -188,6 +188,7 @@ static bool appendObjectToFile(const char* key, const JsonDocument* content, uin
if (f.size() < 3) {
char init[10];
strcpy_P(init, PSTR("{\"0\":{}}"));
f.seek(0, SeekSet); // rewind to ensure we overwrite from the start, instead of appending
f.print(init);
}