aethersdr / aethersdr/AetherSDR

HL2: the automatic RF gain arms by default and then refuses to arm — the constructed baseline is 1 dB above the ceiling that gates it

Open
#5,817 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug GUI maintainer-review
Dominant language
C++
Stars
221
Forks
117
Avg merge
2d 9h
Merged PRs (30d)
302

Description

Hl2Backend arms the automatic RF gain by default and then declines to arm it, because the constructed LNA baseline is one decibel above the ceiling that gates arming.

Measured on merged main 020d31fb, socket-free — no radio, no network, nothing keyed.

The failure

fresh backend: kLnaDefaultGainDb=20, ceiling=19
[FAIL] auto RF gain ARMS from a freshly constructed backend
       (no stored per-band gain, i.e. a first connect)

Construct hl2::Hl2Backend, call setAutoRfGain(true), read back autoRfGainEnabled(). It is false.

Why

Three facts, each read from main rather than inferred:

value on 020d31fb
m_lnaGainDb is seeded with hl2::kLnaDefaultGainDb (Hl2BandMemoryPolicy.h) 20
Hl2Backend::kAutoRfGainMaxBaselineDb (Hl2Backend.h) 19
Hl2Backend::setAutoRfGain refuses when the baseline exceeds that ceiling strict >

20 exceeds 19, so the arming path takes its refusal branch, logs the qWarning and returns. #5652 arms the control by default, so on a first connect the shipped state is a control that reads as on and does not engage.

The refusal is logged, so it is not silent in a terminal. It is silent to an operator.

Who sees it

Anyone whose stored per-band gain for the current band is above 19 dB, which includes anyone with no stored gain at all — a fresh install, a new band, a cleared profile. An operator whose stored gains are all at or below 19 never sees it, which is why this did not surface on our bench: ours are −12 and below.

The code comment says the opposite

Hl2Backend.cpp, in the paragraph justifying the default flip:

"With the ceiling at +19 and the default at 0 dB, arming from a fresh connect works and starts from a baseline that means what it says."

The default is not 0 dB. It is 20 — on main now, and as @ten9876 stated on #5753, "the +20 dB default stands". That sentence is ours and it is wrong; we are reporting it rather than waiting to be asked about it.

Provenance, because it is the fourth of these today

kAutoRfGainMaxBaselineDb = 19 is sized on the & 0x1F gain fold, and its own refusal message cites it — "#5354: +48 dB measures like +18 dB".

#5752 merged declining that premise: the native range −12…+48 stands, and the merged decision records that the single-unit observation "remains unresolved against the native bit-6-selected RTL path".

The same premise produced three other errors that landed or nearly landed today: a docs/HERMES.md row claiming kLnaGainMaxDb is +19 when it is +48 (corrected by @ten9876 in #5753), a paragraph in #5652's body asserting the fold as settled (corrected on that PR), and this ceiling. We are not re-litigating the fold here — only noting that a constant derived from it now gates a default-on control.

Reproduction

A case added to tests/hl2_gain_split_test.cpp, which already constructs Hl2Backend directly and links aethercore:

hl2::Hl2Backend fresh;
fresh.setAutoRfGain(true);
check(fresh.autoRfGainEnabled(),
      "auto RF gain ARMS from a freshly constructed backend");

Both constants are public, so the case prints them alongside the result and carries its own evidence. Happy to open it as a PR if a guard there is wanted.

We are not proposing the fix

Three candidates — raise kAutoRfGainMaxBaselineDb, lower kLnaDefaultGainDb, or lower the baseline on the connect path before arming — and each interacts with the unsettled fold question in a different way. Choosing one would be deciding that question by the back door, which is precisely what #5752 declined to do. That call is yours.

What this does not establish

  • Whether a real connect always leaves the baseline at 20. The test constructs the backend directly. A connect that restores a stored gain of 19 or below arms normally; this measures the no-stored-gain path, which is the default one.
  • Any on-air consequence. Nothing was keyed, no radio was involved, and the control failing to arm is a missing protection rather than an active fault.
  • Whether the ceiling is the right number. Untouched here on purpose.

🤖 Generated with Claude Code

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with Hl2Backend.h, Hl2Backend.cpp, and Hl2BandMemoryPolicy.h to verify the baseline, ceiling, and arming path described in the issue. Run the added case in tests/hl2_gain_split_test.cpp and review #5752, #5652, and #5753 for the unresolved gain-fold context. Done requires an agreed fix and a passing regression test for fresh-backend arming.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.