diff --git a/CMakeLists.txt b/CMakeLists.txt index 268a02a..755f310 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,11 +32,12 @@ if(CMAKE_COMPILER_IS_GNUCXX) add_definitions(-Wno-unused-parameter) endif(CMAKE_COMPILER_IS_GNUCXX) -# Configurable feature set -SET (RF_GAIN_IN_MENU ON CACHE BOOL "Add Rf gain as a setting, additionally to the IFGR gain control") +# The SDRPlay LNA state, aka "RF gain", is more properly a setting than a gain. +# However, some users may prefer to also expose it as a SoapySDR gain. +SET (LNA_STATE_AS_GAIN OFF CACHE BOOL "Duplicate the lna_state setting as a SoapySDR gain.") -IF(RF_GAIN_IN_MENU) - ADD_DEFINITIONS( -DRF_GAIN_IN_MENU=1 ) +IF(LNA_STATE_AS_GAIN) + ADD_DEFINITIONS( -DLNA_STATE_AS_GAIN=1 ) ENDIF() SET (STREAMING_USB_MODE_BULK OFF CACHE BOOL "Use USB bulk mode instead of isochronous") diff --git a/Settings.cpp b/Settings.cpp index 8f6d5c6..7cc2e96 100644 --- a/Settings.cpp +++ b/Settings.cpp @@ -74,6 +74,12 @@ SoapySDRPlay::SoapySDRPlay(const SoapySDR::Kwargs &args) unsigned int idx = 0; for (unsigned int i = 0; i < nDevs; ++i) { + maxLnaState = 3; // SDRPLAY_RSP1_ID (default) + if (rspDevs[i].hwVer == SDRPLAY_RSP2_ID) maxLnaState = 8; + if (rspDevs[i].hwVer == SDRPLAY_RSPduo_ID) maxLnaState = 9; + if (rspDevs[i].hwVer == SDRPLAY_RSP1A_ID) maxLnaState = 9; + if (rspDevs[i].hwVer == SDRPLAY_RSPdx_ID) maxLnaState = 27; + switch (rspDevs[i].hwVer) { case SDRPLAY_RSP1_ID: @@ -591,8 +597,10 @@ std::vector SoapySDRPlay::listGains(const int direction, const size //the functions below have a "name" parameter std::vector results; - results.push_back("IFGR"); - results.push_back("RFGR"); +#ifdef LNA_STATE_AS_GAIN + results.push_back("RF"); +#endif + results.push_back("IF"); return results; } @@ -630,72 +638,86 @@ void SoapySDRPlay::setGain(const int direction, const size_t channel, const std: bool doUpdate = false; - if (name == "IFGR" && chParams->ctrlParams.agc.enable == sdrplay_api_AGC_DISABLE) + if (name == "IF" && chParams->ctrlParams.agc.enable == sdrplay_api_AGC_DISABLE) { - //apply the change if the required value is different from gRdB - if (chParams->tunerParams.gain.gRdB != (int)value) + int new_gRdB = -((int)value); + //apply the change if the required value is different from gRdB + // gRdB is a gain *reduction*, so we negate the SoapySDR "IF gain" + // in order to obtain the new gRdB. + if (chParams->tunerParams.gain.gRdB != new_gRdB) { - chParams->tunerParams.gain.gRdB = (int)value; + chParams->tunerParams.gain.gRdB = new_gRdB; doUpdate = true; } } - else if (name == "RFGR") +#ifdef LNA_STATE_AS_GAIN + else if (name == "RF") { - if (chParams->tunerParams.gain.LNAstate != (int)value) { + // The RF gain is negated to obtain the LNA state. + int newLnaState = -((int)value); + if (chParams->tunerParams.gain.LNAstate != newLnaState) { - chParams->tunerParams.gain.LNAstate = (int)value; + chParams->tunerParams.gain.LNAstate = newLnaState; doUpdate = true; } } - if ((doUpdate == true) && (streamActive)) +#endif + if (doUpdate && streamActive) { sdrplay_api_Update(device.dev, device.tuner, sdrplay_api_Update_Tuner_Gr, sdrplay_api_Update_Ext1_None); } } +void SoapySDRPlay::setGain(const int direction, const size_t channel, const double value) +{ + // Only IF should be used for adjusting the overall system gain. + this->setGain(direction, channel, "IF", value); +} + double SoapySDRPlay::getGain(const int direction, const size_t channel, const std::string &name) const { std::lock_guard lock(_general_state_mutex); - if (name == "IFGR") + if (name == "IF") { - return chParams->tunerParams.gain.gRdB; + // gRdB is a gain *reduction*, so we negate it to obtain the SoapySDR "IF gain". + return -chParams->tunerParams.gain.gRdB; } - else if (name == "RFGR") +#ifdef LNA_STATE_AS_GAIN + else if (name == "RF") { - return chParams->tunerParams.gain.LNAstate; + // LNA state 0 is the minimum numeric value but corresponds to maximum gain. + // We define the RF gain as the negative of the LNA state so that any gain + // adjustment controls (e.g. CubicSDR sliders) operate in the correct direction. + return -chParams->tunerParams.gain.LNAstate; } +#endif return 0; } +double SoapySDRPlay::getGain(const int direction, const size_t channel) const +{ + // Only IF should be used for adjusting the overall system gain. + return this->getGain(direction, channel, "IF"); +} + SoapySDR::Range SoapySDRPlay::getGainRange(const int direction, const size_t channel, const std::string &name) const { - if (name == "IFGR") - { - return SoapySDR::Range(20, 59); - } - else if ((name == "RFGR") && (device.hwVer == SDRPLAY_RSP1_ID)) - { - return SoapySDR::Range(0, 3); - } - else if ((name == "RFGR") && (device.hwVer == SDRPLAY_RSP2_ID)) - { - return SoapySDR::Range(0, 8); - } - else if ((name == "RFGR") && (device.hwVer == SDRPLAY_RSPduo_ID)) - { - return SoapySDR::Range(0, 9); - } - else if ((name == "RFGR") && (device.hwVer == SDRPLAY_RSP1A_ID)) - { - return SoapySDR::Range(0, 9); - } - else if ((name == "RFGR") && (device.hwVer == SDRPLAY_RSPdx_ID)) +#ifdef LNA_STATE_AS_GAIN + if (name == "RF") { - return SoapySDR::Range(0, 27); + return SoapySDR::Range(-maxLnaState, 0); } - return SoapySDR::Range(20, 59); +#endif + // IF gain + return SoapySDR::Range(-59, -20); +} + +SoapySDR::Range SoapySDRPlay::getGainRange(const int direction, const size_t channel) const +{ + // Only IF should be used for adjusting the overall system gain. + return this->getGainRange(direction, channel, "IF"); } /******************************************************************* @@ -1176,119 +1198,16 @@ SoapySDR::ArgInfoList SoapySDRPlay::getSettingInfo(void) const non_const_this->selectDevice(); } -#ifdef RF_GAIN_IN_MENU - if (device.hwVer == SDRPLAY_RSP2_ID) - { - SoapySDR::ArgInfo RfGainArg; - RfGainArg.key = "rfgain_sel"; - RfGainArg.value = "4"; - RfGainArg.name = "RF Gain Select"; - RfGainArg.description = "RF Gain Select"; - RfGainArg.type = SoapySDR::ArgInfo::STRING; - RfGainArg.options.push_back("0"); - RfGainArg.options.push_back("1"); - RfGainArg.options.push_back("2"); - RfGainArg.options.push_back("3"); - RfGainArg.options.push_back("4"); - RfGainArg.options.push_back("5"); - RfGainArg.options.push_back("6"); - RfGainArg.options.push_back("7"); - RfGainArg.options.push_back("8"); - setArgs.push_back(RfGainArg); + SoapySDR::ArgInfo LnaStateArg; + LnaStateArg.key = "lna_state"; + LnaStateArg.value = std::to_string(maxLnaState / 2); + LnaStateArg.name = "RF Gain Select"; + LnaStateArg.description = "SDRPlay LNA State"; + LnaStateArg.type = SoapySDR::ArgInfo::STRING; + for (int i = 0; i <= maxLnaState; i++) { + LnaStateArg.options.push_back(std::to_string(i)); } - else if (device.hwVer == SDRPLAY_RSPduo_ID) - { - SoapySDR::ArgInfo RfGainArg; - RfGainArg.key = "rfgain_sel"; - RfGainArg.value = "4"; - RfGainArg.name = "RF Gain Select"; - RfGainArg.description = "RF Gain Select"; - RfGainArg.type = SoapySDR::ArgInfo::STRING; - RfGainArg.options.push_back("0"); - RfGainArg.options.push_back("1"); - RfGainArg.options.push_back("2"); - RfGainArg.options.push_back("3"); - RfGainArg.options.push_back("4"); - RfGainArg.options.push_back("5"); - RfGainArg.options.push_back("6"); - RfGainArg.options.push_back("7"); - RfGainArg.options.push_back("8"); - RfGainArg.options.push_back("9"); - setArgs.push_back(RfGainArg); - } - else if (device.hwVer == SDRPLAY_RSP1A_ID) - { - SoapySDR::ArgInfo RfGainArg; - RfGainArg.key = "rfgain_sel"; - RfGainArg.value = "4"; - RfGainArg.name = "RF Gain Select"; - RfGainArg.description = "RF Gain Select"; - RfGainArg.type = SoapySDR::ArgInfo::STRING; - RfGainArg.options.push_back("0"); - RfGainArg.options.push_back("1"); - RfGainArg.options.push_back("2"); - RfGainArg.options.push_back("3"); - RfGainArg.options.push_back("4"); - RfGainArg.options.push_back("5"); - RfGainArg.options.push_back("6"); - RfGainArg.options.push_back("7"); - RfGainArg.options.push_back("8"); - RfGainArg.options.push_back("9"); - setArgs.push_back(RfGainArg); - } - else if (device.hwVer == SDRPLAY_RSPdx_ID) - { - SoapySDR::ArgInfo RfGainArg; - RfGainArg.key = "rfgain_sel"; - RfGainArg.value = "4"; - RfGainArg.name = "RF Gain Select"; - RfGainArg.description = "RF Gain Select"; - RfGainArg.type = SoapySDR::ArgInfo::STRING; - RfGainArg.options.push_back("0"); - RfGainArg.options.push_back("1"); - RfGainArg.options.push_back("2"); - RfGainArg.options.push_back("3"); - RfGainArg.options.push_back("4"); - RfGainArg.options.push_back("5"); - RfGainArg.options.push_back("6"); - RfGainArg.options.push_back("7"); - RfGainArg.options.push_back("8"); - RfGainArg.options.push_back("9"); - RfGainArg.options.push_back("10"); - RfGainArg.options.push_back("11"); - RfGainArg.options.push_back("12"); - RfGainArg.options.push_back("13"); - RfGainArg.options.push_back("14"); - RfGainArg.options.push_back("15"); - RfGainArg.options.push_back("16"); - RfGainArg.options.push_back("17"); - RfGainArg.options.push_back("18"); - RfGainArg.options.push_back("19"); - RfGainArg.options.push_back("20"); - RfGainArg.options.push_back("21"); - RfGainArg.options.push_back("22"); - RfGainArg.options.push_back("23"); - RfGainArg.options.push_back("24"); - RfGainArg.options.push_back("25"); - RfGainArg.options.push_back("26"); - RfGainArg.options.push_back("27"); - setArgs.push_back(RfGainArg); - } - else - { - SoapySDR::ArgInfo RfGainArg; - RfGainArg.key = "rfgain_sel"; - RfGainArg.value = "1"; - RfGainArg.name = "RF Gain Select"; - RfGainArg.description = "RF Gain Select"; - RfGainArg.type = SoapySDR::ArgInfo::STRING; - RfGainArg.options.push_back("0"); - RfGainArg.options.push_back("1"); - RfGainArg.options.push_back("2"); - RfGainArg.options.push_back("3"); - setArgs.push_back(RfGainArg); - } -#endif + setArgs.push_back(LnaStateArg); SoapySDR::ArgInfo IQcorrArg; IQcorrArg.key = "iqcorr_ctrl"; @@ -1427,15 +1346,12 @@ void SoapySDRPlay::writeSetting(const std::string &key, const std::string &value { std::lock_guard lock(_general_state_mutex); -#ifdef RF_GAIN_IN_MENU - if (key == "rfgain_sel") + if (key == "lna_state") { chParams->tunerParams.gain.LNAstate = static_cast(stoul(value)); sdrplay_api_Update(device.dev, device.tuner, sdrplay_api_Update_Tuner_Gr, sdrplay_api_Update_Ext1_None); } - else -#endif - if (key == "iqcorr_ctrl") + else if (key == "iqcorr_ctrl") { if (value == "false") chParams->ctrlParams.dcOffset.IQenable = 0; else chParams->ctrlParams.dcOffset.IQenable = 1; @@ -1602,14 +1518,11 @@ std::string SoapySDRPlay::readSetting(const std::string &key) const { std::lock_guard lock(_general_state_mutex); -#ifdef RF_GAIN_IN_MENU - if (key == "rfgain_sel") + if (key == "lna_state") { return std::to_string(static_cast(chParams->tunerParams.gain.LNAstate)); } - else -#endif - if (key == "iqcorr_ctrl") + else if (key == "iqcorr_ctrl") { if (chParams->ctrlParams.dcOffset.IQenable == 0) return "false"; else return "true"; diff --git a/SoapySDRPlay.hpp b/SoapySDRPlay.hpp index 086e73e..1619eb6 100644 --- a/SoapySDRPlay.hpp +++ b/SoapySDRPlay.hpp @@ -146,10 +146,16 @@ class SoapySDRPlay: public SoapySDR::Device void setGain(const int direction, const size_t channel, const std::string &name, const double value); + void setGain(const int direction, const size_t channel, const double value); + double getGain(const int direction, const size_t channel, const std::string &name) const; + double getGain(const int direction, const size_t channel) const; + SoapySDR::Range getGainRange(const int direction, const size_t channel, const std::string &name) const; + SoapySDR::Range getGainRange(const int direction, const size_t channel) const; + /******************************************************************* * Frequency API ******************************************************************/ @@ -256,6 +262,7 @@ class SoapySDRPlay: public SoapySDR::Device sdrplay_api_DeviceParamsT *deviceParams; sdrplay_api_RxChannelParamsT *chParams; std::string hardwareKey; + int maxLnaState; //cached settings double outputSampleRate;