Skip to content

[feature] AetherSweep SWR analyzer#2202

Merged
ten9876 merged 1 commit intoten9876:mainfrom
jensenpat:aether/swr-sweep
Apr 30, 2026
Merged

[feature] AetherSweep SWR analyzer#2202
ten9876 merged 1 commit intoten9876:mainfrom
jensenpat:aether/swr-sweep

Conversation

@jensenpat
Copy link
Copy Markdown
Collaborator

@jensenpat jensenpat commented Apr 30, 2026

Screenshot 2026-04-30 at 7 21 05 AM

Summary

This adds an in-panadapter SWR sweep that can step through the current TX band, plot measured SWR directly on the spectrum surface, and clear the plot from the ANT slice controls.

The sweep is designed as a fast diagnostic view rather than a tuner command. It uses the existing radio tune carrier path, samples fresh meter data at each step, and draws the resulting curve low enough to stay below the slice flag so the user can compare the SWR curve against the active frequency line.

UX

  • Adds Start Sweep and Clear Sweep buttons under the ANT slice menu, below the WNB slider.
  • Draws the SWR curve on top of the panadapter surface, with the current sweep frequency shown as the sweep advances.
  • Shows the latest value as SWR n.nn:1 and includes periodic value callouts along the plotted curve.
  • Labels the plotted source, including TGXL BYPASS when the sweep is measuring antenna-side TGXL bypass data.
  • Blocks normal frequency/input interaction while a sweep is running and lets Escape stop the sweep.

Safety

  • Requires a connected radio, a visible/unlocked TX slice, split disabled, and a non-zero Tune Power before starting.
  • Refuses 60 m because it is channelized.
  • Computes sweep points inside the current amateur band with an edge guard so the tune carrier is not commanded onto the band edge.
  • Uses the normal transmit tune 1 / transmit tune 0 carrier path and relies on the radio interlock for final enforcement.
  • Requires fresh SWR and forward-power meter samples for every step, preventing stale values from a previous band/sweep from being plotted.
  • Stops the tune carrier before restoring frequency/pan state or restoring an external TGXL state.
  • Aborts if the target slice disappears, TGXL leaves bypass during a TGXL sweep, or fresh meter data/forward power does not arrive within the settle window.

TGXL behavior

When a TGXL is present and already in OPERATE, the sweep now measures raw antenna performance instead of the tuned result:

  1. Snapshot the original TGXL bypass state.
  2. If needed, request TGXL BYPASS.
  3. Wait for the TGXL state model to confirm bypass.
  4. Wait a short relay-settle interval before applying RF.
  5. Start the radio tune carrier and sweep the band.
  6. Sample TGXL-specific forward power and SWR meters, not radio-side SWR.
  7. Stop the tune carrier.
  8. Restore the original TGXL bypass state and wait for confirmation.

The sweep does not automatically switch a TGXL from standby into operate. If the TGXL is present but not operating, the sweep falls back to the radio SWR source and labels the plot accordingly.

Validation

  • git diff --check
  • cmake --build build -j10
  • ./build/meter_model_test

meter_model_test still reports the existing compression-meter failures unrelated to this SWR/TGXL change; the build itself succeeds.

👨🏼‍💻 Generated with OpenAI Codex (GPT-5.5 Pro 4/23) and tested by @jensenpat

@jensenpat jensenpat changed the title Add TGXL-safe SWR sweep overlay [feature] AetherSweep SWR analyzer Apr 30, 2026
@jensenpat jensenpat marked this pull request as ready for review April 30, 2026 15:14
@jensenpat jensenpat requested a review from ten9876 as a code owner April 30, 2026 15:14
Copy link
Copy Markdown
Contributor

@aethersdr-agent aethersdr-agent Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this contribution, @jensenpat — really well-thought-out feature. The safety preconditions are thorough, the TGXL bypass/restore state machine is carefully sequenced, and the overall design of stopping tune before restoring state is exactly right for this kind of RF-driving workflow. A few observations:

Looks good

  • Safety checks: The precondition gauntlet in startSwrSweep() covers all the right cases — connected radio, no split, TX slice visible/unlocked, no active transmit, non-zero tune power, 60m exclusion, band edge guards. Solid.
  • State machine: The phased approach (WaitingForTgxlBypassTgxlBypassSettleSweepingStoppingTuneRestoringTgxl) with timeouts at each stage is clean. The "stop tune carrier before restoring frequency/TGXL state" ordering is correct.
  • Meter freshness: Requiring both SWR and forward power timestamps to be ≥ sampleNotBeforeMs prevents stale readings. The fwdPowerInstant addition to MeterModel (un-smoothed watts) is the right call for per-step validation — the smoothed fwdPower() would lag.
  • MeterModel changes: The new timestamp accessors and fwdPowerInstant are well-placed. Using the existing packetUpdatedMs for the new timestamps is consistent with the compression meter pattern already in place. The clear() / removeMeter() / setTgxlHandle() updates correctly reset the new fields.

Items worth a second look

  1. AppletPanel.cpp include removal — Removing <QMenu> and <QContextMenuEvent> is unrelated to SWR sweep and could break if another open PR adds a context menu to AppletPanel. I'd suggest dropping this hunk or splitting it into its own commit to keep the PR scope clean.

  2. advanceSwrSweep()tunerModel() returns a non-const ref via const pollingadvanceSwrSweep() grabs auto& tuner = m_radioModel.tunerModel() to check isPresent() / isOperate() / isBypass(). This works because tunerModel() returns a non-const ref, but since the sweep code only reads tuner state here (the one setBypass() call is elsewhere), consider using const auto& to signal read-only intent. Minor.

  3. finishSwrSweep() re-entrancyfinishSwrSweep(true, ...) is called from many places (Escape key, disconnect, slice disappear, meter timeout, TGXL state change). The early returns for StoppingTune/RestoringTgxl phases are correct. However, completeSwrSweepFinish() accesses m_panStack->allApplets() in the clearPlot path — if the radio disconnects while in RestoringTgxl phase and onConnectionStateChanged(false) fires again, the !m_swrSweep.running guard at the top protects against this, which is good. Just noting this was verified.

  4. Pan restore on abort only — After a successful (non-aborted) sweep, the panadapter stays zoomed to the full band. This seems intentional per the UX description (the user wants to compare SWR against the active frequency). Worth confirming this is the desired behavior, since on abort the original pan center/bandwidth is restored but on success it isn't.

  5. drawSwrSweep() — minor edge case — If m_swrSweepRunning is true but m_swrSweepPoints is empty (the sweep just started, no samples yet), the function still enters and draws the label/background. This is fine — the label shows "SWR Sweep RUN" — but the plotRect background rectangle gets drawn with no curve data. This is a cosmetic choice, not a bug, but you might want the "RUN" indicator to wait until the first sample arrives.

Overall this is clean, well-guarded code. The feature is well-scoped and the abort paths are thorough. Nice work.

🤖 Reviewed by AetherClaude

@ten9876 ten9876 merged commit bc47c3b into ten9876:main Apr 30, 2026
5 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.

2 participants