diff options
author | Trung N Tran <trung.tran@ettus.com> | 2018-01-04 11:32:24 -0800 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2018-01-12 16:26:03 -0800 |
commit | 00402669d08b206f3b0367f5f4e3383d25e7944b (patch) | |
tree | 1ab5948382dde42f164499ce8e1cd68c3c4d959c /host/lib/usrp/dboard/magnesium | |
parent | 7ffea3746be77cf926db946987ee83d48a33c798 (diff) | |
download | uhd-00402669d08b206f3b0367f5f4e3383d25e7944b.tar.gz uhd-00402669d08b206f3b0367f5f4e3383d25e7944b.tar.bz2 uhd-00402669d08b206f3b0367f5f4e3383d25e7944b.zip |
mg: add facility that handle individual gain
-Create name for each gain/att element
-Create property tree entry for each gain and their handlers.
-Create gain profile that control how gain distributed.
Right now, it is either "default" or "manual".
Diffstat (limited to 'host/lib/usrp/dboard/magnesium')
5 files changed, 348 insertions, 12 deletions
diff --git a/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp b/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp index 72a708165..0d914636e 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp @@ -31,6 +31,9 @@ static const double AD9371_RX_GAIN_STEP = 0.5; static const double DSA_MIN_GAIN = 0; // dB static const double DSA_MAX_GAIN = 31.5; // dB static const double DSA_GAIN_STEP = 0.5; // db +static const double AMP_MIN_GAIN = 0; // dB +static const double AMP_MAX_GAIN = 10; // dB +static const double AMP_GAIN_STEP = 10;// dB static const double AD9371_MIN_TX_GAIN = 0.0; // dB static const double AD9371_MAX_TX_GAIN = 41.95; // dB static const double AD9371_TX_GAIN_STEP = 0.05; @@ -40,14 +43,27 @@ static const double ALL_RX_GAIN_STEP = 0.5; static const double ALL_TX_MIN_GAIN = 0.0; static const double ALL_TX_MAX_GAIN = 65.0; static const double ALL_TX_GAIN_STEP = 0.5; + static const double MAGNESIUM_CENTER_FREQ = 2.5e9; // Hz static const std::vector<std::string> MAGNESIUM_RX_ANTENNAS = { "TX/RX", "RX2", "CAL", "LOCAL" }; + //! AD9371 LO (for direct conversion) static const char* MAGNESIUM_LO1 = "rfic"; //! Low-band LO (for IF conversion) static const char* MAGNESIUM_LO2 = "lowband"; +//! Magnesium gain profile options +static const std::vector<std::string> MAGNESIUM_GP_OPTIONS = { + "manual", + "default" +}; +//! AD9371 attenuation +static const char* MAGNESIUM_GAIN1 = "rfic"; +//! DSA attenuation +static const char* MAGNESIUM_GAIN2 = "dsa"; +//! Amplifier gain +static const char* MAGNESIUM_AMP = "amp"; static const double MAGNESIUM_DEFAULT_BANDWIDTH = 40e6; // Hz TODO: fix // Note: MAGNESIUM_NUM_CHANS is independent of the number of chans per diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_gain.cpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_gain.cpp index 449b772b3..f934e5794 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_gain.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_gain.cpp @@ -28,9 +28,21 @@ double magnesium_radio_ctrl_impl::_set_all_gain( const size_t ad9371_chan = _master ? 0 : 1; ;// FIXME: use chan when 2 radios const magnesium_cpld_ctrl::chan_sel_t chan_sel = _master ? magnesium_cpld_ctrl::CHAN1 : magnesium_cpld_ctrl::CHAN2; - const auto gain_tuple = (dir == RX_DIRECTION) ? - get_rx_gain_tuple(gain, _map_freq_to_rx_band(freq)) : - get_tx_gain_tuple(gain, _map_freq_to_tx_band(freq)); + gain_tuple_t gain_tuple = (dir == RX_DIRECTION) ? + get_rx_gain_tuple(gain, _map_freq_to_rx_band(freq)): + get_tx_gain_tuple(gain, _map_freq_to_tx_band(freq)); + + if (_gain_profile[dir] == "manual"){ + UHD_LOG_TRACE(unique_id(), "Manual gain mode. Getting gain from property tree."); + gain_tuple = { + DSA_MAX_GAIN - _dsa_att[dir], + ((dir == RX_DIRECTION) ? AD9371_MAX_RX_GAIN : AD9371_MAX_TX_GAIN) - _ad9371_att[dir], + _amp_bypass[dir]}; + }else if (_gain_profile[dir] == "default"){ + UHD_LOG_TRACE(unique_id(), "Getting gain from gain table."); + }else { + UHD_LOG_ERROR(unique_id(), "Unsupported gain mode: " << _gain_profile[dir]) + } const double ad9371_gain = ((dir == RX_DIRECTION) ? AD9371_MAX_RX_GAIN : AD9371_MAX_TX_GAIN) - gain_tuple.ad9371_att; diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp index 2c7121c5c..eb4894e19 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp @@ -412,6 +412,50 @@ double magnesium_radio_ctrl_impl::set_tx_gain( return coerced_gain; } +double magnesium_radio_ctrl_impl::_set_tx_gain( + const std::string &name, + const double gain, + const size_t chan +) { + std::lock_guard<std::mutex> l(_set_lock); + UHD_LOG_TRACE(unique_id(), + "_set_tx_gain(name=" << name << ", gain=" << gain << ", chan=" << chan << ")"); + if (name == MAGNESIUM_GAIN1){ + _ad9371_att[TX_DIRECTION] = gain; + }else if (name == MAGNESIUM_GAIN2){ + _dsa_att[TX_DIRECTION] = gain; + }else if (name == MAGNESIUM_AMP){ + _amp_bypass[TX_DIRECTION] = gain == 0.0; + }else { + throw uhd::value_error("Could not find gain element " + name); + } + UHD_LOG_TRACE(unique_id(), + "_set_tx_gain calling update gain"); + this->_set_all_gain( + this->_get_all_gain(chan, TX_DIRECTION), + this->get_tx_frequency(chan), + chan, + TX_DIRECTION + ); + return gain; // not really any coreced here for individual gain +} + +double magnesium_radio_ctrl_impl::_get_tx_gain( + const std::string &name, + const size_t chan +) { + std::lock_guard<std::mutex> l(_set_lock); + if (name == MAGNESIUM_GAIN1){ + return _ad9371_att[TX_DIRECTION]; + }else if (name == MAGNESIUM_GAIN2){ + return _dsa_att[TX_DIRECTION]; + }else if (name == MAGNESIUM_AMP){ + return _amp_bypass[TX_DIRECTION]? AMP_MIN_GAIN : AMP_MAX_GAIN; + }else { + throw uhd::value_error("Could not find gain element " + name); + } +} + double magnesium_radio_ctrl_impl::set_rx_gain( const double gain, const size_t chan @@ -429,6 +473,51 @@ double magnesium_radio_ctrl_impl::set_rx_gain( return coerced_gain; } +double magnesium_radio_ctrl_impl::_set_rx_gain( + const std::string &name, + const double gain, + const size_t chan +) { + std::lock_guard<std::mutex> l(_set_lock); + UHD_LOG_TRACE(unique_id(), + "_set_rx_gain(name=" << name << ", gain=" << gain << ", chan=" << chan << ")"); + if (name == MAGNESIUM_GAIN1){ + _ad9371_att[RX_DIRECTION] = gain; + }else if (name == MAGNESIUM_GAIN2){ + _dsa_att[RX_DIRECTION] = gain; + }else if (name == MAGNESIUM_AMP){ + _amp_bypass[RX_DIRECTION] = gain == 0.0; + }else { + throw uhd::value_error("Could not find gain element " + name); + } + UHD_LOG_TRACE(unique_id(), + "_set_rx_gain calling update gain"); + this->_set_all_gain( + this->_get_all_gain(chan, RX_DIRECTION), + this->get_rx_frequency(chan), + chan, + RX_DIRECTION + ); + return gain; // not really any coreced here for individual gain +} + +double magnesium_radio_ctrl_impl::_get_rx_gain( + const std::string &name, + const size_t chan +) { + std::lock_guard<std::mutex> l(_set_lock); + + if (name == MAGNESIUM_GAIN1){ + return _ad9371_att[RX_DIRECTION]; + }else if (name == MAGNESIUM_GAIN2){ + return _dsa_att[RX_DIRECTION]; + }else if (name == MAGNESIUM_AMP){ + return _amp_bypass[RX_DIRECTION]? AMP_MIN_GAIN : AMP_MAX_GAIN; + }else{ + throw uhd::value_error("Could not find gain element " + name); + } +} + std::vector<std::string> magnesium_radio_ctrl_impl::get_rx_lo_names( const size_t /*chan*/ ) { diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp index 49affaa6f..d12666ce7 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp @@ -134,6 +134,10 @@ public: // gain double set_tx_gain(const double gain, const size_t chan); double set_rx_gain(const double gain, const size_t chan); + void set_tx_gain_source(const std::string& src, const std::string& name, const size_t chan); + std::string get_tx_gain_source(const std::string& name, const size_t chan); + void set_rx_gain_source(const std::string& src, const std::string& name, const size_t chan); + std::string get_rx_gain_source(const std::string& name, const size_t chan); size_t get_chan_from_dboard_fe(const std::string &fe, const direction_t dir); std::string get_dboard_fe_from_chan(const size_t chan, const direction_t dir); @@ -147,6 +151,18 @@ private: /************************************************************************** * Helpers *************************************************************************/ + //! Set tx gain on each gain element + double _set_tx_gain(const std::string &name, const double gain, const size_t chan); + + //! Set rx gain on each gain element + double _set_rx_gain(const std::string &name, const double gain, const size_t chan); + + //! Get tx gain on each gain element + double _get_tx_gain(const std::string &name, const size_t chan); + + //! Get rx gain on each gain element + double _get_rx_gain(const std::string &name, const size_t chan); + //! Initialize all the peripherals connected to this block void _init_peripherals(); @@ -328,14 +344,18 @@ private: //! AD9371 gain double _ad9371_rx_gain = 0.0; double _ad9371_tx_gain = 0.0; - + std::map<direction_t,double> _ad9371_att = { {RX_DIRECTION, 0.0}, {TX_DIRECTION, 0.0} }; //! DSA attenuation double _dsa_rx_att = 0.0; double _dsa_tx_att = 0.0; - + std::map<direction_t,double> _dsa_att = { {RX_DIRECTION, 0.0}, {TX_DIRECTION, 0.0} }; + //! amp gain + std::map<direction_t,bool> _amp_bypass = { {RX_DIRECTION, true}, {TX_DIRECTION, true} }; //! All gain double _all_rx_gain = 0.0; double _all_tx_gain = 0.0; + //! Gain profile + std::map<direction_t,std::string> _gain_profile = { {RX_DIRECTION, "default"}, {TX_DIRECTION, "default"} }; bool _rx_bypass_lnas = true; bool _tx_bypass_amp = true; diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp index 5858995b0..5eb3cacd0 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp @@ -315,33 +315,232 @@ void magnesium_radio_ctrl_impl::_init_frontend_subtree( return this->set_tx_gain(gain, chan_idx); }) .set_publisher([this, chan_idx](){ - return this->get_tx_gain(chan_idx); + return radio_ctrl_impl::get_tx_gain(chan_idx); }) ; subtree->create<meta_range_t>(tx_fe_path / "gains" / "all" / "range") - .set(meta_range_t(ALL_TX_MIN_GAIN, ALL_TX_MAX_GAIN, ALL_TX_GAIN_STEP)) .add_coerced_subscriber([](const meta_range_t &){ throw uhd::runtime_error( - "Attempting to update bandwidth range!"); + "Attempting to update gain range!"); + }) + .set_publisher([this, chan_idx](){ + if (_gain_profile[TX_DIRECTION] == "manual") { + return meta_range_t(0.0, 0.0, 0.0); + }else{ + return meta_range_t(ALL_TX_MIN_GAIN, ALL_TX_MAX_GAIN, ALL_TX_GAIN_STEP); + } }) ; + + subtree->create<std::vector<std::string> >(tx_fe_path / "gains/all/profile/options") + .set(boost::assign::list_of("manual")("default")); + + subtree->create<std::string>(tx_fe_path / "gains/all/profile/value") + .set_coercer([this, chan_idx](const std::string& profile){ + std::string return_profile = profile; + if (std::find(MAGNESIUM_GP_OPTIONS.begin(), + MAGNESIUM_GP_OPTIONS.end(), + profile + ) == MAGNESIUM_GP_OPTIONS.end()) + { + return_profile = "default"; + } + _gain_profile[TX_DIRECTION] = return_profile; + return return_profile; + }) + .set_publisher([this, chan_idx](){ + return _gain_profile[TX_DIRECTION]; + }) + ; + // RX gains subtree->create<double>(rx_fe_path / "gains" / "all" / "value") .set_coercer([this, chan_idx](const double gain){ return this->set_rx_gain(gain, chan_idx); }) .set_publisher([this, chan_idx](){ - return this->get_rx_gain(chan_idx); + return radio_ctrl_impl::get_rx_gain(chan_idx); }) ; + subtree->create<meta_range_t>(rx_fe_path / "gains" / "all" / "range") - .set(meta_range_t(ALL_RX_MIN_GAIN, ALL_RX_MAX_GAIN, ALL_RX_GAIN_STEP)) .add_coerced_subscriber([](const meta_range_t &){ throw uhd::runtime_error( - "Attempting to update bandwidth range!"); + "Attempting to update gain range!"); + }) + .set_publisher([this, chan_idx](){ + if (_gain_profile[RX_DIRECTION] == "manual") { + return meta_range_t(0.0, 0.0, 0.0); + }else{ + return meta_range_t(ALL_RX_MIN_GAIN, ALL_RX_MAX_GAIN, ALL_RX_GAIN_STEP); + } + }) + ; + + subtree->create<std::vector<std::string> >(rx_fe_path / "gains/all/profile/options") + .set(MAGNESIUM_GP_OPTIONS); + + subtree->create<std::string>(rx_fe_path / "gains/all/profile/value") + .set_coercer([this, chan_idx](const std::string& profile){ + std::string return_profile = profile; + if (std::find(MAGNESIUM_GP_OPTIONS.begin(), + MAGNESIUM_GP_OPTIONS.end(), + profile + ) == MAGNESIUM_GP_OPTIONS.end()) + { + return_profile = "default"; + } + _gain_profile[RX_DIRECTION] = return_profile; + return return_profile; + }) + .set_publisher([this, chan_idx](){ + return _gain_profile[RX_DIRECTION]; }) ; - // FIXME separate DSA and Myk gains + + // TX mykonos attenuation + subtree->create<double>(tx_fe_path / "gains" / MAGNESIUM_GAIN1 / "value") + .set_coercer([this, chan_idx](const double gain){ + return _set_tx_gain(MAGNESIUM_GAIN1, gain, chan_idx); + }) + .set_publisher([this, chan_idx](){ + return this->_get_tx_gain(MAGNESIUM_GAIN1, chan_idx); + }) + ; + + subtree->create<meta_range_t>(tx_fe_path / "gains" / MAGNESIUM_GAIN1 / "range") + .add_coerced_subscriber([](const meta_range_t &){ + throw uhd::runtime_error( + "Attempting to update gain range!"); + }) + .set_publisher([this, chan_idx](){ + if (_gain_profile[TX_DIRECTION] == "manual") { + return meta_range_t(AD9371_MIN_TX_GAIN, AD9371_MAX_TX_GAIN, AD9371_TX_GAIN_STEP); + }else{ + return meta_range_t(0.0, 0.0, 0.0); + } + }) + ; + // TX DSA + subtree->create<double>(tx_fe_path / "gains" / MAGNESIUM_GAIN2 / "value") + .set_coercer([this, chan_idx](const double gain){ + return this->_set_tx_gain(MAGNESIUM_GAIN2, gain, chan_idx); + }) + .set_publisher([this, chan_idx](){ + return this->_get_tx_gain(MAGNESIUM_GAIN2, chan_idx); + }) + ; + + subtree->create<meta_range_t>(tx_fe_path / "gains" / MAGNESIUM_GAIN2 / "range") + .add_coerced_subscriber([](const meta_range_t &){ + throw uhd::runtime_error( + "Attempting to update gain range!"); + }) + .set_publisher([this, chan_idx](){ + if (_gain_profile[TX_DIRECTION] == "manual") { + return meta_range_t(DSA_MIN_GAIN, DSA_MAX_GAIN, DSA_GAIN_STEP); + }else{ + return meta_range_t(0.0, 0.0, 0.0); + } + }) + ; + //TX amp + subtree->create<double>(tx_fe_path / "gains" / MAGNESIUM_AMP / "value") + .set_coercer([this, chan_idx](const double gain) { + return this->_set_tx_gain(MAGNESIUM_AMP, gain, chan_idx); + }) + .set_publisher([this, chan_idx]() { + return this->_get_tx_gain(MAGNESIUM_AMP, chan_idx); + }) + ; + + subtree->create<meta_range_t>(tx_fe_path / "gains" / MAGNESIUM_AMP / "range") + .add_coerced_subscriber([](const meta_range_t &) { + throw uhd::runtime_error( + "Attempting to update gain range!"); + }) + .set_publisher([this, chan_idx](){ + if (_gain_profile[TX_DIRECTION] == "manual") { + return meta_range_t(AMP_MIN_GAIN, AMP_MAX_GAIN, AMP_GAIN_STEP); + }else{ + return meta_range_t(0.0, 0.0, 0.0); + } + }) + ; + + // RX mykonos attenuation + subtree->create<double>(rx_fe_path / "gains" / MAGNESIUM_GAIN1 / "value") + .set_coercer([this, chan_idx](const double gain){ + UHD_VAR(gain); + return this->_set_rx_gain(MAGNESIUM_GAIN1, gain, chan_idx); + }) + .set_publisher([this, chan_idx](){ + return this->_get_rx_gain(MAGNESIUM_GAIN1, chan_idx); + }) + ; + + subtree->create<meta_range_t>(rx_fe_path / "gains" / MAGNESIUM_GAIN1 / "range") + .add_coerced_subscriber([](const meta_range_t &) { + throw uhd::runtime_error( + "Attempting to update gain range!"); + }) + .set_publisher([this, chan_idx](){ + if (_gain_profile[RX_DIRECTION] == "manual") { + return meta_range_t(AD9371_MIN_RX_GAIN, AD9371_MAX_RX_GAIN, AD9371_RX_GAIN_STEP); + }else{ + return meta_range_t(0.0, 0.0, 0.0); + } + }) + ; + //RX DSA + subtree->create<double>(rx_fe_path / "gains" / MAGNESIUM_GAIN2 / "value") + .set_coercer([this, chan_idx](const double gain) { + UHD_VAR(gain); + return this->_set_rx_gain(MAGNESIUM_GAIN2, gain, chan_idx); + }) + .set_publisher([this, chan_idx]() { + return this->_get_rx_gain(MAGNESIUM_GAIN2, chan_idx); + }) + ; + + subtree->create<meta_range_t>(rx_fe_path / "gains" / MAGNESIUM_GAIN2 / "range") + .add_coerced_subscriber([](const meta_range_t &){ + throw uhd::runtime_error( + "Attempting to update gain range!"); + }) + .set_publisher([this, chan_idx](){ + if (_gain_profile[RX_DIRECTION] == "manual") { + return meta_range_t(DSA_MIN_GAIN, DSA_MAX_GAIN, DSA_MAX_GAIN); + }else{ + return meta_range_t(0.0, 0.0, 0.0); + } + }) + ; + + //RX amp + subtree->create<double>(rx_fe_path / "gains" / MAGNESIUM_AMP / "value") + .set_coercer([this, chan_idx](const double gain) { + return this->_set_rx_gain(MAGNESIUM_AMP, gain, chan_idx); + }) + .set_publisher([this, chan_idx]() { + return this->_get_rx_gain(MAGNESIUM_AMP, chan_idx); + }) + ; + + subtree->create<meta_range_t>(rx_fe_path / "gains" / MAGNESIUM_AMP / "range") + .add_coerced_subscriber([](const meta_range_t &) { + throw uhd::runtime_error( + "Attempting to update gain range!"); + }) + .set_publisher([this, chan_idx](){ + if (_gain_profile[RX_DIRECTION] == "manual") { + return meta_range_t(AMP_MIN_GAIN, AMP_MAX_GAIN, AMP_GAIN_STEP); + }else{ + return meta_range_t(0.0, 0.0, 0.0); + } + }) + ; + // TX LO lock sensor ////////////////////////////////////////////////////// // Note: The lowband and AD9371 LO lock sensors are generated // programmatically in set_rpc_client(). The actual lo_locked publisher is |