Skip to content

Arena Studio v0.4: session rig + ?rig= + rig io: power-on defaults (#135) · negative frame_rate (Mode-2 reverse)#137

Merged
mbreiser merged 10 commits into
mainfrom
claude/vigilant-tereshkova-7d2d75
Jul 3, 2026
Merged

Arena Studio v0.4: session rig + ?rig= + rig io: power-on defaults (#135) · negative frame_rate (Mode-2 reverse)#137
mbreiser merged 10 commits into
mainfrom
claude/vigilant-tereshkova-7d2d75

Conversation

@mbreiser

@mbreiser mbreiser commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Session rig (#135) — closes #135

  • One session/bench rig (Studio.currentRig) shared by Run/Edit/Console: a single locked 🔒 top-bar selector (the Console's own caption picker is removed; stream/ISP/paste/thumb geometry all read the shared value). Explicit selections (unlock-and-pick, or ?rig=) are never silently overridden by a protocol load — the amber ⚠ bench ≠ protocol chip surfaces disagreement instead.
  • ?rig=<key> per-setup bookmarks: decode validated against configs/rigs/index.json, encoded only for explicit selections (clean-URL rule), replace-not-push per the Represent website state in the URL for shareable sessions #107 rules. +28 codec checks.
  • Rig io: power-on defaults: tolerant parseRigIo + RIG_IO_ROLES in js/plugin-registry.js (suite N12io); Studio.applyRigIo() drives declared DO/AO defaults at connect (before the read-back GETs) and logs each value; Controller ▾ gains session-local role overrides with bench-pending roles greyed + tooltips.
  • I/O naming = the board silkscreen ("Digital IO 1/2 (5V)", "Analog Out (0-5V)"): rig io: ports are 1-based == silkscreen == 0xAA channel (the addendum's 0-based sketch is superseded; parseRigIo rejects port: 0 with a warning). All labels/logs/command options renamed.
  • CSHL rig YAMLs declare the course defaults: IO1 = out_debug_framescan, AO = programmable @ 5.0 V idle.

Negative frame_rate — Mode-2 reverse playback

Firmware reads trial-params frame_rate as int16 since ee74c33 (LED-Display_G6_Firmware_Arena#4). The web now encodes it signed (i16le, golden vectors −2→FE FF), the runner's stale rejection is gone, and the designer schema is −32768…32767 — max deliberately dropped from 65535, since larger unsigned values now alias to reverse rates on the signed firmware (encoder throws).

Verification

  • pixi run test fully green (708/708 v3 incl. new suites N12io + 34, 155/155 wire, 152/152 runner, 62/62 url-state).
  • Browser-verified on the nocache server (chip/lock/URL scenarios, io menu, labels).
  • Bench-signed 2026-07-03 on real hardware paired with firmware feat/dio-roles-ao-modes: connect log shows io_ext caps + MAC, AO 5 V idle on the meter, framescan envelope on the AD3, reverse playback, reboot-restores-defaults. Record: docs/development/135-bench-checklist.md.

Follow-ups (named, not in this PR): web apply-path for the bench-pending roles (applyRigIo → 0xAC, un-grey on the io_ext capability), trigger-input + AI calibration bench session, g6_03-controller.md spec sync.

🤖 Generated with Claude Code

mbreiser and others added 9 commits July 3, 2026 12:55
…le + ?rig= + rig io: defaults

Session-1 build of #135 (+ addendum):
- Studio.currentRig = THE session/bench rig, top-bar selector (locked, 🔒
  unlock), consumed by Console stream/ISP/paste/thumb geometry; the Console's
  own caption picker is gone. setSessionRig() enforces explicit-beats-derived:
  a protocol load follows rig: only when the user/URL hasn't picked one —
  disagreement shows the amber "bench ≠ protocol" chip, never a silent rewrite.
- ?rig=<key> codec (js/studio-url-state.js): decode validated against
  configs/rigs/index.json names; encodeApp gains rigKey, emitted only for
  explicit selections (clean-URL rule). +28 codec checks.
- Rig io: block (dio roles/defaults, ai, ao incl. 5 V idle): tolerant
  parseRigIo + RIG_IO_ROLES in js/plugin-registry.js (suite N12io, fixture
  io_rig.yaml); Studio.applyRigIo() pushes defaults at connect via 0xAA/0xA0
  (before the read-back GETs) and logs each value; Controller ▾ gains
  session-local role overrides with fw-gated roles greyed + tooltips.
  Documented io: template added to the three CSHL rig YAMLs (all off).
- Docs: proposal open-questions answered (course-pipeline decisions), parity
  ledger entry, CLAUDE.md session-rig rule, bench checklist
  (docs/development/135-bench-checklist.md — hardware gate before #135 closes).

Pairs with LED-Display_G6_Firmware_Arena feat/controller-info-mac-0xc2 (MAC
bytes in the 0xC2 reply; the Studio's connect-time decode was already live).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-needs review

Against the physical controller board (BNC silkscreen: "Digital IO 1 (5V)",
"Digital IO 2 (5V)", "Analog In 1/2 (±10V)", "Analog Out (0-5V)"):

- Rig io: dio `port` is now 1-BASED — one number everywhere: silkscreen ==
  YAML port == SET_DIGITAL_OUT 0xAA channel. parseRigIo rejects the old
  0-based sketch's `port: 0` with a warning naming the convention (N12io
  updated, +3 checks); shipped rig YAMLs + fixture renumbered. Schema was
  authored earlier today and never pushed — no compat burden.
- All web-facing DIO/AO labels renamed to the silkscreen vocabulary: Console
  hardware-I/O row + channel picker, Controller ▾ Rig I/O rows (ids →
  cIoRoleDio1/2), applyRigIo log lines ("Digital IO 1←HIGH · Analog Out←5 V"),
  setDigitalOut/setAnalogOut command labels in js/plugin-registry.js,
  wire/runner comments. CLAUDE.md records the naming rule.
- NEW docs/development/135-io-firmware-needs.md — exact firmware changes per
  fw-gated role, grounded in the code: DIO role state machine + explicit
  0xAA refusal (SET_DIO_ROLE 0xAC / GET_DIO_ROLE 0xAD sketch), including the
  discovered Digital IO 2 boot contention (cmdProc.begin() runs before
  setupExternalTriggerInput(), leaving D35 driving the EINT net) and the
  0xAA-ch2 silently-kills-the-trigger-route hazard; framescan toggle; AO
  frame_number mode (0xA3) with MCP4725 I2C rate caveat; AI validation +
  GET_ANALOG_IN (0xA4); capability-bit detection so fwGated can go dynamic.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Firmware main reads trial-params frame_rate as int16 since ee74c33
(2026-06-25, LED-Display_G6_Firmware_Arena#4): negative = G4-style reverse
in Mode 2, sign ignored in Modes 3/4. The web tools still blocked it in
three layers — all shared modules, so this flows to the standalones too:

- js/arena-wire-g6.js: new i16le() (two's-complement LE, pinned by golden
  vectors: -2→FE FF, -30→E2 FF, boundaries ±32767/-32768); encodeTrialParams
  rate switches u16le→i16le. 32768..65535 now THROW — on signed firmware
  they'd silently alias to reverse rates (they were legal as u16).
- js/arena-runner-g6.js: drop the buildTrialParams negative-rate rejection
  ("not supported over the wire yet" — stale since June 25); sign passes
  through, encoder enforces the int16 range.
- js/plugin-registry.js: trialParams frame_rate schema -32768..32767 (max
  DOWN from 65535 per the aliasing hazard), label "Frame rate (Hz, − =
  reverse)" — designer clamp-to-legal now accepts negatives everywhere.
- arena_studio.html: Console rate input gains min/max + tooltip (incl. the
  old-firmware caveat: pre-ee74c33 builds read a huge forward rate).
- Tests: wire +8 (golden vectors + alias rejections), runner reverse
  pass-through, v3 Suite 34 (parse→regen→parse keeps -30; schema + clamp).
  708/708 v3, 154/154 wire, 152/152 runner.
- Bench checklist C2: reverse-playback verification steps (never
  bench-verified on either side).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ecklist

Companion to firmware feat/dio-roles-ao-modes (81d427d):
- js/arena-wire-g6.js: capability bit 5 = io_ext in CAPABILITY_BITS, so the
  connect log / Get info shows it (+decode test, bitmap 0x23).
- Controller ▾ greyed role options: "needs fw" → "bench-pending" with
  tooltips naming the shipped fw support (0xAC/0xA3) and the remaining gates
  (bench validation, web apply-path).
- Bench checklist §E: raw-hex recipes for the new opcodes (boot-contention
  fix, 0xAA refusal + auto-promote, framescan SPI envelope, AO frame_number
  sawtooth, GET_ANALOG_IN vs meter).
- 135-io-firmware-needs.md: status header — 0-3 + 0xA4/capability implemented
  with the user's decisions; remaining = bench, AI calibration, web apply-path,
  g6_03 spec sync.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Per bench decisions (2026-07-03): all three CSHL rigs declare
"Digital IO 1 (5V)" as out_debug_framescan (SPI frame-transmission scope
envelope — useful default, no experimental plans for these BNCs) and
"Analog Out (0-5V)" as programmable with a 5.0 V connect idle. Digital IO 2
stays off in the YAML — firmware boots it as the EINT trigger route; declare
in_trigger when a trigger source is actually cabled. applyRigIo warn lines
updated from "firmware-gated" to the real state (fw io_ext shipped,
bench-pending, web apply-path after validation).

Net connect-time behavior today: AO driven to 5 V (0xA0 path, live);
framescan role visible in Controller ▾ but not applied until the 0xAC web
wire-up lands post-bench.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ity-gated UI

Completes the #135 rig-I/O arc now that the firmware side is bench-verified:
- js/arena-wire-g6.js: encodeSetDioRole (name or code) / encodeGetDioRole /
  decodeDioRole (role-name vocabulary shared with rig io:) / encodeSetAoMode /
  encodeGetAnalogIn / decodeAnalogIn (signed int16 pair) + DIO_ROLE_CODES/
  NAMES exports; io_ext golden vectors + decode tests (172/172).
- applyRigIo: on io_ext controllers, SET_DIO_ROLE precedes the output default
  for every DECLARED role (rig `off` = don't touch — preserves the firmware's
  boot in_trigger on Digital IO 2); AO frame_number via 0xA3; a stale
  frame_number mode is cleared before programmable defaults. Pre-io_ext
  firmware keeps the old 0xAA-only path with a lacks-io_ext warn.
- Controller ▾ role options un-grey DYNAMICALLY when the connected controller
  advertises io_ext (Studio.capabilities stored at connect) — no firmware
  version guessing; AI 'in' stays locked until Mode-4 calibration.
- Console hardware I/O gains an Analog In readout (0xA4, guarded — unknown
  opcodes raise a CE glyph on old fw) and the Rig I/O menu a "Read roles"
  item (0xAD: roles + live pin levels).

Net effect at the bench: connecting with the CSHL rig YAMLs now applies
"Digital IO 1→out_debug_framescan · Analog Out←5 V" automatically — the
scope envelope appears with no raw hex.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mbreiser mbreiser merged commit 33c6fc8 into main Jul 3, 2026
3 checks passed
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.

Arena Studio: one rig/arena selection shared across Run/Edit/Console (locked by default)

1 participant