Skip to content

Start both RSPduo tuners at the less sensitive gain reduction - #74

Merged
Purple10101 merged 1 commit into
mainfrom
20260929-rspduo-safe-cold-start
Sep 29, 2026
Merged

Purple10101 merged 1 commit into
mainfrom
20260929-rspduo-safe-cold-start

Conversation

@Purple10101

Copy link
Copy Markdown

Summary

On a cold start, sdrplay_api_Init() begins streaming with rxChannelB overwritten by rxChannelA's values. process() already puts B's own value back with an Update afterwards, but until that lands, tuner B runs at tuner A's gain reduction.

That is harmless when A is the less sensitive tuner. When A is the more sensitive one, B briefly runs hotter than configured. With a tuning like A=20 / B=59, it is about 39 dB hotter, at a gain a calibration run may just have proved overloads it. A hard enough overload there takes the SDRplay service to ServiceNotResponding, and the radio stays down (NumDevs=0) until the service is restarted.

Live retunes never do this, because they change each tuner separately while streaming. So a node can run a tuning cleanly during Auto-Calibrate, then fail to come back up on the same tuning after the restart that persists it. That is the failure reported in ClickUp 123zgec4dua:

  • The customer's config was 20/59/LNA 3. The radio was already dead when Auto-Calibrate started.
  • The run recovered it, reached 20/59/3 by live retune and confirmed a track.
  • Persist then restarted the stack from config at 20/59/3, and the radio died again.

Change

Before Init, both tuners are staged at max(gain_a, gain_b). The post-Init Updates that already exist then move each tuner to its configured value. During startup, neither tuner is ever more sensitive than configured. A starts a little quieter until its Update lands, which is harmless. LNA state is shared by both tuners, so the copy cannot make it worse.

One file, +19/-3, no behaviour change for configs where A is already the less sensitive tuner.

Evidence

  • The Init copy is real. It was measured on owl on 2026-08-03 (every rxChannelB field reads back as A's value after Init), and the comment in process() documents it. It was seen again today on jonathan-node-1: a cold start of v0.6.1 configured at 20/59/LNA 3 logged Gain change, tuner=sdrplay_api_Tuner_B gRdB=20.
  • A hard startup overload wedges the service. In that same jonathan-node-1 run, tuner A overloaded 250 ms after Init, and 5 s later Failed to update Tuner A gain: sdrplay_api_ServiceNotResponding exited blah2. The radio stayed at NumDevs=0 until the cron watchdog restarted sdrplay.service.

That test did not exercise this fix. On jonathan-node-1 the overload was tuner A at its own configured value, which this change does not touch. That node's reference antenna hears the tower more strongly than its surveillance antenna (its proven tuning is A=45 / B=28), so the copy can only ever make B quieter there. The failure depends on the site: it needs a node where surveillance hears the tower more strongly than reference. The customer's 20/59 split is exactly that arrangement, which may also mean their antennas are swapped.

Verification

  • Built natively on jonathan-node-1 (arm64) from this branch against CI's registry cache. All 10 unit test binaries passed in the build stage.
  • Not live-tested on hardware (see above). The change was shipped on the reasoning, by agreement.

Test plan

  • CI build passes
  • On a node with a normal tuning (A less sensitive than B), a cold start logs both tuners starting at the higher reduction, then B moving to its configured value, and streams normally
  • If the customer's node can be reached: a cold start at 20/59/3 comes up without ServiceNotResponding

🤖 Generated with Claude Code

sdrplay_api_Init() starts streaming with rxChannelB overwritten by
rxChannelA's values, and process() only puts B's own value back with an
Update afterwards. Staging each tuner at its configured gain before Init
therefore starts surveillance at the reference tuner's gain reduction. With
the reference set more sensitive than surveillance (A=20 / B=59), B starts
~39 dB hotter than configured, at a gain a calibration run may just have
proved overloads it. That can take the SDRplay service down on a cold
start, while the same tuning applied by live retune (which changes each
tuner separately) runs cleanly (ClickUp 123zgec4dua).

Both tuners now start at max(gain_a, gain_b), and the existing post-Init
Updates move each one to its configured value, so neither tuner is ever
more sensitive than configured during startup.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Purple10101
Purple10101 merged commit db8aa52 into main Sep 29, 2026
1 check passed
@Purple10101
Purple10101 deleted the 20260929-rspduo-safe-cold-start branch September 29, 2026 13:50
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