Skip to content

g6_03: per-trial duty byte in trial-params (param[11]) — stacked on #65#66

Open
mbreiser wants to merge 2 commits into
mainfrom
docs/duty-override-0x1d-0x1e
Open

g6_03: per-trial duty byte in trial-params (param[11]) — stacked on #65#66
mbreiser wants to merge 2 commits into
mainfrom
docs/duty-override-0x1d-0x1e

Conversation

@mbreiser

@mbreiser mbreiser commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Reworked after the design pivot: the withdrawn 0x1D/0x1E opcodes are gone from this PR; it now documents the optional per-trial duty byte that merged in Arena-Firmware PR #39 (c3475fd).

  • trial-params (0x08) frame: 0x0C (11 params, no duty) or 0x0D (12th byte = duty; 0 = stored duty ≡ omitting the byte).
  • Transmit-time semantics, trial-scoped lifecycle (re-declared per trial, none on 0x03, cleared on all-off), 0x88-reports-stored invariant.
  • Consistency ride-alongs: registry row, Mode-4 gain int16 prose, resolved review-notes row, 0x03 duty note.

Stacked on #65 (the canonical-relayout docs) — merge #65 first; this PR's diff then collapses to the duty delta.

🤖 Generated with Claude Code

Update the 0x08 payload table for the canonical re-layout (init_pos/gain
swap, gain widened to int16, new duration field) and delete the "Known,
intentional divergences" row for 0x08; the gain-width/runtime gap it
tracked as open is now closed.
@mbreiser mbreiser requested a review from floesche July 7, 2026 15:17
@floesche

floesche commented Jul 7, 2026

Copy link
Copy Markdown
Member

0x1D/0x1E change the fundamental model of talking to the arena: today every command is self-contained (stateless), the panel-protocol's 0x50-0x53 / 0x60-0x63 families already let the controller display a given pattern at an explicit, per-call brightness. Nothing the host sends depends on what it sent a minute ago. SET_DUTY_OVERRIDE breaks that: it introduces sticky, invisible state that lives on the controller between commands and silently reshapes every subsequent frame the controller ships, regardless of which command produced it.

That has real downstream cost, not just a style preference:

  • Every client now has to defend against stale state. A script (or a different experimenter's session, after a reconnect, a controller reset that didn't happen, or a crashed run) can leave the override on. The next unrelated command inherits it silently, with no local signal that anything is different, unless the client remembers to GET_DUTY_OVERRIDE before every run and reconcile.
  • It couples unrelated commands. stream-frame, display-psram-index, all-on, and SD playback all currently mean exactly what their bytes say. Once a global override exists, the meaning of those commands becomes conditional on prior state that isn't visible in the command itself, which is exactly the class of bug we've been designing the rest of the v1/v2 command set to avoid.
  • It duplicates a mechanism that already exists. 0x60-0x63 already do the thing SET_DUTY_OVERRIDE is trying to accomplish, an explicit, per-display duty_cycle, without adding any controller-side state: the brightness is part of the command itself, not a side effect of a prior one. If a host wants pattern X at brightness 64 and then brightness 255, it just issues two 0x6x calls; there's nothing to remember, nothing to query, nothing that can be left "on" by accident.

You can already produce the exact same outcome with the existing set of opcodes. There is no need to introduce a second layer of opcodes, and the state they carry, on top of a command set that already solves this problem statelessly.
Adding 0x1D/0x1E doesn't unlock new behavior, it just gives us two ways to do the same thing, one of which is harder to reason about and harder to keep in sync across clients.

So my suggestion: keep brightness control anchored on 0x60-0x63 (extending the PSRAM display path as needed) instead of adding a global sticky toggle at the host-command layer. If SD-mode playback (Modes 2/3/4) or streamed frames need variable per-call brightness too, that argues for extending the same stateless, explicit-argument pattern to those paths, not for bolting a global override on top of them.

@mbreiser

mbreiser commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

On hold pending the redesign agreed in reiserlab/LED-Display_G6_Firmware_Arena#34 (0x1D/0x1E withdrawn): I'll rework this PR to document the per-trial duty byte in trial_params (0x08) and the optional duty on 0x3A/0x3B instead of the new opcode pair, once the layout is confirmed there.

…D/0x1E

Documents the layout merged in Arena-Firmware PR #39 (c3475fd): optional
12th param byte on trial-params (0 = stored duty, 1-255 = per-trial
override; frame 0x0C or 0x0D), applied at transmit time with the pattern
file untouched. Scope/lifecycle: re-declared per trial, none on 0x03,
cleared on all-off. Stacked on the #65 canonical-relayout docs; the
withdrawn 0x1D/0x1E section from the previous revision of this PR is gone.

Ride-alongs: registry row 0x08 frame lengths; Mode-4 gain prose int8→int16;
review-notes row marked resolved; 0x03 note documents duty clearing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mbreiser mbreiser force-pushed the docs/duty-override-0x1d-0x1e branch from a44b31d to 485809b Compare July 8, 2026 05:00
@mbreiser mbreiser changed the title g6_03: document set/get-duty-override (0x1D/0x1E) g6_03: per-trial duty byte in trial-params (param[11]) — stacked on #65 Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants