Skip to content

Serial channel mode commands never applied the selected mode - #2

Open
xmutantson wants to merge 1 commit into
ARSFI:masterfrom
xmutantson:fix/serial-mode-dispatch-upstream
Open

xmutantson wants to merge 1 commit into
ARSFI:masterfrom
xmutantson:fix/serial-mode-dispatch-upstream

Conversation

@xmutantson

Copy link
Copy Markdown

The defect

Selecting a channel profile over the USB serial port (WGN:, MPG:, MPM:, MPP:,
MPD:) answers OK but does not change the running channel profile. Only the target
S:N number is updated; the simulator keeps whichever profile the front-panel encoder
last selected (or WGN after power-on).

Cause: ParseSetSimParameter(String strParameter, int intMode) takes a parameter named
intMode, which shadows the global intMode. For modes 0-4 it validates the request
and sets intTargetSN, but the global mode index is never assigned. The follow-up call
ParseSetParameter(strParameter, intSerialCmdMode) has the same parameter shadowing,
so it updates the display text and S:N only. The main loop configures the IQ tap delays
and the Doppler update cadence from the unchanged global intMode, so the physical
signal path never switches. Both firmware variants (src/HFSim_BFD_2_03 and
hardware/Alternate hardware platforms/.../HFSim_BFD_2_03_Proto) have the same
dispatch code and the same defect.

How it was found

Driving the simulator from a Raspberry Pi over USB serial for automated modem testing:

  • After a commanded WGN:40, the received tone showed slow amplitude fading and
    measured about 18.5 dB SNR in a setup that had previously measured about 43 dB on a
    genuinely clean WGN channel — the profile was still a multipath/fading mode from
    earlier front-panel use.
  • After commanded MPP:9, independent SNR estimators disagreed by ~12 dB because the
    channel was not actually in the commanded profile.
  • The TFT display showed the commanded mode name while the output audibly kept the old
    profile, which is what pointed at the dispatch rather than the signal path.

The fix

In the successful serial dispatch, assign the global mode and clear blnInitialized
before applying the parameter update:

if (intSerialCmdMode < 5)
  {
    intMode = intSerialCmdMode;
    blnInitialized = false;
    ParseSetParameter(strParameter, intSerialCmdMode);
  }

Clearing blnInitialized makes the next loop() pass run the exact mode-entry
initialization a front-panel mode change runs (tap delays, path mixer gains, display),
and the Doppler update cadence follows the global intMode from then on. The target
S:N set by the command is preserved. Front-panel behavior, EEPROM handling, and the
BUSY-mode command path are untouched. Applied identically to both firmware variants.

tests/test_serial_mode_dispatch.py (plain python -m unittest tests.test_serial_mode_dispatch) guards the dispatch block of both sources: it fails
on the previous code and passes with the fix.

Validation on hardware

Flashed the fixed firmware to the Teensy 4.0 unit on the same Raspberry Pi bench and
re-ran the failing sequence:

  • Commanded WGN:40: measured 43.9 dB SNR with a flat envelope (std 0.003 dB, Doppler-band
    energy fraction 0.0005) — the clean channel is actually delivered. Before the fix the same
    command measured 18.5 dB with visible slow fading.
  • Commanded MPP:9: fading now genuinely present — envelope std 5.3 dB, p95-p05 spread
    17.5 dB, Doppler-band energy fraction 0.79, and the serial debug echo
    Line 1014 SetIQTapDelays: intMode = 3 confirms the global mode assignment on dispatch.
  • Commanded WGN:40 again: 44.2 dB, flat — live re-switching works in both directions
    without a power cycle.
  • The two independent SNR estimators that disagreed by ~38 dB on a commanded-clean channel
    before the fix now agree within 0.13 dB on it.
  • Power-cycle behavior unchanged: after RESET the unit boots to WGN as before (modes are
    deliberately not persisted), with the same banner and serial number.

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.
@xmutantson
xmutantson force-pushed the fix/serial-mode-dispatch-upstream branch from 4a7b87f to 037458f Compare September 13, 2026 20:08
xmutantson added a commit to xmutantson/HFSimulator that referenced this pull request Sep 13, 2026
…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).
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