Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SoapySDR::Device::setGain has undesired behavior for SDRPlay #60

Open
dlaw opened this issue Nov 3, 2019 · 2 comments
Open

SoapySDR::Device::setGain has undesired behavior for SDRPlay #60

dlaw opened this issue Nov 3, 2019 · 2 comments

Comments

@dlaw
Copy link

dlaw commented Nov 3, 2019

SoapySDR assumes that gains are additive in dB. When Device::setGain is called without a name, it automatically distributes the requested gain between all available gain stages:
https://github.com/pothosware/SoapySDR/blob/master/lib/Device.cpp#L281

Unfortunately, SDRPlay gains are unconventional. There are two gains exposed via SoapySDR, called "RFGR" and "IFGR".

  1. "IFGR" stands for "intermediate frequency gain reduction". It takes a value between 20 and 59. Contrary to what SoapySDR expects, the greatest amplification is obtained with the smallest numerical value. The IFGR has units of dB.
  2. "RFGR" stands for "radio frequency gain reduction". It takes a value between 0 and 9. As with the IFGR, the greatest amplification is obtained with the smallest value. In addition, the RFGR does not have units of dB! The actual gain reduction is nonlinear and frequency-dependent, but tends to be about 7 dB per count.
    (a) Note that RFGR is also settable via the "rxgain_sel" menu item.
    (b) RFGR attenuation tables in dB are available in the SDRPlay API documentation, section 5.3.
    (c) Most SDRPlay technical documents refer to the RFGR as the LNA state. I am not sure which terminology is preferred.

When we put these unconventional gain definitions together with SoapySDR's default gain distribution algorithm, disaster follows. Nearly any call to
void SoapySDR::Device::setGain(const int, const size_t, const double)
will force the RFGR to 9 (more than 60 dB of attenuation!) before allocating the remainder of the requested gain to the IFGR. Now you might argue that SDRPlay users should always set their gains by name -- but unfortunately, certain unenlightened applications do not expose the individual named gains, and there may be no way to avoid a call to the automatic gain distribution algorithm.

Proposed solution 1: quick and easy

  • Override the default SoapySDR implementation of SoapySDR::Device::setGain(const int, const size_t, const double). Rather than attempting to distribute gain between stages, the requested gain will be assigned directly to the IFGR and the RFGR will not be changed.
  • For consistency, also override SoapySDR::Device::getGainRange(const int dir, const size_t channel) to exclude the RFGR.
  • SDRPlay's automatic gain control works in much the same way -- it varies the IFGR but does not touch the RFGR.

Proposed solution 2: fix the abstraction, break some existing configurations

  • Remove RFGR from the list of available gains. It will remain available through the "rfgain_sel" menu item (which perhaps should be renamed to "LNA_state").
  • Invert the sign of IFGR in SoapySDR, so that it spans from -20 to -59 rather than +20 to +59. This will match the SoapySDR sign convention of a bigger number representing more amplification, while preserving a clear correspondence with the numerical IFGR values present in SDRPlay documentation.
  • With these abstractions fixed, setGain and getGainRange will now do the right thing without any further changes.

I am very new to SoapySDR (and SDR in general, for that matter). I would be happy to send in a pull request, but first I'd appreciate some feedback from the maintainers regarding the preferred approach.

Huge thanks to SDRPlay support for helping me understand what is going on in the hardware... responding in 15 minutes at midnight on Saturday!

@dlaw dlaw changed the title Override SoapySDR::Device::setGain to account for SDRPlay gains SoapySDR::Device::setGain has undesired behavior for SDRPlay Nov 3, 2019
@guruofquality
Copy link
Contributor

I am very new to SoapySDR (and SDR in general, for that matter). I would be happy to send in a pull request, but first I'd appreciate some feedback from the maintainers regarding the preferred approach.

Sounds great, thats exactly what overriding setGain is for. A PR would be very helpful, and gives us something specific to discuss.

@dlaw
Copy link
Author

dlaw commented Nov 4, 2019

@guruofquality Thanks for the response! I've opened #61 with the larger set of changes to bring SoapySDRPlay in line with the SoapySDR gain abstraction. I think this is the best long-term solution.

A simpler change would be to keep the non-standard RFGR and IFGR, and override setGain to ensure that RFGR is never changed. I think this solution is more confusing in the long term, and it's not consistent with the behavior of other SoapySDR hardware interfaces.
pothosware/SoapySDRPlay3@master...dlaw:master

The argument I see for the simpler solution would be concern over breaking existing configurations. But if you agree, I'd prefer to move ahead with the changes as sketched out in #61.

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

No branches or pull requests

2 participants