diff --git a/CMakeLists.txt b/CMakeLists.txt index 268a02a..344d8c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,13 +32,6 @@ 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") - -IF(RF_GAIN_IN_MENU) - ADD_DEFINITIONS( -DRF_GAIN_IN_MENU=1 ) -ENDIF() - SET (STREAMING_USB_MODE_BULK OFF CACHE BOOL "Use USB bulk mode instead of isochronous") IF(STREAMING_USB_MODE_BULK) diff --git a/Settings.cpp b/Settings.cpp index 8f6d5c6..b8628cc 100644 --- a/Settings.cpp +++ b/Settings.cpp @@ -591,8 +591,11 @@ 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"); + // only return the gains (not the GRs) + //results.push_back("IFGR"); + results.push_back("IF"); + //results.push_back("RFGR"); + results.push_back("RF"); return results; } @@ -624,32 +627,166 @@ bool SoapySDRPlay::getGainMode(const int direction, const size_t channel) const return chParams->ctrlParams.agc.enable != sdrplay_api_AGC_DISABLE; } +static int getMaxRFGR(unsigned char hwVer) +{ + switch(hwVer) + { + case SDRPLAY_RSP1_ID: + return 3; + case SDRPLAY_RSP1A_ID: + return 9; + case SDRPLAY_RSP2_ID: + return 8; + case SDRPLAY_RSPduo_ID: + return 9; + case SDRPLAY_RSPdx_ID: + return 27; + default: + return 0; + } +} + +// There are 29 default gain settings, ranging from 0 to 28, which select a +// pre-determined optimum balance between LNA attenuation and IF attenuation. +// Larger values represent less attenuation (i.e. more gain), but note that +// this value is *not* in decibels. +#define NUM_DEFAULT_GAIN_SETTINGS 29 + +void SoapySDRPlay::setGain(const int direction, const size_t channel, const double value) +{ + std::lock_guard lock(_general_state_mutex); + bool doUpdate = false; + + const uint8_t rsp1_lnastates[NUM_DEFAULT_GAIN_SETTINGS] = { + 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + const uint8_t rsp1_ifgains[NUM_DEFAULT_GAIN_SETTINGS] = { + 59, 56, 53, 50, 47, 44, 41, 58, 55, 52, 49, 46, 43, 45, 42, + 58, 55, 52, 49, 46, 43, 41, 38, 35, 32, 29, 26, 23, 20 + }; + const uint8_t rsp1a_lnastates[NUM_DEFAULT_GAIN_SETTINGS] = { + 9, 9, 9, 9, 9, 9, 8, 7, 7, 7, 7, 7, 6, 6, 5, + 5, 4, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 + }; + const uint8_t rsp1a_ifgains[NUM_DEFAULT_GAIN_SETTINGS] = { + 59, 55, 52, 48, 45, 41, 42, 58, 54, 51, 47, 43, 46, 42, 44, + 41, 43, 42, 44, 40, 43, 45, 42, 38, 34, 31, 27, 24, 20 + }; + const uint8_t rsp2_lnastates[NUM_DEFAULT_GAIN_SETTINGS] = { + 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 5, 5, 4, + 4, 4, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + const uint8_t rsp2_ifgains[NUM_DEFAULT_GAIN_SETTINGS] = { + 59, 55, 52, 48, 44, 41, 56, 52, 49, 45, 41, 44, 45, 41, 48, + 44, 40, 45, 42, 43, 49, 46, 42, 38, 35, 31, 27, 24, 20 + }; + const uint8_t rspduo_lnastates[NUM_DEFAULT_GAIN_SETTINGS] = { + 9, 9, 9, 9, 9, 9, 8, 7, 7, 7, 7, 7, 6, 6, 5, + 5, 4, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 + }; + const uint8_t rspduo_ifgains[NUM_DEFAULT_GAIN_SETTINGS] = { + 59, 55, 52, 48, 45, 41, 42, 58, 54, 51, 47, 43, 46, 42, 44, + 41, 43, 42, 44, 40, 43, 45, 42, 38, 34, 31, 27, 24, 20 + }; + const uint8_t rspdx_lnastates[NUM_DEFAULT_GAIN_SETTINGS] = { + 26, 26, 26, 26, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 11, + 10, 8, 7, 5, 5, 5, 3, 2, 0, 0, 0, 0, 0, 0 + }; + const uint8_t rspdx_ifgains[NUM_DEFAULT_GAIN_SETTINGS] = { + 59, 55, 50, 46, 41, 40, 42, 40, 42, 40, 42, 41, 42, 41, 43, + 41, 43, 41, 49, 45, 40, 42, 40, 42, 38, 33, 29, 24, 20 + }; + + int index = std::max(0, std::min(NUM_DEFAULT_GAIN_SETTINGS - 1, (int)value)); + int rfGR = 0; + int ifGR = 0; + + switch(device.hwVer) + { + case SDRPLAY_RSP1_ID: + rfGR = rsp1_lnastates[index]; + ifGR = rsp1_ifgains[index]; + break; + case SDRPLAY_RSP1A_ID: + rfGR = rsp1a_lnastates[index]; + ifGR = rsp1a_ifgains[index]; + break; + case SDRPLAY_RSP2_ID: + rfGR = rsp2_lnastates[index]; + ifGR = rsp2_ifgains[index]; + break; + case SDRPLAY_RSPduo_ID: + rfGR = rspduo_lnastates[index]; + ifGR = rspduo_ifgains[index]; + break; + case SDRPLAY_RSPdx_ID: + rfGR = rspdx_lnastates[index]; + ifGR = rspdx_ifgains[index]; + break; + } + + if (chParams->tunerParams.gain.gRdB != ifGR && chParams->ctrlParams.agc.enable == sdrplay_api_AGC_DISABLE) + { + chParams->tunerParams.gain.gRdB = ifGR; + doUpdate = true; + } + + if (chParams->tunerParams.gain.LNAstate != rfGR) + { + chParams->tunerParams.gain.LNAstate = rfGR; + doUpdate = true; + } + + if (doUpdate && streamActive) + { + sdrplay_api_Update(device.dev, device.tuner, sdrplay_api_Update_Tuner_Gr, + sdrplay_api_Update_Ext1_None); + } +} + +SoapySDR::Range SoapySDRPlay::getGainRange(const int direction, const size_t channel) const +{ + return NUM_DEFAULT_GAIN_SETTINGS; +} + void SoapySDRPlay::setGain(const int direction, const size_t channel, const std::string &name, const double value) { std::lock_guard lock(_general_state_mutex); bool doUpdate = false; - if (name == "IFGR" && chParams->ctrlParams.agc.enable == sdrplay_api_AGC_DISABLE) + if (chParams->ctrlParams.agc.enable == sdrplay_api_AGC_DISABLE) + { + if (name == "IFGR" || name == "IF") + { + return; + } + } + + if (name == "IF" || name == "IFGR") { - //apply the change if the required value is different from gRdB - if (chParams->tunerParams.gain.gRdB != (int)value) + int ifGR = (name == "IF") ? -value : value; + if (chParams->tunerParams.gain.gRdB != ifGR) { - chParams->tunerParams.gain.gRdB = (int)value; + chParams->tunerParams.gain.gRdB = ifGR; doUpdate = true; } } - else if (name == "RFGR") + else if (name == "RF" || name == "RFGR") { - if (chParams->tunerParams.gain.LNAstate != (int)value) { + int rfGR = (name == "RF") ? -value : value; + if (chParams->tunerParams.gain.LNAstate != rfGR) { - chParams->tunerParams.gain.LNAstate = (int)value; + chParams->tunerParams.gain.LNAstate = rfGR; doUpdate = true; } } - if ((doUpdate == true) && (streamActive)) + + if (doUpdate && streamActive) { - sdrplay_api_Update(device.dev, device.tuner, sdrplay_api_Update_Tuner_Gr, sdrplay_api_Update_Ext1_None); + sdrplay_api_Update(device.dev, device.tuner, sdrplay_api_Update_Tuner_Gr, + sdrplay_api_Update_Ext1_None); } } @@ -661,10 +798,18 @@ double SoapySDRPlay::getGain(const int direction, const size_t channel, const st { return chParams->tunerParams.gain.gRdB; } + else if (name == "IF") + { + return -(chParams->tunerParams.gain.gRdB); + } else if (name == "RFGR") { return chParams->tunerParams.gain.LNAstate; } + else if (name == "RF") + { + return -(chParams->tunerParams.gain.LNAstate); + } return 0; } @@ -675,27 +820,18 @@ SoapySDR::Range SoapySDRPlay::getGainRange(const int direction, const size_t cha { 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)) + else if (name == "IF") { - return SoapySDR::Range(0, 9); + return SoapySDR::Range(-59, -20); } - else if ((name == "RFGR") && (device.hwVer == SDRPLAY_RSP1A_ID)) + else if (name == "RFGR") { - return SoapySDR::Range(0, 9); + return SoapySDR::Range(0, getMaxRFGR(device.hwVer)); } - else if ((name == "RFGR") && (device.hwVer == SDRPLAY_RSPdx_ID)) + else // name == "RF" { - return SoapySDR::Range(0, 27); + return SoapySDR::Range(-getMaxRFGR(device.hwVer), 0); } - return SoapySDR::Range(20, 59); } /******************************************************************* @@ -1176,7 +1312,6 @@ SoapySDR::ArgInfoList SoapySDRPlay::getSettingInfo(void) const non_const_this->selectDevice(); } -#ifdef RF_GAIN_IN_MENU if (device.hwVer == SDRPLAY_RSP2_ID) { SoapySDR::ArgInfo RfGainArg; @@ -1288,7 +1423,7 @@ SoapySDR::ArgInfoList SoapySDRPlay::getSettingInfo(void) const RfGainArg.options.push_back("3"); setArgs.push_back(RfGainArg); } -#endif +//#endif SoapySDR::ArgInfo IQcorrArg; IQcorrArg.key = "iqcorr_ctrl"; @@ -1427,14 +1562,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") { 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") { if (value == "false") chParams->ctrlParams.dcOffset.IQenable = 0; @@ -1602,14 +1735,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") { 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..18a03fd 100644 --- a/SoapySDRPlay.hpp +++ b/SoapySDRPlay.hpp @@ -43,6 +43,8 @@ #define DEFAULT_NUM_BUFFERS (8) #define DEFAULT_ELEMS_PER_SAMPLE (2) +#define GAIN_STEPS (29) + class SoapySDRPlay: public SoapySDR::Device { public: @@ -144,12 +146,16 @@ class SoapySDRPlay: public SoapySDR::Device bool getGainMode(const int direction, const size_t channel) const; + void setGain(const int direction, const size_t channel, const double value); + void setGain(const int direction, const size_t channel, const std::string &name, const double value); double getGain(const int direction, const size_t channel, const std::string &name) 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 ******************************************************************/