From 03379d71207b515b67cc4ab03cdad9c296b1398d Mon Sep 17 00:00:00 2001 From: Yona Appletree Date: Sat, 1 Aug 2026 21:31:41 -0700 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20close=20out=20the=20RMT-priority=20?= =?UTF-8?q?plan=20=E2=80=94=20G1=20decisions,=20license=20addendum,=20debt?= =?UTF-8?q?=20entry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit P6 of the RMT-priority/HLI plan, committed post-merge of #268. * fw-esp32c6 README: 2ch x 24-word halves is the SHIPPED DEFAULT (G1 Q1), with the measured scan numbers (28.0% vs 0.49%) and the OPC/E1.31 = S4 reopen trigger; stress features documented; D8 marked non-RMT. * lp-ws281x README: entry-delay telemetry credited as the instrument that attributed the C6 scan truncation to entry latency, not refill work. * License-discipline ADR addendum: WLED relicensed MIT->EUPL 2024-10-15; the 'GPL shim' shorthand corrected; consult-prohibition unchanged for post-switch code; the MIT-era provenance path recorded. (A firewalled investigation subsequently established WLED contains NO interrupt shim at any revision — its stability mechanism is NeoPixelBus/LGPL I2S+DMA — which the HLI experiment's ADR will record in full.) * NEW debt entry c6-scan-truncation-accepted: the consciously-carried G1 tradeoff, with exit criteria (S4 measurement on OPC/E1.31; I2S/DMA backend would retire it). Plan: 2026-08-01-1459-rmt-priority-hli Co-Authored-By: Claude Opus 5 --- ...026-07-29-license-provenance-discipline.md | 30 ++++++++++++++ docs/debt/README.md | 1 + docs/debt/c6-scan-truncation-accepted.md | 40 ++++++++++++++++++ lp-fw/fw-esp32c6/README.md | 41 +++++++++++++++---- lp-fw/lp-ws281x/README.md | 8 ++++ 5 files changed, 112 insertions(+), 8 deletions(-) create mode 100644 docs/debt/c6-scan-truncation-accepted.md diff --git a/docs/adr/2026-07-29-license-provenance-discipline.md b/docs/adr/2026-07-29-license-provenance-discipline.md index bc5240cd2..8eae347c7 100644 --- a/docs/adr/2026-07-29-license-provenance-discipline.md +++ b/docs/adr/2026-07-29-license-provenance-discipline.md @@ -131,3 +131,33 @@ section. Review of any PR touching `lp-xt-*` should check the headers. - ~~Formalize the CLA / DCO-with-grant mechanism when the first outside contribution to relicensing-sensitive code is proposed.~~ Done ahead of that trigger — see `2026-07-31-contributor-license-agreement.md`. + +## Addendum (2026-08-01): WLED's license changed, and is not GPL + +Several planning docs referring to WLED's ESP32 RMT driver as off-limits +(the classic-ESP32 bring-up roadmap's M5 brief, `lp-fw/lp-ws281x`'s +provenance note) describe it loosely as "WLED's GPL shim." That is imprecise +and, for older code, wrong. Verified from WLED's repo history (via +Ben Hencke) during roadmap M5's `2026-08-01-1459-rmt-priority-hli` plan: + +- WLED was **MIT-licensed from 2016-12-28 to 2024-10-15**, then relicensed to + **EUPL** ("Re-license the WLED project from MIT to EUPL (#4194)"). + Relicensing is not retroactive — revisions before the switch remain MIT. +- The consult-prohibition in this ADR and `AGENTS.md` (no copying, + transliterating, or line-by-line adapting from copyleft sources) applies + to WLED's **post-switch EUPL code** the same as it would to GPL: EUPL is + copyleft, and neither this ADR's decision nor `AGENTS.md`'s enforcement + distinguishes "which copyleft license" — the rule is "no copyleft source, + full stop," so the practical prohibition is unchanged by this correction. +- What changes: a **pre-2024-10-15 MIT revision** of WLED's own code (not + NeoPixelBus, which it may have adapted — NeoPixelBus was historically + LGPL and needs its own check) is permissively licensed and, per this ADR's + rule 2, portable with attribution and a provenance header, unlike GPL/EUPL + source. This does not by itself authorize using it — it opens a path that + did not previously exist for one specific piece of code. +- The concrete instance: the classic ESP32's level-4/5 high-priority + interrupt vector, parked NO-GO at M5's G1 gate + (`2026-08-01-1459-rmt-priority-hli/notes.md`, "G1 COMPLETE"). Its + documented reopen ladder now runs a step-zero, per-file provenance check + against WLED's MIT-era history before falling back to pure clean-room from + Espressif's Apache-licensed `hli_vector.S`. diff --git a/docs/debt/README.md b/docs/debt/README.md index 909fa7e69..12fe05a24 100644 --- a/docs/debt/README.md +++ b/docs/debt/README.md @@ -53,6 +53,7 @@ stay in place when retired; the log is the history). | Entry | Status | Since | Area | Cost in one line | | --- | --- | --- | --- | --- | +| [c6-scan-truncation-accepted](c6-scan-truncation-accepted.md) | carried | 2026-08-01 | fw-esp32c6 ws281x default config | 2ch default truncates ~28% of frames during WiFi scans (editing-time only); reopens on OPC/E1.31 streaming | | [brightness-applied-before-gamma](brightness-applied-before-gamma.md) | carried | 2026-08-01 | lpc-engine fixture node (value pipeline) | dim gamma-on fixtures collapse to ~1 wire code (30× resolution loss at brightness 38); projects work around it by shipping gamma off | | [lps-probe-perf-test-load-sensitive](lps-probe-perf-test-load-sensitive.md) | carried | 2026-08-01 | lps-probe/tests | spurious full-gate reds whenever a dev server or sibling session runs; ~20% wall-clock headroom | | [bundled-firmware-chip-unplumbed](bundled-firmware-chip-unplumbed.md) | carried | 2026-07-27 | studio-web roster cards | the "firmware update available" chip is implemented, tested and story-visible, but `bundled_fw` is never supplied in production — the feature never fires | diff --git a/docs/debt/c6-scan-truncation-accepted.md b/docs/debt/c6-scan-truncation-accepted.md new file mode 100644 index 000000000..97ba6498d --- /dev/null +++ b/docs/debt/c6-scan-truncation-accepted.md @@ -0,0 +1,40 @@ +--- +status: carried +since: 2026-08-01 +logged: 2026-08-01 +area: fw-esp32c6 WS281x output (2-channel default config) +related: + - docs/adr/2026-07-29-license-provenance-discipline.md + - lp-fw/fw-esp32c6/README.md (WS281x section) +--- +# The C6's 2-channel default truncates ~28 % of frames during WiFi scans + +**Shape** — the shipped C6 default gives each of its two RMT TX channels one +48-word block (24-word ping-pong halves, 30 µs refill deadlines). Measured +2026-08-01 on the desk jig: under a continuous active-scan loop the +first-started channel truncates **28.0 %** of frames (guard-word trips; +bounded staleness, never corruption), the second 1.3 %. The alternative +config (`ws281x_2blocks`: one channel, 60 µs deadlines) measures 0.49 % under +the same load. Idle and ESP-NOW — the C6's actual shipping radio — measure +clean in both configs (worst: 1 trip in ~2,800 frames). The mechanism is +interrupt-to-service latency during the radio's masked windows, measured at +`Priority::max()`; RISC-V has no higher level, so no software priority fix +exists. Margin (bigger halves) is the only working software lever. + +**Why it is acceptable now** — decided at the RMT-priority plan's G1 +(2026-08-01): scan-class WiFi load is an editing-time concern, not a +deployed-install concern, and the second output is worth more than scan +robustness. The truncation is visible shimmer during scans, bounded to one +frame period per trip. + +**Exit criteria** — reopens if OPC or E1.31 streaming (or any sustained +STA/UDP usage — the never-measured S4 scenario) enters the C6's product +path: measure S4 first, then revisit the default via the recorded matrix +(plan dir `2026-08-01-1459-rmt-priority-hli`, p4 file + logs). A future +I2S/DMA backend (no refill deadline at all) would retire this entirely. + +**Log** + +- 2026-08-01 — measured (P4 matrix), accepted at G1 with the reopen trigger + named by Yona: "wifi load isn't a big concern for actual used installs... + unless we start streaming opc or e131." diff --git a/lp-fw/fw-esp32c6/README.md b/lp-fw/fw-esp32c6/README.md index d2551b409..194ec965e 100644 --- a/lp-fw/fw-esp32c6/README.md +++ b/lp-fw/fw-esp32c6/README.md @@ -31,24 +31,49 @@ belongs in `fw-host`. Browser Studio simulation belongs in `fw-browser`. `src/output/rmt/` implements `lp_ws281x::RmtHw` for this chip and registers one driver at boot; the sequencing lives in `lp-fw/lp-ws281x` and is shared with `fw-esp32s3` and `fw-esp32v3`. The chip has **two RMT TX channels** (48-word -memory blocks), and both are usable in the shipped configuration: +memory blocks): | Build | Blocks/channel | Usable channels | Window | Refill half | | --- | --- | --- | --- | --- | -| default | 1 | 2 (`/rmt/ws281x0`, `/rmt/ws281x1`) | 48 words | 24 words (~30 µs) | +| default (**shipped**) | 1 | 2 (`/rmt/ws281x0`, `/rmt/ws281x1`) | 48 words | 24 words (~30 µs) | | `--features ws281x_2blocks` | 2 | 1 (slot 1 absorbed) | 96 words | 48 words (~60 µs) | -Which one ships is a measurement question (roadmap M5's stress matrix), so it is -a cargo feature, never an env var — and cargo tracks feature-driven `cfg` -unreliably here, so `touch src/main.rs` before rebuilding after flipping it. -`--features ws281x_telemetry` adds a periodic `[WS281X]` counters line per -channel, in the same field order the classic firmware prints. +**2ch × 24-word halves ships as the default**, decided at roadmap M5's G1 gate +(`2026-08-01-1459-rmt-priority-hli`, phase P4) from measurement, not +arithmetic: under a WiFi scan, the default's first channel truncates 28.0 % +of frames (1,380/4,932) vs the `ws281x_2blocks` single-channel config's +0.49 % (25/5,071) — margin drops truncation 57×, but does not eliminate it, +and the C6 sits at `Priority::max()` already (RISC-V has no headroom above +maskable levels to raise into). Yona's call: "wifi load isn't a big concern +for actual used installs. that's mostly an editing concern, unless we start +streaming opc or e131" — so `ws281x_2blocks` is the documented fallback for +scan-heavy conditions (e.g. mid-edit with the client connected over WiFi), +not the shipped default. **Reopen trigger**: OPC/E1.31-over-WiFi streaming +lands (that is also the unmeasured S4 scenario — sustained UDP while +associated — so S4 measurement precedes any config revisit). + +Which one ships is therefore a cargo feature, never an env var — and cargo +tracks feature-driven `cfg` unreliably here, so `touch src/main.rs` before +rebuilding after flipping it. `--features ws281x_telemetry` adds a periodic +`[WS281X]` counters line per channel, in the same field order the classic +firmware prints, including the entry-delay fields (see `lp-fw/lp-ws281x`'s +README for what they measure — they are what attributed the scan truncation +above to interrupt-to-service latency rather than refill work). + +`--features stress_s2` and `--features stress_s3` add embassy tasks that +replace the ESP-NOW radio driver registration with a continuous load +generator — S2 repeats active WiFi scans to completion, S3 sends bursts of +ESP-NOW broadcasts — for reproducing the M5 stress matrix on the desk. Both +imply `radio`, are off by default, and cost the shipping image nothing +(byte-identical size-check with either enabled). They are a measurement tool, +not a product feature. Which pins the two channels drive is authored, not fixed: an `Output` node names a board label (`ws281x:rmt:D10`) and the driver binds that GPIO when the project opens the endpoint. The desk jig used for M5 wires three strips — D10/GPIO18, D9/GPIO20, and D8/GPIO19. Only the first two can be RMT channels; D8 is spare -for a future SPI-class output, since the chip has no third TX channel. +for a future SPI-class output — **not an RMT resource**, since the chip has +no third TX channel. ## Common Commands diff --git a/lp-fw/lp-ws281x/README.md b/lp-fw/lp-ws281x/README.md index 1756c5a98..721a46403 100644 --- a/lp-fw/lp-ws281x/README.md +++ b/lp-fw/lp-ws281x/README.md @@ -213,6 +213,14 @@ higher-numbered ones includes every earlier channel's refill — which is the co `on_interrupt`'s index-order service actually imposes, now measured rather than inferred. +This is the instrument that settled the C6's WiFi-scan truncation: roadmap +M5's stress matrix (`2026-08-01-1459-rmt-priority-hli`, phase P4) found +refill lag flat with or without radio load, while the entry-delay histogram's +delayed-entry population grew two orders of magnitude under scan — the +truncation is interrupt-to-service latency, not refill work, which is also +why raising software priority alone (already at `Priority::max()`) had no +headroom left to give. + `record_lag` deliberately keeps the running maximum with a load/compare/store rather than `fetch_max`, and the interrupt handler is the only writer, so nothing is lost. This began as a workaround — `AtomicI32::fetch_max` would not From 572f2527a747d4250e868549313e74cd6c3ef594 Mon Sep 17 00:00:00 2001 From: Yona Appletree Date: Sat, 1 Aug 2026 21:47:02 -0700 Subject: [PATCH 2/2] docs: attribute the WLED license finding to a community tip The verification stands on the repo's own public history; no individual needs naming. Co-Authored-By: Claude Opus 5 --- docs/adr/2026-07-29-license-provenance-discipline.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/adr/2026-07-29-license-provenance-discipline.md b/docs/adr/2026-07-29-license-provenance-discipline.md index 8eae347c7..b8a8e0531 100644 --- a/docs/adr/2026-07-29-license-provenance-discipline.md +++ b/docs/adr/2026-07-29-license-provenance-discipline.md @@ -137,8 +137,8 @@ section. Review of any PR touching `lp-xt-*` should check the headers. Several planning docs referring to WLED's ESP32 RMT driver as off-limits (the classic-ESP32 bring-up roadmap's M5 brief, `lp-fw/lp-ws281x`'s provenance note) describe it loosely as "WLED's GPL shim." That is imprecise -and, for older code, wrong. Verified from WLED's repo history (via -Ben Hencke) during roadmap M5's `2026-08-01-1459-rmt-priority-hli` plan: +and, for older code, wrong. Following a community tip, verified from WLED's +own repo history during roadmap M5's `2026-08-01-1459-rmt-priority-hli` plan: - WLED was **MIT-licensed from 2016-12-28 to 2024-10-15**, then relicensed to **EUPL** ("Re-license the WLED project from MIT to EUPL (#4194)").