-
Notifications
You must be signed in to change notification settings - Fork 15
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
New gain controls #35
Comments
Wow! That is quite an amazing piece of work! Thank you @fventuri ! I will give it a test run sometime over this next week, but in the meantime, a comment about the "generic" SoapySDR provides a default implementation of the "generic" In the case where all gains are in dB, the default implementation is already correct and we do not need to implement these functions ourselves. (Well, technically we may wish to tweak It is in the other three cases where we do need to implement our own generic |
I think the IF gain range from 20 dB to 59 dB is a bit of an anti-pattern, and if you must avoid the negative numbers, a range from 0 dB to 39 dB would be better. Here's why: An IF gain range of -59 dB to -20 dB will be confusing to a user who does not expect negative numbers, but at least the correspondence with IFGR value will be obvious for any user who uses SDRuno or is looking at SDRPlay documentation: IF -20 is IFGR 20, IF -30 is IFGR 30, etc. An IF gain range of 20 dB to 59 dB eliminates the confusion with negative numbers, but a user could easily look at the range from 20 to 59 and conclude that this IF gain is exactly the same as the IFGR value from the datasheet! Whereas I think few users will readily deduce that e.g. an IF gain of 30 turns into an IFGR of 49. So, for the case where you don't want to use negative numbers, I think it is better for IF gain to go from 0 to 39. This makes it obvious that the IF gain is something different than the IFGR and removes the possibility for confusion. I still think the negative gains are cleanest of all, but 🤷 I will test out the options shortly and report back to confirm functionality and share any notes on usability. Cheers! |
@dlaw - many thanks for your comments and for giving it a try so quickly. A few comments:
Franco |
I've been reading the gain thread with great interest. Fundamentally the RSPs have 2 gain systems with a single hardware AGC system. How this is all implemented in SoapySDRPlay isn't something that you need my input on. All I would do is point out some things that we have found in the development of SDRuno over the last few years...
One thing that I looked at doing once for the TCP server was to map each RSP/LO frequency combination to an appropriate IFGR + RGFR value for a given single gain value. Of course this only works for when the IFAGC is off, but if the IFAGC is enabled, you could disable it, set the IFGR+RFGR and then enable the IFAGC - this would have the effect of putting the user close to where they wanted to be. If they want total gain control then the IFAGC would need to be disabled. There were some other issues that occurred in that piece of work that meant the single gain value work was not completed or implemented. If you wanted to mimic how SDRuno works then you would need to have 2 independent gain control systems that could be individually set to have AGC or not. Then some code that internally could report back to the user on what GR or gain has actually been set. Also, I think the key thing is to remember what the target audience is for this library. It's developers and not end users. I personally would look at popular end user software, see how they have been developed to work in gain and then work out the best way to interface to that with minimal impact. Just my two penneth. Best regards, Andy |
@SDRplay - thanks for the interesting and useful thoughts, Andy I have a few personal considerations about your last comment, where you say that the target audience is developers and not end users. I suspect that a SoapySDR module like SoapySDRPlay3 is mostly used within client applications like CubicSDR or gqrx; these SDR receiver programs cater to a wider audience than just developers (in my opinion), as opposed to a software like GNU Radio, where the average user is probably someone more technical and more familiar with the concepts of SDRs. This whole preamble is to say that I think we have to put ourselves in the shoes of the end user when making decisions on these controls: which controls could be more useful to them, easier for them to understand, or just "make sense". On the other hand, as a developer of a module like SoapySDRPlay3, I am bound to the contract that is the SoapySDR API; namely in this case to the description of the arguments of
In closing, what I am trying to say is that whatever we end up choosing will be some sort of trade-off, and there will always be someone who won't be 100% happy with it. Franco |
Hi Franco, What I meant by that is that of course the end user will need to be able to set frequency, sample rate, gain, etc. however they will not care how that is handled by the SoapySDRPlay library. It is the job of the developer to understand these concepts and present them to the end user. For example when we point people to CubicSDR and the SoapySDR framework, almost all of them won't know or care what the SoapySDRPlay library does, just that they can control the hardware through the CubicSDR interface. For the large part, and I'm not saying this is you, what I've seen here is "how do we get the SDRplay gain control to operate like a RTL device does" - if that's the end goal then that's one thing, but that's not to understand what benefits the RSP gain control system has. We have many thousands of customers that use various software and I would say a lot less than 1% of them want, or have the coding knowledge, to understand or use the SoapySDR framework in anything other than an end application. From our experience you guys are the exception rather than the rule. If you see what I mean. Best regards, Andy |
@SDRplay - Andy, thanks for your always welcome advice and for keeping me (and this group) grounded down to earth, i.e. to the reality of the actual end users. I followed your suggestion of taking a look at what the other popular SDR applications are doing regarding the gain controls for the SDRplay RSPs; since I think that 90% of the SDR end users run Windows, I looked at what is the approach for gains in the most popular SDR applications for Windows:
I also googled terms like 'sdrconsole gain controls', and there seems to be some confusion among the end users on how these controls work (see for instance here: https://sdrplay.com/community/viewtopic.php?t=3524 and here: https://sdr-radio.groups.io/g/main/topic/16932930). I found similar results when googling 'hdsdr sdrplay gain controls' (for example: https://www.sdrplay.com/community/viewtopic.php?t=356). Finally I implemented yet another gain control model, that I called 'NO_IF_GAIN_CONTROL_ON_AGC' for lack of a better term; it is essentially the same as the 'DB' gain control model, except that I changed Franco |
Thanks @fventuri for your dedication. I gave some try on your branch, and the most usable was the
About your last message:
Good heavens, CubicSDR certainly didn't expect the gain list to change dynamically. I'll have a look If it can be changed when I have some time.
Standard procedure for Cubic, yes. It has been discussed in the past if we can add configurable behaviour for the Gain controls, i.e choosing which one you want to hide if AGC is on. It is certainly possible to do so, but I'm lacking the motivation to do it myself. Is it not a niche feature anyway ?
See the points above :) |
@vsonnier - many thanks for your feedback and useful suggestions! I finally found some time this weekend to fix the problem with the settings selection for the RF Gain (or RFGR, or LNA, depending on the gain control model); it is now back to a string type (instead of an integer), so it should be easier to use, and the avalable selections now match the correct options for each of the gain control models. On the AGC front, I knew it was a very tall order for CubicSDR (and probably for any other SDR application out there) to be able to deal with a list of gains that changes dynamically, but I was just too curious to see what would happen - so don't worry about try to handle a gain list changing dynamically, since I doubt any other SDR client would be happy about it anyway (I removed that gain control model with this latest commit). Franco |
Working on the RF control via a SoapySDR setting yesterday, gave me the idea of a possibly better approach for handling IF AGC; instead of using SoapySDR With this approach, and a small change to the CubicSDR source code (see below), I was able IMHO to have a much better user experience using the IF AGC with CubicSDR. This new approach can be enabled by setting the cmake variable As per the CubicSDR source code change mentioned above, I had to change lines 1028-1034 of
to something like this:
Before trying the new Franco |
For the cases where the client application can only use the generic Tonight I went ahead and implemented both options for the 'Legacy' gain control model; you can try them by editing the cmake config file
The code with these options is in the usual Franco |
Thanks again @fventuri for implementing all of these different options. And thanks to @SDRplay for the insight about how users tend to adjust the gains. I played around with all the different options and here are some thoughts:
It seems that @fventuri has the code well in hand, but once it is decided which of these options to merge, I volunteer to write some documentation about gains for the SoapySDRPlay wiki ✍️ Cheers! |
Thanks for your feedback @dlaw This weekend I thought that with so many choices on the gain controls it is almost impossible to make everyone happy. Perhaps a better approach would be to select the more sensible and useful models among them, and create a a new 'meta' setting called say 'gain_control_model' (or something like that), whose values could be something like 'Legacy', 'DB', 'LNA', etc. This meta setting would not be listed by This way a more advanced user could set up the gain control as they prefer - they would have to just add an entry for that setting in the CubicSDR That's just an idea that popped up in my head; if there's a general consensus that it is worth trying, I could work on it this coming weekend. Franco |
Sorry, for late reply. I see a lot of development on gain modes, how can I select one ? |
@nmaster2042 - no problem at all - I have been busy these days too, so I understand you 100% Yes, at this time it is a compile time option that you can set in the cmake config file The different gain control models available at this time are described in detail in these comments: #35 (comment) ('Legacy', 'SDRplay', 'DB', and 'LNA'), and #35 (comment) ('Normalized'). You may also want to to try out a new implementation of the IF AGC controls that in @dlaw and my opinion provides a much better user experience with the IF AGC enabled in CubicSDR. To try it, you'll have to set Finally I just ported to the Franco |
Thanks to @fventuri for pointing me to this issue and for all the hard work and thought; thanks also to @dlaw, @SDRplay and @vsonnier for your contributions. As I wrote in a now deleted post here, I had run into this issue after discovering experimentally that the "gains" as reported by SoapySDR were in fact gain reductions. My use case might be worth adding to your deliberations: I'm working on adding SoapySDR support to the Dream Digital Radio Mondiale receiver project, and I want to be able to measure and report the received signal power in dBuV at the antenna input. Dream already measures the power in-band in the digital signal, but needs to apply a correction for the amount of gain applied in the front-end SDR device. For this to work consistently, the overall gain reported by the "generic" getGain() function needs to be (a) in dB and (b) to include all the variable gains in the frontend. (It doesn't need to be the absolute gain - there's a "calibration factor" in the config file to convert the final figure to dBuV). As I hope you'll agree, the only option that satisfies this use case is the "DB" model, and I'd even started implementing something like it myself before Franco thankfully pointed me here. I'll try out the DB model next and let you know how I get on! Ollie. |
Update: I've tried out this branch with GAIN_MODE set to "DB", and it's working perfectly. I tried all 7 of the LNA settings on the RSP1A and my signal strength measurement gives the same value (within a dB) over the whole range. I am most grateful at having been saved a lot of work! The only surprise was that the "RF Gain setting", i.e. using writeSetting("rfgain_sel", ...), was also in dB, but requiring an exact match. For some reason I expected it to set the LNAState directly as in the Legacy model. I can see the argument for having the setting presented as meaningful options, but there's the difficult problem of how to deal with changes of frequency, which you have discussed above. I had thought that it could just keep the LNAState, but I'd overlooked the jaggedness of the tables, which means that a particular LNAState might no longer be valid following a frequency change. On the other hand, it's also likely that a given dB gain value wouldn't be valid in a different band. In the end I undefined GAIN_MODE_DB_POSITIVE so that I could simply use the negative of the values in the table (I'm with @dlaw on this point!). I think that will be fine for my application. @fventuri's suggestion of a meta-setting is interesting and might eventually be a better option than requiring compile-time settings. Thanks again! OIllie. |
Hi. Very sorry @fventuri, things didn't happened like I expected (personal case). I agree with you for a meta "gain_control_mode", it would be better than compile time config in CMakefile ;-) If this meta parameter is added but not exposed, how could it be used ? |
@nmaster2042 - no problem at all! No, the code in the Based on your suggestion, I think I'll create a new branch with the option to select the gain control model at device creation (i.e. through a parameter in the SoapySDR device string), with the default set to 'legacy' mode, so it wouldn't affect the existing users of CubicSDR. Franco |
@fventuri : Sure it will be the best option. |
I just pushed to the branch There are currently four options available:
All the gain control modes above except for the first one ('legacy') also offer a 'generic' Tonight I ran a few tests with each one of these gain control modes using the application CubicSDR, and it seems to me that they work as expected; feel free to run more tests, and tell me if you see any problem. I also renamed the old 'new-gain-controls' branch (the one where you had to rebuild every time you wanted to change gain control mode) to Let me know what you think, and I really apologize that it took me so long to get this new code out. Franco |
Hello, Franco! It is very nice to see that you have finally got to do something about setGain(). I am somewhat disappointed though that you have not implemented the mode I suggested, where setGain() controls IFGR, while RFGR is left alone, set with a separate (already existing) parameter. I am going to try your changes, but since MSI.SDR has been shown to use completely different units to control RFGR, it is unlikely that any of the highly elaborate models you implemented are going to make any sense for my use case. |
So, since the effective gain now depends on the frequency, why aren't you updating gain settings in setFrequency()? Also, what happens if a previously set gain is out of range for a newly selected frequency? |
@luarvique - thanks for the feedback! First of all I didn't mean to disappoint you; I just implemented these four types of gain controls in the last week or so, but now that the C++ class infrastructure is in place (it took me a few tries to come up with the current approach), I think it would be pretty straightforward to add another gain control mode based on the IF gain (or gain reduction); I have been really busy with work recently, but I think this weekend I should be able to find the time to do it, so you can give it a try and compare it with the other methods. A few more notes:
Franco |
Thanks,, that would be hugely appreciated. I have also submitted a pull request with the appropriate changes, although they are an order of magnitude less elaborate than what your current implementation is.
Be it frequency or band, you are still creating a situation where user changes to the frequency inadvertently break their previously chosen gain value. There is no way to explain this as a normal, logical behavior to a user. Hence, you probably want to store the last selected (or the default) gain value somewhere and call setGain() on frequency changes. I suppose this situation does not apply when the user sets both RFGR and IFGR explicitly, since they probably know what they are doing. It also does not happen if only IFGR affects the overall gain, since IFGR meaning is constant and well defined.
This is true, but the rfgain_sel value is not treated as actual generic gain. It has no implicit semantics, but is rather some weird setting that is allowed to behave any way it likes. A magic switch, so to say.
Well, I doubt that this particular license term is enforceable. As to the ethics of the MSI.SDR usage, the manufacturer does not claim this device to be an SDRPlay or its clone. Anyone can take the same two MSI chips and connect them according to the datasheet. Before we continue down this slippery quasi-legal slope, I also own a real, genuine RSPduo which is, of course, a much better device than MSI.SDR. It just doesn't fit the use case where MSI.SDR is being used.
I will probably look into that, but there are only so many open source packages I can fix in the remaining free time, and I am kind of hitting this limit here. PS: Speaking of fixes, there is a partial deadlock in the current SoapySDRPlay3 code. Please, see pull request #59. |
@fventuri I built the new branch and made tests with CubicSDR. |
Thanks for mentioning me here. I agree that sometimes more control over the device's gains is required, and sometimes it's not. The "sweet spot" heavily depends on your antenna (to not get into overload) and on the frequency. And since there are 4 gain controls, it's not trivial to make it right (this thread is an evidence of that). The libmirisdr driver by Miroslav Slugeň can work in both modes, with one slider approximating the real attenuation, or with 4 sliders (or less, if combined) for each stage separately: https://github.com/ericek111/libmirisdr-5/blob/master/src/gain.c#L20 Looking at the code, it's kind of what I had in mind, except I believe these opinionated decisions should be handled by the (painfully unstable, insecure by design, closed-source and not portable) driver itself. |
I was requesting documentation for the actual customers / users / operators of these devices. I think this needs more explanation than just inline documetation in a source file. Please address, if you want this to succeed, you need to be able to explain in plain and simple words what happens, otherwise this will only lead to more confusion.
I think you've picked out a very use case here. What about users that hook up their SDRs to dualband antennas for 2m and 70cm? What about using a diplexer or wideband antennas to get even wider coverage? The user in the OpenWebRX context does not have the ability to adjust the gain, so please, for the love of consistency: If the gain is a function of frequency, adjust the gain when adjusting the frequency. |
Thanks for your useful and interesting comments @luarvique @nmaster2042 @ericek111 @jketterl Tonight I took a quick stab at implementing the It's getting late here and I do not have much time and energy left to write down my thoughts; just a quick comment on the documentation request: all these gain control modes are still a work in progress (that's why they are not in the Franco |
Hello, Franco! I've submitted a pull request to OpenWebRX, adding support for the gain model selection and a few other options present in SoapySDRPlay3: |
Hi Franco. Tried on CubicSDR, it works fine here too. |
Given the diversity of opinions on how the gain controls should work (see discussion here: #27), I spent some time over the weekend thinking about a possible way of dealing with all the different tastes and preferences, and I just pushed my changes to the
new-gain-controls
branch.Basically I created four different 'models' of gain controls, selectable via a line in the cmake config file
CMakeLists.txt
(https://github.com/pothosware/SoapySDRPlay3/blob/new-gain-controls/CMakeLists.txt#L43).The four models are:
master
(IFGR and RFGR, no "generic"setGain()
, etc); if these changes land inmaster
, the default could be initially set to 'Legacy' for compatibility with the existing clients; this way the distributions would use the 'Legacy' mode by default, and there would be little to no disruption to the end users.RF
andIF
, and the values are expressed in dB (higher values mean more gain, i.e. stronger signal). Since the two gain control values use the same units, I also added a genericsetGain()
(andgetGain()
), where the requested gain is split between RF and IF in parts proportional to the range of each gain control (see the source code for details). The dB range of these "gains" is arbitrary: for IF I chose the range [20,59], while for RF I chose the range [X,100] (where X depends on the RSP model, frequency band, etc). For those who prefer negative values like @dlaw, commenting out lines 49-51 inCMakeLists.txt
will do just that.LNA
andIF
(higher values mean more gain, i.e. stronger signal). The default range for IF is the same as before ([20,59]), while the default range for LNA is [0,max(LNAstate)]. Since these values use incompatible units, I did not define a genericsetGain()
(orgetGain()
) for this case. For those who prefer negative values, again commenting out lines 46-48 inCMakeLists.txt
will do the trick.To make it easier to work with all the different gain control models (and perhaps to add more if we like to explore other options), I pulled out of
Settings.cpp
all the code for the gain API, and reorganized it in four different source files, one for each of these gain control models (plus one for some common code related to the gain reduction tables from the SDRplay API specification document).One final note about the gains in dB: I spent some time yesterday afternoon playing around with SDRuno, switching the RF gain display mode back and forth between 'Gain' and 'Attenuation', and I noticed that while the dB values for RF attenuations in SDRuno match exactly the values in the gain reduction tables in the SDRplay API specification, the same is not true when the RF gain display mode is set to 'Gain': the dB values in this case have decimals, their spacing is different than shown in the tables (for instance the gain reduction tables might have 7dB difference between two successive LNA state values, while the SDRuno RF gain changes 6.5dB between the same LNA states); the minimum and maximum values depend on the frequency band, the RSP model, and possibly other factors.
In other words I have the impression that SDRplay have done a good amount of work in figuring out the real gains in dB (and those are displayed in SDRuno when the RF gain control is set to 'Gain'), while the figures from the gain reduction tables are just rough approximations, and it is not obvious to me how the two are related, i.e. how to compute the real RF gain from the LNA state (I searched around for a bit, but I couldn't find much information about these RF gain values).
As a consequence the RF "gains" in dB of the third gain control model (the one I called 'DB') are not the real gains, and shouldn't be treated as such; they are just some arbitrary values in dB that "approximate" the behavior of the real gain, in the sense that increasing the
RF
gain control by 10dB increases the signal by about 10dB, but the RF gain value shown is purely arbitrary (I hope this rambling makes sense).One last caveat when using CubicSDR with the new gain controls: CubicSDR stores the last used config under
$HOME/.CubicSDR/config.xml
(on Linux; there's probably a similarly named file on Windows and Mac); in my case this file had the last used gains controls asIFGR
andRFGR
, and threw a few error messages about invalid gain range when starting the RSP, because those names are different in some of the gain control models; if you see similar error messages, you may want to recreate the CubicSDRconfig.xml
file from scratch (or edit it to change the names and values of the gain controls, if you don't want to lose the rest of the CubicSDR configuration).@SDRplay, @vsonnier, @dlaw, @nmaster2042, please give it a try and let me know what you think (I just ran a few quick tests here streaming a local FM station, and they worked, but there are probably still bugs in the code).
Franco
The text was updated successfully, but these errors were encountered: