From a13aabcd79f24c38e2e74260a00a34f2e4fc7a67 Mon Sep 17 00:00:00 2001 From: Eric Dahl Date: Sat, 4 Jul 2026 00:27:59 -0400 Subject: [PATCH 1/3] =?UTF-8?q?esp32:=20file=20LNK-029=20=E2=80=94=20resea?= =?UTF-8?q?rch=20mixer=20FX-slot=20introspection=20+=20multi-slot=20tempo?= =?UTF-8?q?=20control?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Research ticket (todo, needs-triage): what /fx/N/type + /fx/N/par/MM let us learn about loaded FX slots, which tempo-syncable params are worth controlling, how to drive multiple tempo effects at once (per-target note division + per-algorithm encoding), and extending config from one fx_slot to N targets. Deliverable is a findings doc + design recommendation, not code. Claude-Session: https://claude.ai/code/session_01WSeSToFVSvAFBDvHewrMHo --- esp32/tasks/LNK-029.md | 99 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 esp32/tasks/LNK-029.md diff --git a/esp32/tasks/LNK-029.md b/esp32/tasks/LNK-029.md new file mode 100644 index 0000000..047369e --- /dev/null +++ b/esp32/tasks/LNK-029.md @@ -0,0 +1,99 @@ +--- +id: LNK-029 +title: "Research: mixer FX-slot introspection + multi-slot / multi-param tempo control" +status: todo +assignee: null +priority: medium +tags: [link-firmware, osc, fx, mixer, research, needs-triage] +depends_on: [LNK-005] +created_at: 2026-07-04 +updated_at: 2026-07-04 +--- + +## Goal + +Scope what the device could do with mixer FX beyond today's single hardcoded +target. Today (LNK-005) we send BPM → `/fx//par/01 ,f` (delay-time param) +to **one** configured slot, send-only, assuming the slot holds a delay. This +ticket researches four questions before any implementation: + +1. **What can we read from the mixer about the FX slots?** +2. **What other parameters make sense to tempo-control?** +3. **How to handle multiple tempo-syncable effects at once** (e.g. a delay in one + slot and another effect with its own tap-tempo/rate in another)? +4. **Should we control more than one FX slot?** + +Output is a findings doc + a design recommendation, **not** code. + +## What we already know (grounding) + +- `/fx/N/type ,i` — the loaded **algorithm** per slot, index `[0,60]` + (`docs/xr18-xair-osc-cheatsheet.md`). This is the key introspection hook. +- `/fx/N/par/MM ,f` — per-algorithm parameters, `MM = 01..64`. Which `MM` is the + tempo/delay-time param **depends on the algorithm** (par/01 happens to be delay + time for the delay algorithms we target now). +- We are currently **send-only** and never read `/fx/N/type` — so we're blind to + what's actually loaded and just assume par/01. +- XR18 has 4 FX slots, X32 has 8 (`config_model_slot_max`). +- The receive/subscribe plumbing exists (`osc_in`, xremote — LNK-013), so reading + back mixer state is feasible, we just don't use it for FX. + +## Research questions + +### Q1 — FX-slot introspection +- Read `/fx/N/type` for each slot → know the algorithm. Can we also get a + human-readable name, or only the index? Build the **index → algorithm** table + for XR18 and X32 (they may differ). +- For each tempo-relevant algorithm, which `par/MM` is the tempo/delay-time param, + and what are its **units/encoding** (normalized float → ms? a note-division + enum? a raw ms value?). Does the XR/X32 FX expose a "tempo sync on/off" or a + "division" param we should set instead of writing a raw time? +- Can/should we **subscribe** (xremote) so we track slot type changes live and + avoid writing a delay-time to a slot the user just changed to reverb? + +### Q2 — which params are worth controlling +- Catalog tempo-syncable params across algorithms: delay time (delays), LFO rate + (chorus/flanger/phaser), reverb pre-delay, tremolo/auto-pan rate, gate/ducker + timing. Note which are musically useful to lock to Link tempo vs noise. +- Non-tempo params worth a look while we're here? (probably out of scope — keep + this ticket tempo-focused, list others as future.) + +### Q3 — multiple tempo-syncable effects at once +- If a user has a delay in slot 1 and, say, a tremolo/tap-tempo effect in slot 3, + both want the tempo. The device is the tempo authority — we'd write each slot's + tempo param directly (overriding the mixer's own tap-tempo). Confirm that's the + right model vs trying to drive the mixer's tap-tempo input. +- Different targets may want **different note divisions** (1/4 vs 1/8-dotted vs + 1/2). Implies a per-target division/multiplier, not one global BPM→ms. +- Encoding differs per algorithm (ms float vs division enum) — the per-target + mapping must carry the algorithm's param index + unit conversion. + +### Q4 — multi-slot control +- Extend config from a single `fx_slot` to a set of targets: each `{slot, + enabled, division, (auto-detected type → param index + unit)}`. +- Config/UI implications: the web + touch UIs, NVS schema, and validation grow + from one slot to N. How much of the mapping can be **auto-derived** from + `/fx/N/type` so the user just picks slots + divisions? +- Rate-limit / OSC-flood concerns when writing several params on every tempo + change (reuse LNK-011 bpm_publisher send-policy). + +## Deliverables (this is research) + +- [ ] `index → algorithm` tables for XR18 and X32, annotated with the tempo param + index + unit/encoding for each tempo-relevant algorithm. +- [ ] Recommendation: **auto-detect** FX type via `/fx/N/type` (+ optional + subscribe) vs **manual** per-slot config — with the tradeoffs. +- [ ] A proposed config/UI/NVS shape for N targets with per-target note division. +- [ ] A note on the tap-tempo question (write params directly vs drive tap input). +- [ ] Follow-on implementation tickets filed from the findings. + +## Notes + +- Rides on LNK-005 (current FX delay send), LNK-011 (send policy), LNK-013 + (`osc_in`/xremote read-back), and the phase/tempo pipeline validated in LNK-020. +- Reference: `docs/x32-osc-protocol.md`, `docs/xr18-xair-osc-cheatsheet.md`, + `docs/xr18-geq-osc.md`. Hardware to probe: the XR18 (and X32 if available) via + `osc_in` dumps of `/fx/N/type` and `/fx/N/par/*` while loading different + algorithms. +- Keep any resulting unit-conversion math (BPM + division → ms/enum) in a pure, + host-tested module, same pattern as the rest of the firmware. From 455685c130be0f909b8ae1beabdae3bb28a9d131 Mon Sep 17 00:00:00 2001 From: Eric Dahl Date: Sat, 4 Jul 2026 00:29:50 -0400 Subject: [PATCH 2/3] LNK-029: add Behringer Wing as a research track (different OSC protocol) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Wing isn't an X32-family device — different address tree/param model/encoding, more FX slots, richer introspection. Adds Q5 (Wing protocol, FX topology, introspection, MODEL_WING integration, discovery) and a Wing assessment deliverable; Q1–Q4 must be answered independently for the Wing. Claude-Session: https://claude.ai/code/session_01WSeSToFVSvAFBDvHewrMHo --- esp32/tasks/LNK-029.md | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/esp32/tasks/LNK-029.md b/esp32/tasks/LNK-029.md index 047369e..929b88b 100644 --- a/esp32/tasks/LNK-029.md +++ b/esp32/tasks/LNK-029.md @@ -1,10 +1,10 @@ --- id: LNK-029 -title: "Research: mixer FX-slot introspection + multi-slot / multi-param tempo control" +title: "Research: mixer FX-slot introspection + multi-slot tempo control (X32/XR18 + Wing)" status: todo assignee: null priority: medium -tags: [link-firmware, osc, fx, mixer, research, needs-triage] +tags: [link-firmware, osc, fx, mixer, wing, research, needs-triage] depends_on: [LNK-005] created_at: 2026-07-04 updated_at: 2026-07-04 @@ -37,6 +37,10 @@ Output is a findings doc + a design recommendation, **not** code. - XR18 has 4 FX slots, X32 has 8 (`config_model_slot_max`). - The receive/subscribe plumbing exists (`osc_in`, xremote — LNK-013), so reading back mixer state is feasible, we just don't use it for FX. +- **Model support today is XR18/X32 only** (`MODEL_XR18=1`, `MODEL_X32=2`; + `config_model_port` → X32:10023 / XR18:10024). The whole OSC layer assumes the + **X32-family address tree** (`/fx/N/par/MM`). The **Behringer Wing does not share + that protocol** — see Q5. ## Research questions @@ -77,6 +81,32 @@ Output is a findings doc + a design recommendation, **not** code. - Rate-limit / OSC-flood concerns when writing several params on every tempo change (reuse LNK-011 bpm_publisher send-policy). +### Q5 — Behringer Wing support (different protocol, not a config tweak) +The Wing is a separate research track because it is **not** an X32-family device: +- **Protocol dialect.** The Wing speaks its own control protocol (OSC-style plus a + text/`$`-style command channel) with a **different address tree, node/param + model, and encoding** than X32/XR18's `/fx/N/par/MM`. Confirm: the Wing's UDP + control port(s), whether plain OSC works or the node protocol is required, and + how FX parameters are addressed and encoded (name-addressed nodes vs numeric + par indices; value units). +- **FX topology.** Confirm the Wing's FX slot count and effect set (it has more, + and different "premium" effects than the X32 verb/delay set), and which effects + are tempo-syncable + how their tempo param is expressed (ms vs beat-division vs + a sync/tap node). +- **Introspection.** Does the Wing expose richer read-back (effect type/name per + slot, param metadata) than X32's `/fx/N/type`? If so, auto-detection (Q1) may be + cleaner on Wing than on X32. +- **Firmware integration.** What it takes to add `MODEL_WING`: a new model id + + port in `config_model_port`/`config_model_slot_max`, and — crucially — whether + the X32-specific `osc_out`/`osc_in` layer can be parameterized or needs a + **separate Wing OSC dialect module** behind the existing `tempo_source`→OSC seam. + Estimate how much of Q1–Q4 (introspection, param catalog, multi-slot fan-out, + per-target divisions) is reusable vs Wing-specific. +- **Discovery/connection.** How the device finds/targets a Wing on the LAN vs the + X32 (mixer IP is user-set today; confirm the Wing is reachable the same way). + +Answer Q1–Q4 **independently for the Wing** — do not assume the X32 findings port. + ## Deliverables (this is research) - [ ] `index → algorithm` tables for XR18 and X32, annotated with the tempo param @@ -85,7 +115,12 @@ Output is a findings doc + a design recommendation, **not** code. subscribe) vs **manual** per-slot config — with the tradeoffs. - [ ] A proposed config/UI/NVS shape for N targets with per-target note division. - [ ] A note on the tap-tempo question (write params directly vs drive tap input). -- [ ] Follow-on implementation tickets filed from the findings. +- [ ] **Wing protocol assessment:** control port(s), address/encoding model, FX + topology + tempo params, introspection capability, and a `MODEL_WING` + feasibility estimate — how much of the X32 OSC layer is reusable vs needs a + separate Wing dialect module behind the `tempo_source`→OSC seam. +- [ ] Follow-on implementation tickets filed from the findings (X32/XR18 and Wing + likely land as separate implementation tickets given the protocol split). ## Notes From de7924179afabb99960c859edd38969ef5bcb90a Mon Sep 17 00:00:00 2001 From: Eric Dahl Date: Sat, 4 Jul 2026 00:34:42 -0400 Subject: [PATCH 3/3] LNK-030: split Wing support into its own (later, lower-priority) research issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Back Wing out of LNK-029 (now X32/XR18-only, with a scope pointer) and file LNK-030 for the Wing's separate control protocol — different address/param model, more FX slots, MODEL_WING integration. Priority low; depends on LNK-029 as the template. Claude-Session: https://claude.ai/code/session_01WSeSToFVSvAFBDvHewrMHo --- esp32/tasks/LNK-029.md | 44 ++++-------------------- esp32/tasks/LNK-030.md | 76 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 38 deletions(-) create mode 100644 esp32/tasks/LNK-030.md diff --git a/esp32/tasks/LNK-029.md b/esp32/tasks/LNK-029.md index 929b88b..c81fcfa 100644 --- a/esp32/tasks/LNK-029.md +++ b/esp32/tasks/LNK-029.md @@ -1,10 +1,10 @@ --- id: LNK-029 -title: "Research: mixer FX-slot introspection + multi-slot tempo control (X32/XR18 + Wing)" +title: "Research: mixer FX-slot introspection + multi-slot / multi-param tempo control" status: todo assignee: null priority: medium -tags: [link-firmware, osc, fx, mixer, wing, research, needs-triage] +tags: [link-firmware, osc, fx, mixer, research, needs-triage] depends_on: [LNK-005] created_at: 2026-07-04 updated_at: 2026-07-04 @@ -37,10 +37,9 @@ Output is a findings doc + a design recommendation, **not** code. - XR18 has 4 FX slots, X32 has 8 (`config_model_slot_max`). - The receive/subscribe plumbing exists (`osc_in`, xremote — LNK-013), so reading back mixer state is feasible, we just don't use it for FX. -- **Model support today is XR18/X32 only** (`MODEL_XR18=1`, `MODEL_X32=2`; - `config_model_port` → X32:10023 / XR18:10024). The whole OSC layer assumes the - **X32-family address tree** (`/fx/N/par/MM`). The **Behringer Wing does not share - that protocol** — see Q5. + +Scope note: this ticket is **X32-family only** (XR18/X32). Behringer **Wing** is a +different control protocol and is tracked separately in **LNK-030** (later). ## Research questions @@ -81,32 +80,6 @@ Output is a findings doc + a design recommendation, **not** code. - Rate-limit / OSC-flood concerns when writing several params on every tempo change (reuse LNK-011 bpm_publisher send-policy). -### Q5 — Behringer Wing support (different protocol, not a config tweak) -The Wing is a separate research track because it is **not** an X32-family device: -- **Protocol dialect.** The Wing speaks its own control protocol (OSC-style plus a - text/`$`-style command channel) with a **different address tree, node/param - model, and encoding** than X32/XR18's `/fx/N/par/MM`. Confirm: the Wing's UDP - control port(s), whether plain OSC works or the node protocol is required, and - how FX parameters are addressed and encoded (name-addressed nodes vs numeric - par indices; value units). -- **FX topology.** Confirm the Wing's FX slot count and effect set (it has more, - and different "premium" effects than the X32 verb/delay set), and which effects - are tempo-syncable + how their tempo param is expressed (ms vs beat-division vs - a sync/tap node). -- **Introspection.** Does the Wing expose richer read-back (effect type/name per - slot, param metadata) than X32's `/fx/N/type`? If so, auto-detection (Q1) may be - cleaner on Wing than on X32. -- **Firmware integration.** What it takes to add `MODEL_WING`: a new model id + - port in `config_model_port`/`config_model_slot_max`, and — crucially — whether - the X32-specific `osc_out`/`osc_in` layer can be parameterized or needs a - **separate Wing OSC dialect module** behind the existing `tempo_source`→OSC seam. - Estimate how much of Q1–Q4 (introspection, param catalog, multi-slot fan-out, - per-target divisions) is reusable vs Wing-specific. -- **Discovery/connection.** How the device finds/targets a Wing on the LAN vs the - X32 (mixer IP is user-set today; confirm the Wing is reachable the same way). - -Answer Q1–Q4 **independently for the Wing** — do not assume the X32 findings port. - ## Deliverables (this is research) - [ ] `index → algorithm` tables for XR18 and X32, annotated with the tempo param @@ -115,12 +88,7 @@ Answer Q1–Q4 **independently for the Wing** — do not assume the X32 findings subscribe) vs **manual** per-slot config — with the tradeoffs. - [ ] A proposed config/UI/NVS shape for N targets with per-target note division. - [ ] A note on the tap-tempo question (write params directly vs drive tap input). -- [ ] **Wing protocol assessment:** control port(s), address/encoding model, FX - topology + tempo params, introspection capability, and a `MODEL_WING` - feasibility estimate — how much of the X32 OSC layer is reusable vs needs a - separate Wing dialect module behind the `tempo_source`→OSC seam. -- [ ] Follow-on implementation tickets filed from the findings (X32/XR18 and Wing - likely land as separate implementation tickets given the protocol split). +- [ ] Follow-on implementation tickets filed from the findings. ## Notes diff --git a/esp32/tasks/LNK-030.md b/esp32/tasks/LNK-030.md new file mode 100644 index 0000000..399d958 --- /dev/null +++ b/esp32/tasks/LNK-030.md @@ -0,0 +1,76 @@ +--- +id: LNK-030 +title: "Research: Behringer Wing support (different OSC protocol) for tempo/FX control" +status: todo +assignee: null +priority: low +tags: [link-firmware, osc, fx, mixer, wing, research, needs-triage] +depends_on: [LNK-005, LNK-029] +created_at: 2026-07-04 +updated_at: 2026-07-04 +--- + +## Goal + +Assess what it takes to support the **Behringer Wing** as a mixer target for +tempo/FX control, the way we support XR18/X32 today. The Wing is **not** an +X32-family device — different control protocol — so this is its own research +track, deliberately **later** than the X32/XR18 FX work in LNK-029. Output is a +findings doc + a `MODEL_WING` feasibility recommendation, **not** code. + +## Why separate from LNK-029 + +LNK-029 (X32/XR18 FX-slot introspection + multi-slot tempo control) assumes the +**X32-family address tree** (`/fx/N/par/MM`, ports 10023/10024). The Wing uses a +different address/param model, so its findings won't port. It's also farther down +the roadmap — keep it from blocking the X32/XR18 work. Reuse LNK-029's *method* +(introspect FX type → map tempo param → fan out to N targets with per-target note +division), just re-answered for the Wing. + +## What we know today (grounding) + +- Model support is XR18/X32 only: `MODEL_XR18=1`, `MODEL_X32=2` + (`app_config.h`); `config_model_port` → X32:10023 / XR18:10024; + `config_model_slot_max` → X32:8 / XR18:4. +- The OSC layer (`osc_out`/`osc_in`) is X32-dialect-specific. Adding a Wing means + either parameterizing that layer or adding a **separate Wing OSC dialect + module** behind the existing `tempo_source`→OSC seam. + +## Research questions + +- **Protocol dialect.** The Wing speaks its own control protocol (OSC-style plus a + text/`$`-style command channel) with a different address tree, node/param model, + and encoding. Confirm: control UDP port(s); whether plain OSC suffices or the + node protocol is required; how FX params are addressed and encoded + (name-addressed nodes vs numeric par indices; value units). +- **FX topology.** Confirm the Wing's FX slot count and effect set (more slots and + a different "premium" effect set than X32's verb/delay), which effects are + tempo-syncable, and how each tempo param is expressed (ms vs beat-division vs a + sync/tap node). +- **Introspection.** Does the Wing expose richer read-back (effect type/name per + slot, param metadata) than X32's `/fx/N/type`? If so, auto-detection may be + *cleaner* on Wing. +- **Firmware integration.** What `MODEL_WING` needs: a new model id + port in + `config_model_port`/`config_model_slot_max`, and how much of LNK-029's Q1–Q4 + (introspection, param catalog, multi-slot fan-out, per-target divisions) is + reusable vs Wing-specific. Estimate: parameterize `osc_out`/`osc_in` vs a new + dialect module. +- **Discovery/connection.** Confirm a Wing is reached the same way as the X32 + (user-set mixer IP) or needs different discovery. + +## Deliverables (this is research) + +- [ ] Wing control port(s) + address/encoding model documented (with real dumps + from a Wing if one is available). +- [ ] Wing FX topology: slot count, tempo-syncable effects, tempo-param encoding. +- [ ] Introspection capability assessment (vs X32 `/fx/N/type`). +- [ ] `MODEL_WING` feasibility + integration recommendation: parameterize the + existing OSC layer vs a separate Wing dialect module behind the seam; how + much of LNK-029 is reusable. +- [ ] Follow-on Wing implementation ticket(s) filed from the findings. + +## Notes + +- Do the X32/XR18 research (LNK-029) first; use its structure as the template. +- Needs a Wing on the bench (or its documented protocol) to dump `/fx` state. +- Keep any tempo→param unit math in a pure, host-tested module, same as the rest.