Skip to content

Make USB control DSP-authoritative and attest firmware builds - #5

Open
xmutantson wants to merge 15 commits into
ARSFI:masterfrom
xmutantson:owner-correctness
Open

xmutantson wants to merge 15 commits into
ARSFI:masterfrom
xmutantson:owner-correctness

Conversation

@xmutantson

@xmutantson xmutantson commented Sep 21, 2026

Copy link
Copy Markdown

Why

The USB serial side had never been seriously exercised by scripted control. Based on correspondence with the Winlink team, this is the first systematic scripted use of that interface.

That exposed three correctness failures in released behavior:

  • serial profile commands changed S:N and redrew the panel but did not select the DSP profile;
  • a convincing panel redraw could therefore show a mode that had never been applied;
  • acknowledgments were emitted before the DSP transition completed.

This is test equipment. If the commanded channel and the live channel can differ, every downstream measurement can be mislabeled. The interface must report what the DSP is actually running, not what the parser or display intended.

This consolidated change supersedes PRs #2, #3, and #4. It incorporates their useful work, corrects the ancillary-command regression in #4, and adds the missing trust and build-attestation pieces.

Changes

Tier 0 — make scripted profile selection work

  • Apply WGN, MPG, MPM, MPP, and MPD to the live channel mode.
  • Restrict live profile replacement to selectors 0–4.
  • Let FADE DEPTH, FADE FREQ, OFFSET, input/output gains, and BANDWIDTH update their parameters without replacing the live profile.
  • Preserve boot-to-WGN behavior and do not persist channel mode to EEPROM.

The established nine-command profile-first program now ends with live MPP and mode-3 tap initialization:

MPP:25
FADE DEPTH:0
FADE FREQ:0
OFFSET:0
CH1 IN:1
CH2 IN:1
CH1 OUT:1
CH2 OUT:1
BANDWIDTH:3000

Tier 1 — make state authoritative

  • Route panel and serial profile changes through synchronous ApplyChannelMode().
  • Complete tap/routing initialization before returning OK or the structured ACK.
  • Add an applied-generation counter to ACK and STATUS output.
  • Make the SIM-to-BUSY command reachable and apply BUSY state before acknowledgment.
  • Reject fractional syntax for integer-valued commands before mutation, eliminating contradictory OK/ERROR replies.
  • Make STATUS report the live DSP-driving mode, S:N, multipaths, fade depth/rate, offset, four gain settings, bandwidth, measured input/output levels, applied generation, and build identity.
  • Keep LEVEL as the STATUS level subset and HELP as the complete command reference.
  • Print the same build identity on the physical boot screen, serial boot banner, and STATUS.

Tier 2 — retain maintenance behavior

  • Restore RESET with transmit flush before reset.
  • Restore CODECINIT, completing codec reinitialization before its response.

Tier 3 — display and repository cleanup

Validation` section with:

Validation

  • Eight source-level regression tests pass against both production and Proto sketches where applicable.
  • Coverage includes the Rev 2.04 sketch naming and live revision surfaces, exact nine-command sequence, mode-3 initialization, ancillary profile preservation, apply-before-ACK ordering, STATUS variable provenance, integer syntax rejection, BUSY reachability, RESET/CODECINIT behavior, and duplicate-header cleanup.
  • The production sketch is now HFSim_BFD_2_04; its TFT display, serial boot banner, HELP banner, and STATUS revision field report Rev 2.04. The Proto sketch follows the same revision convention.
  • Teensy 4.0 builds use Arduino CLI 1.5.1, Teensy core 1.62.0, teensy-compile 15.2.1, and explicit teensy:avr:teensy40:usb=serial,speed=600,opt=o2std,keys=en-us settings.
  • Two fresh builds with the same recorded identity produced byte-identical Intel HEX output.

Build identity: c0ce0af@20260921T025520Z

HEX SHA-256: 095055164f3646f1dbb9a36d189c4dc799caa3a811cf0e9ac4b766fd8c932b9b

Hardware validation: this exact Rev 2.04 HEX was flashed to the Teensy 4.0 HF simulator and re-verified over serial and on the audio wire. The boot banner and STATUS report Rev 2.04 and c0ce0af@20260921T025520Z; the exact nine-command program ends with live MPP and mode-3 tap initialization at generation 11. A matched 60-second steady-tone discriminator measured MPP envelope std 4.7154 dB, a 25.8050 dB min–max span, and 40 downward −3 dB crossings over the common 53-second analysis interval, while WGN measured 0.2734 dB std, a 1.4649 dB span, and zero crossings. RESET re-enumerated cleanly, and the device was restored to neutral WGN defaults before the Butler lock was released.

When the mode screen initializes with a mode other than WGN selected, the
WGN branch also runs because its condition treats any uninitialized state
as WGN. Both branches then print the mode and S:N lines, and since there
is no screen clear or cursor reset between them the second copy lands two
text rows lower, leaving a duplicated header on the panel until the next
full redraw.

Select the WGN branch on the mode alone. Initialization of a non-WGN mode
falls through to its own branch and the header is drawn exactly once; WGN
behavior is unchanged.
Apply the parsed channel mode to the live DSP for every serial SIM
parameter-page command (not only WGN-MPD): assign intMode and force
reinitialization. Bound BUSY CH1 IN to the nine-element fltLogs table;
apply MULTIPATHS, OFFSET and FM-deviation routing immediately; restore
fade rate, FM rate and FM amplitude from EEPROM into the DSP at boot;
reject empty and non-numeric parameters before the setters coerce them
to zero; correct the FM-rate display multiplier (10 * fltLogs). Updates
the regression tests for both sketches.
…L/HELP)

Echo the live DSP state after each command, ending in OK or ERROR, as the
single source of truth. Add a one-way DSP-to-display watchdog with change
detection and a 30-second repaint. Add STATUS (mode and S:N), LEVEL (input
level in mVp-p) and HELP (command and range listing ending END HELP).
Legacy OK and ? replies preserved. With the watchdog now owning the
display, remove the redundant ParseSetParameter parser. Based on the
PR ARSFI#2 branch (apply after PR ARSFI#2).
The AdjustS_N calibration debug block printed on every change of the
requested S:N. Under a running flat fade the fade state machine steps the
integer S:N tens of times per second, so the block was emitted from inside
the audio envelope loop at roughly 40 Hz. That floods the serial link,
desyncs the host command protocol, and risks the processor blocking on the
serial chip inside the very loop that is shaping the fade envelope.

Classify the debug output by source rather than by a bare value change:
  - the fade loop's internal per-step adjustment (Fade -> AdjustS_N) is
    silent;
  - operator-initiated changes (boot/initial apply, front-panel dial, and
    the USB/serial S:N command) still print exactly one block on change.

An opt-in DEBUG ON|OFF verb restores the legacy per-step calibration trace
for bench calibration and STATUS reports its state; it defaults off. No DSP
math changes. Bump the consolidated firmware and sketch name to Rev 2.05.

Add a source-pattern test asserting the fade path is silent by default while
the operator paths keep their single calibration block.
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.

1 participant