feat(tci): add tx_gain command + ALC field in tx_sensors#2950
Conversation
Two TCI-layer additions that support automated TX-drive calibration tooling (sweeping drive against forward power and ALC). tx_gain (AetherSDR extension, 0-100): gets/sets TciServer's outbound TX gain (m_txGain), applied to WSJT-X/JTDX audio before the radio. GET reads the persisted TciTxGain value; SET stashes m_pendingTxGain and TciServer applies it via setTxGain() after handleCommand() returns — the same indirection cmdVolume uses, since TciProtocol cannot reach TciServer. tx_sensors: append a trailing alc_dbfs field (SW-ALC peak, sourced from MeterModel::swAlcChanged). Trailing position keeps it backward compatible — index-based parsers ignore the extra field. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Runtime verification — both hooks exercised on live RF (FlexRadio). A calibration harness drove these hooks directly: it steps
Test plan:
(Test build also carried the #2814 fix from #2946, so repeated |
There was a problem hiding this comment.
Nice, focused addition — thanks @nigelfenton. Pattern review is clean: cmdTxGain mirrors cmdVolume precisely (pending-int stash, AppSettings-backed GET, notification broadcast via m_pendingNotification), and m_pendingTxGain resets at the top of handleCommand like its sibling. The tx_sensors field is appended trailing as the PR description says, which is index-safe for existing parsers. Scope is tight — all four files are TCI core. Uses AppSettings, QStringLiteral, qBound, std::clamp consistent with the surrounding code.
One minor thing worth a look (not blocking):
m_cachedAlc{0.0f} initial value (TciServer.h:181)
ALC is dBFS, where 0.0 is clipping. If a TCI client polls tx_sensors in the very small window between isTransmitting() going true and the first swAlcChanged emission, the broadcast will report alc_dbfs=0.0 — i.e. apparent clip indication, not "unknown". That window should be tiny in practice (MeterModel updates fast during TX) and your harness presumably wouldn't have caught it, but for symmetry with m_cachedMicLevel{-50.0f} consider an obviously-not-real sentinel like -50.0f or lower. Trivial to change.
Other notes:
setTxGain()persists but doesn't itself broadcasttx_gain:N;to TCI clients — that's fine here because the SET path goes throughm_pendingNotification, which the existing loop atTciServer.cpp:577–580already broadcasts to other clients. Just flagging it in case a future non-TCI caller (UI etc.) callssetTxGain()directly and we want connected TCI clients to learn about it; that'd be a separate change.- The GET reads
TciTxGainfrom AppSettings rather than the in-memorym_txGain— same patterncmdVolumeuses (TciProtocol has no TciServer handle), andsetTxGain()saves synchronously, so they stay in lockstep. ✅
Verified the new connect(&meterModel(), &MeterModel::swAlcChanged, …) sits inside the existing if (m_model) block, so no null-deref risk. Looks good to me modulo the init value.
|
Claude here — merged. Thanks @nigelfenton, second careful TCI PR What stood out on review: The mirror of `cmdVolume`'s indirection pattern — protocol stashes The trailing-field policy for `tx_sensors` extension is the right And the use case is concrete and operationally useful — a Also appreciate the cleanness with respect to #2946 — no new One small follow-up worth knowing about: `m_cachedAlc` defaults to Ships in v26.5.3. 73, |
- New ### TX Cal subsection under Toolkit tabs, sibling to Inspect / Console / Compare / Replay. Covers what the panel does, the shipped safety model (arm/dry-run/watchdog/UNKEY/auto-DIGU), the self-identifying CSV header (build identity + AE identity + no-carrier WARNING), and the upstream AetherSDR PR requirement (aethersdr/AetherSDR#2950 for tx_gain + ALC). - Embedded a docs/tx-cal-curve.png screenshot captured against Mac AE / Flex 6300 (tx_gain=34, 30.7 W, ALC -10.3 dBFS) showing the smoothed twin-axis chart with the glow markers and the alongside "how to apply" guidance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… + @G6PWY-Chris (#3067) Two attribution errors in the v26.5.3 release CHANGELOG: 1. @M7HNF-Ian (Ian, separate GitHub account) → @nigelfenton (Nigel Fenton, G0JKN) — Nigel authored all 5 of the commits I bucketed under that line: TCI Network dialog tab (#2879), tx_gain + ALC (#2950), use-after-free fix (#2946), vfo emit on band-change (#2828), mic-capture suppress during TCI feed (#2982). 2. @chrisb1964 → @G6PWY-Chris (Chris G6PWY) — single commit author in the cycle was the latter; chrisb1964 is unrelated. Reported by Nigel directly. All other handles verified against gh api repos/.../commits/<sha>. GitHub release notes already updated; this lands the same fix in the in-repo CHANGELOG. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
) ## Summary Two small TCI-layer additions that give external tooling the hooks to characterise TX drive — sweeping drive against forward power and ALC. (Motivating use: finding the WSJT-X digital-mode drive sweet spot — maximum clean output with ALC held near zero.) ## Changes **`tx_gain` TCI command** — AetherSDR extension (not TCI v2.0 spec), range `0-100`. Gets/sets `TciServer`'s outbound TX gain (`m_txGain`), applied to WSJT-X/JTDX audio before the radio. GET reads the persisted `TciTxGain`; SET stashes a pending value that `TciServer` applies via `setTxGain()` after `handleCommand()` — the same indirection `cmdVolume` uses, since `TciProtocol` has no `TciServer` handle. Makes the TX-drive level scriptable. **`alc` field in `tx_sensors`** — appends a trailing `alc_dbfs` field (SW-ALC peak, from `MeterModel::swAlcChanged`) to the periodic `tx_sensors` broadcast. Trailing position is backward compatible — index-based parsers ignore the extra field. ## Verification - Builds clean (`647/647`) on Linux / Qt 6.4.2. - Binary launches and runs. - **Runtime-verified on live RF** (FlexRadio): a calibration harness exercised both hooks across a full TX-drive sweep — `tx_gain` SET/GET and the `tx_sensors` `alc` field. See the verification comment below for evidence. ## Test plan - [x] Compiles + links clean - [x] Binary launches - [x] `tx_gain;` GET / `tx_gain:N;` SET round-trip over a TCI client - [x] `alc` field seen in `tx_sensors` during TX Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… + @G6PWY-Chris (aethersdr#3067) Two attribution errors in the v26.5.3 release CHANGELOG: 1. @M7HNF-Ian (Ian, separate GitHub account) → @nigelfenton (Nigel Fenton, G0JKN) — Nigel authored all 5 of the commits I bucketed under that line: TCI Network dialog tab (aethersdr#2879), tx_gain + ALC (aethersdr#2950), use-after-free fix (aethersdr#2946), vfo emit on band-change (aethersdr#2828), mic-capture suppress during TCI feed (aethersdr#2982). 2. @chrisb1964 → @G6PWY-Chris (Chris G6PWY) — single commit author in the cycle was the latter; chrisb1964 is unrelated. Reported by Nigel directly. All other handles verified against gh api repos/.../commits/<sha>. GitHub release notes already updated; this lands the same fix in the in-repo CHANGELOG. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Two small TCI-layer additions that give external tooling the hooks to characterise TX drive — sweeping drive against forward power and ALC. (Motivating use: finding the WSJT-X digital-mode drive sweet spot — maximum clean output with ALC held near zero.)
Changes
tx_gainTCI command — AetherSDR extension (not TCI v2.0 spec), range0-100. Gets/setsTciServer's outbound TX gain (m_txGain), applied to WSJT-X/JTDX audio before the radio. GET reads the persistedTciTxGain; SET stashes a pending value thatTciServerapplies viasetTxGain()afterhandleCommand()— the same indirectioncmdVolumeuses, sinceTciProtocolhas noTciServerhandle. Makes the TX-drive level scriptable.alcfield intx_sensors— appends a trailingalc_dbfsfield (SW-ALC peak, fromMeterModel::swAlcChanged) to the periodictx_sensorsbroadcast. Trailing position is backward compatible — index-based parsers ignore the extra field.Verification
647/647) on Linux / Qt 6.4.2.tx_gainSET/GET and thetx_sensorsalcfield. See the verification comment below for evidence.Test plan
tx_gain;GET /tx_gain:N;SET round-trip over a TCI clientalcfield seen intx_sensorsduring TX