Gain control acts in reverse ?
pjalocha opened this issue · 18 comments
I installed SoapySDR support for SDRPlay and try some applications which worked with other hardware.
Strange enough I was getting very weak signals, like near or below the digitization level, even setting the maximum gain.
The I tried lower gain and then the signals got stronger and stronger... the strongest and like normal level is wneh I set gain to zero ?!
It appears as if the gain acts in reverse: higher gain is lower amplification and the reverse.
Did anybody notice such behavior ?
SoapySDRPlay supports IFGR and RFGR, these are IF gain reduction and RF gain reduction (or attenuation), not gain. RFGR = 0 is minimum attenuation or maximum gain and the same for IFGR
OK, this explains.
But shouldn't then these attenuation be given as negative number for consistent control ?
As well the overall gain 0..42dB should be given in the same direction of control as for other SDR interfaces, again for consistency.
Otherwise, how can the user know that the gain he specifies is really the attenuaton ?
Or tell him the overall gain range is -42dB .. 0dB ?
Not sure I understand - IFGR and RFGR are Gain Reduction (or attenuation) and they only support positive numbers of gain reduction - RFGR represents a gain reduction stage from maximum gain (0 to a variable maximum depending on device and frequency). Each step has a certain amount of gain reduction. IFGR ranges from 20 to 59 (except the RSP1 which is 0 to 78) - the IFAGC only works on the IFGR and not the RFGR - I'm not sure where the 0 to 42 comes from? Hopefully whatever application you are using shows RFGR and IFGR and not gain? CubicSDR shows RFGR and IFGR - the API can report the gain for a given gain reduction setting (which is calibrated gain value), so you could change SoapySDRPlay if you wanted to, to support gain as well as gain reduction. This is what we do in SDRuno. The RF Gain Reduction table can be seen in section 5.3 (P70) in the API specification: https://www.sdrplay.com/docs/SDRplay_SDR_API_Specification.pdf - hope that helps.
OK, I mean from a perspective of a pure naive user who used SoapySDR as a tool to run some SDR platforms like RTLSDR, AirSpy and LimeSDR and now he got to the SDRPlay.
My code worked on these other hardware platforms, I could ask SoapySDR for gain range, etc.
and so I could try the max. gain, adjust it, if the signals were too strong, etc.
Now, I go to SDRPlay, all seems fine, I ask what the gain range is, it tells me 0-42dB, fine, so I try with the max. gain first, as I have tiny antenna anyway.
And here comes the surprise: the data shows very low noise level and no signals !
I thought the hardware was bad or I was doing something wrong, etc.
It took me half a day before I realized the reverse gain action.
This is why I suggest that at least the overall gain setting should act in the positive direction:
larger number is doing larger gain for the receiver chain and the SDR data.
I guess I'm just surprised that it's reporting 0 to 42 - what are you doing to get that back from SoapySDRPlay - it's possible that this is something that needs looking at.
I type: SoapySDRUtil --probe="driver=sdrplay"
and get the reply:
(...)
-- RX Channel 0
Full-duplex: YES
Supports AGC: YES
Stream formats: CS16, CF32
Native format: CS16 [full-scale=32767]
Antennas: RX
Corrections: DC removal
Full gain range: [0, 42] dB
IFGR gain range: [20, 59] dB
RFGR gain range: [0, 3] dB
Full freq range: [0.01, 2000] MHz
RF freq range: [0.01, 2000] MHz
CORR freq range: MHz
Sample rates: 0.25, 0.5, 1, 2, 2.048, 6, 7, 8, 9, 10 MSps
Filter bandwidths: 0.2, 0.3, 0.6, 1.536, 5, 6, 7, 8 MHz
ok, I hadn't noticed that, I'll have to see where those numbers are coming from. You can see that it doesn't relate to the available gain reduction range.
Well, I think it does relate.
My initial interpretation was: there are two elements with settable gains in the chain
and one can vary by 39dB and the other by 3dB which make total variable gain range of 42dB.
It was thus logical to have the overall gain variation of 42dB and you could assume the zero of this range to be at the lowest gain setting.
The RFGR is a stage value, you can see from the document I linked that it is not a dB value - some configurations have over 60 dB of RF gain reduction range, which is on top of the 40 dB of IF gain reduction range, so the maximum gain range is closer to 100 dB, not 42
The total available gain control range is dependent on RSP device and LO frequency, so it's not possible to return a totally accurate value in the probe - a maximum value could be returned, but then maybe SoapySDRPlay should silently ignore gain requests that were outside of the limits?
I don't mind clippng the requested gain value accoriding lo hardware limits, it is the sign, which is important for good interpretation. If it says "gain" then larger values should correspond to larger gain, attenuation should be represented by negative numbers.
Would be nice to be able to use the full gain range.
From the current SoapySDR interface I can only set numbers from 0 to 42
and so likely I am not able to use the full range.
There are a few issues having looked through the code if you assume it works in gain mode...
The "gains" are correctly labelled IFGR and RFGR, and the ranges seem to be correct. However, setGain just sends the value specified through to IFGR or RFGR. Maybe a setGainReduction function would be useful or some sort of estimate as I describe below...
Also, RFGR is shown as its stage range and it seems to be assumed as a dB value - this is not right. listGains should probably be updated to show a dB value for RFGR, not a RF State value
setGain function requires either IFGR or RFGR, so at least 2 writes are required to set the gain manually. If AGC is enabled, then you just need to set RFGR (as this isn't controlled by the AGC)
Turning a single gain value into the optimum IFGR and RFGR isn't really possible.
setGain(SOAPY_SDR_RX, 1, "IFGR", 30);
setGain(SOAPY_SDR_RX, 1, "RFGR", 1);
this would set a gain reduction of anywhere between 35 and 40 dB depending on what device and LO frequency is previously set. The RFGR stage of 1 could be 5, 6, 7 or 10 dB if you look at the tables. I guess this would equate to something like 60-70 dB of gain
You could have a look up table I guess, so that something like...
setGain(SOAPY_SDR_RX, 1, "GAIN", 60);
would then apply some IF and RF gain reduction values, however they may not be optimum but could be close.
May be there is someone who wants to have a go at that?
Clearly, an optimum setting would be very nice here.
A naive user does not want to go into the hardware details.
Other hardware achieve this somehow, although the algorithm can be non-trivial and not-optimal as it is done now.
Some drivers use additional settings like "linear mode" or "sensitivity mode" to help the algorithm decide.
Anyway, is it possible that whether you call setGain() of whatever stage or overall, higher numbers would represent higher gain ?
well you could duplicate the IFGR and RFGR to IFGain and RFGain so that...
setGain(SOAPY_SDR_RX, 1, "IFGain", 40);
would basically set IFGR to (59 - 40) - that would be a crude way of doing it. We recommend that AGC is left enabled and that only RFGR is used. This works in the majority of cases.
So for now if you enable AGC and then use...
setGain(SOAPY_SDR_RX, 1, "RFGR", 0); // max gain
setGain(SOAPY_SDR_RX, 1, "RFGR", 1); // 5-10 dB from max gain
etc., this would give you access to a wider gain range than 0-42 (which isn't real and is just an addition of the IF gain reduction range and the RF stage range, which is wrong).
The thing is, this needs customized code for various hardware interfaces.
In fact, I started from AGC (I did not touch it, thus it was enabled by default)
I only set the gain (which turned out to be attenuation) and the receiver would not
atomatically come up to some reasonable gain by the AGC control.
i will work on this. I'll definitely will solve that overall gain won't act in reverse (and even all exposed gain elements - I'm not sure gain reduction should be exposed at all). Will see what I can do about some gain values not being actual dB but index into a gain table