Skip to content

soapy: fix SDRplay RSP1B gain (stream fails to start; gain runs backwards) - #331

Open
CharlesBaud wants to merge 1 commit into
flightaware:devfrom
CharlesBaud:sdrplay-gain-dev
Open

CharlesBaud wants to merge 1 commit into
flightaware:devfrom
CharlesBaud:sdrplay-gain-dev

Conversation

@CharlesBaud

@CharlesBaud CharlesBaud commented Oct 21, 2026 •

Copy link
Copy Markdown

PR checklist

  • I certify that this PR meets the requirements of the DCO
  • This PR has a base branch of dev (not master)
  • This PR does not contain generative AI output
  • Tools and affected parts. The change to sdr_soapy.c (the whole
    commit) was written with Claude Code (Anthropic, Claude Opus models) to my
    specification: the diagnosis, the IFGR/RFGR gain mapping, the sdrplay_models[]
    table and the commit message. I chose the approach (only the RSP1B enabled,
    the other models listed but commented out until someone can test them) and
    reviewed and tested every line. The commit carries a Co-Authored-By: Claude
    trailer.

  • DCO. I wrote the specification, reviewed the code, tested it on my
    own hardware and submit it under the project's licence. I have the right to
    submit it and certify the DCO for it as my contribution (Signed-off-by on the
    commit).

  • Reproduction (before this change). SDRplay RSP1B, SoapySDR with
    SoapySDRPlay3, SDRplay API 3.15, Raspberry Pi 5:

    1. dump1090 --device-type soapy --device driver=sdrplay
    2. With the default (maximum) gain, dump1090 asks for LNA state 9. The
      RSP1B has 9 L-band states (0..8), sdrplay_api_Init() fails and the
      stream doesn't start.
    3. With a lower --gain, it starts, but IFGR and RFGR are reductions, so the
      total gain runs backwards: a higher --gain gives less gain, and adaptive
      gain steps the wrong way.
  • Testing. After the change, on the same setup (15 s run, stock decoder):

    soapy: hardware key:    RSP1B
    soapy: total gain:      47.0dB; IFGR=20.0dB; RFGR=0.0dB
    soapy: sample rate:     2.4 MHz
    soapy: bandwidth:       5.0 MHz
                 0 samples dropped
          4303 total usable messages
    

    The noise floor rises with --gain, and adaptive gain steps upwards. The
    existing 5 MHz SDRplay bandwidth default was confirmed live: 5, 7 and 8 MHz
    decoded within 1% of each other and 6 MHz within noise; 1.536 MHz decoded
    about 40% as many messages. Builds with no warnings with every SDR driver
    enabled.

…ards)

SoapySDRPlay3 exposes IFGR (IF gain reduction, 20..59 dB) and RFGR (LNA
state, higher = more attenuation) as gain elements. Both are reductions,
so SoapySDR's generic total gain runs backwards: dump1090's default
(maximum) gain is the least gain, and adaptive gain steps the wrong way.
The module also reports RFGR 0..9 for the RSP1B, but at 1090 MHz (L-band)
it has 9 LNA states, 0..8; LNA state 9 makes sdrplay_api_Init() fail, so
dump1090 did not start with its default gain.

For the SDRplay models in sdrplay_models[] (only the RSP1B, the one
tested), dump1090 now maps its own total gain onto the two elements: the
gain below the maximum comes off IFGR first, then off the LNA, never above
the highest L-band LNA state. Default gain is now IFGR 20, RFGR 0. The
RSP1A, RSPduo and RSPdx are listed commented out, with their L-band LNA
state counts from the SDRplay API 3.15 headers. Other devices are
unchanged.

Tested on an RSP1B (Raspberry Pi 5, SDRplay API 3.15): the stream starts
with the default gain, the noise floor rises with --gain, and adaptive
gain steps upwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@CharlesBaud
CharlesBaud changed the base branch from master to dev October 21, 2026 19:16
@mutability

Copy link
Copy Markdown

I see you filled the generative AI part of the checklist in the PR summary but left it commented out, is that part completed / can be uncommented?

@mutability mutability added the LLM has LLM-generated content, treat with extreme suspicion label Oct 22, 2026
@CharlesBaud

Copy link
Copy Markdown
Author

Yes sorry

@mutability

Copy link
Copy Markdown

Hm, both of these seem to be bugs in the sdrplay driver; can we try to get them fixed in the driver, rather than baking lots of hardware-specific knowledge into dump1090? e.g. I would expect the same problem to appear in dump978, and we don't really want to fix it in N different places.

specifically I think it's reasonable for a soapysdr client to assume that:

  1. SoapySDRDevice_setGain() is monotonically non-decreasing, i.e. if you compare the actual hardware gain that results from calling setGain(x) and setGain(x+n) then the actual hardware gain g(x+n) >= g(x) for all x and all positive n

  2. it should be okay to pass any gain in the gain range returned by SoapySDRDevice_getGainRange() to SoapySDRDevice_setGain() without causing failures

  3. if the hardware cannot exactly support a gain value passed to SoapySDRDevice_setGain() then the driver should pick the nearest supportable gain setting instead

.. mostly because soapysdr is an abstraction layer and the client can't be expected to know the quirks of every device in detail.

Currently it sounds like the sdrplay driver does none of these. the bare minimum would be to support (1) (and by analogy, the per-element settings for attenuator stages should probably deal in terms of negative gain..)

@CharlesBaud

Copy link
Copy Markdown
Author

Yes its really whether you can get that change - trouble is will then break their compatibility and their documented API. So I think they will resist that. The only nasty bug in their driver it if you do send an illegal gain the driver does not work again. That's why it seemed better to go with the quirk method. The gain in their driver goes the wrong way both for RF and IF its attenuation so it positive feedback rather than negative. I leave this one I just bring to your attention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

LLM has LLM-generated content, treat with extreme suspicion

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants