diff options
author | Martin Braun <martin.braun@ettus.com> | 2019-01-30 14:41:00 +0100 |
---|---|---|
committer | michael-west <michael.west@ettus.com> | 2019-02-18 11:03:09 -0800 |
commit | 85ec2704384c09da8913f58f94b6a3ee6a007ba5 (patch) | |
tree | 8e0db689f61764ac5b6371dfb14e8a84a01eeb33 | |
parent | b81b4aaeaf3187ffcc69513f83ef9651b8e27b18 (diff) | |
download | uhd-85ec2704384c09da8913f58f94b6a3ee6a007ba5.tar.gz uhd-85ec2704384c09da8913f58f94b6a3ee6a007ba5.tar.bz2 uhd-85ec2704384c09da8913f58f94b6a3ee6a007ba5.zip |
x300: Enable ADC gain through RFNoC API
The RFNoC call set_rx_gain() would previously ignore the additional 6 dB
that can be set on the ADC. On the BasicRX board in particular, this
meant there was no RX gain setting at all.
-rw-r--r-- | host/lib/usrp/x300/x300_radio_ctrl_impl.cpp | 107 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_radio_ctrl_impl.hpp | 5 |
2 files changed, 83 insertions, 29 deletions
diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp index 76971a76e..b61e64800 100644 --- a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp +++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp @@ -29,6 +29,23 @@ using namespace uhd::usrp::x300; static const size_t IO_MASTER_RADIO = 0; +namespace { + +gain_fcns_t make_gain_fcns_from_subtree(property_tree::sptr subtree) +{ + gain_fcns_t gain_fcns; + gain_fcns.get_range = [subtree]() { + return subtree->access<meta_range_t>("range").get(); + }; + gain_fcns.get_value = [subtree]() { return subtree->access<double>("value").get(); }; + gain_fcns.set_value = [subtree](const double gain) { + subtree->access<double>("value").set(gain); + }; + return gain_fcns; +} + +} // namespace + /**************************************************************************** * Structors ***************************************************************************/ @@ -325,42 +342,25 @@ double x300_radio_ctrl_impl::get_rx_bandwidth(const size_t chan) double x300_radio_ctrl_impl::set_tx_gain(const double gain, const size_t chan) { - // TODO: This is extremely hacky! - fs_path path("dboards" / _radio_slot / "tx_frontends" / _tx_fe_map.at(chan).db_fe_name - / "gains"); - std::vector<std::string> gain_stages = _tree->list(path); - if (gain_stages.size() == 1) { - const double actual_gain = - _tree->access<double>(path / gain_stages[0] / "value").set(gain).get(); - radio_ctrl_impl::set_tx_gain(actual_gain, chan); - return gain; - } else { - UHD_LOGGER_WARNING("X300 RADIO") - << "set_tx_gain: could not apply gain for this daughterboard."; - radio_ctrl_impl::set_tx_gain(0.0, chan); - return 0.0; + if (_tx_gain_groups.count(chan)) { + auto& gg = _tx_gain_groups.at(chan); + gg->set_value(gain); + return radio_ctrl_impl::set_tx_gain(gg->get_value(), chan); } + return radio_ctrl_impl::set_tx_gain(0.0, chan); } double x300_radio_ctrl_impl::set_rx_gain(const double gain, const size_t chan) { - // TODO: This is extremely hacky! - fs_path path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name - / "gains"); - std::vector<std::string> gain_stages = _tree->list(path); - if (gain_stages.size() == 1) { - const double actual_gain = - _tree->access<double>(path / gain_stages[0] / "value").set(gain).get(); - radio_ctrl_impl::set_rx_gain(actual_gain, chan); - return gain; - } else { - UHD_LOGGER_WARNING("X300 RADIO") - << "set_rx_gain: could not apply gain for this daughterboard."; - radio_ctrl_impl::set_tx_gain(0.0, chan); - return 0.0; - } + auto& gg = _rx_gain_groups.at(chan); + gg->set_value(gain); + return radio_ctrl_impl::set_rx_gain(gg->get_value(), chan); } +double x300_radio_ctrl_impl::get_rx_gain(const size_t chan) +{ + return _rx_gain_groups.at(chan)->get_value(); +} std::vector<std::string> x300_radio_ctrl_impl::get_rx_lo_names(const size_t chan) { @@ -905,6 +905,55 @@ void x300_radio_ctrl_impl::setup_radio(uhd::i2c_iface::sptr zpu_i2c, //////////////////////////////////////////////////////////////// const double tick_rate = _tree->access<double>("tick_rate").get(); radio_ctrl_impl::set_rate(tick_rate); + + //////////////////////////////////////////////////////////////// + // Set gain groups + // Note: The actual gain control comes from the daughterboard drivers, thus, + // we need to call into the prop tree at the appropriate location in order + // to modify the gains. + //////////////////////////////////////////////////////////////// + // TX + for (size_t chan = 0; chan < _num_tx_channels; chan++) { + fs_path rf_gains_path(db_tx_fe_path / _tx_fe_map.at(chan).db_fe_name / "gains"); + if (!_tree->exists(rf_gains_path)) { + continue; + } + + std::vector<std::string> gain_stages = _tree->list(rf_gains_path); + if (gain_stages.empty()) { + continue; + } + + // DAC does not have a gain path + auto gg = gain_group::make(); + for (const auto& name : gain_stages) { + gg->register_fcns(name, + make_gain_fcns_from_subtree(_tree->subtree(rf_gains_path / name)), + 1 /* high prio */); + } + _tx_gain_groups[chan] = gg; + } + // RX + for (size_t chan = 0; chan < _num_rx_channels; chan++) { + fs_path rf_gains_path(db_rx_fe_path / _rx_fe_map.at(chan).db_fe_name / "gains"); + fs_path adc_gains_path("rx_codecs" / _radio_slot / "gains"); + + auto gg = gain_group::make(); + // ADC also has a gain path + for (const auto& name : _tree->list(adc_gains_path)) { + gg->register_fcns("ADC-" + name, + make_gain_fcns_from_subtree(_tree->subtree(adc_gains_path / name)), + 0 /* low prio */); + } + if (_tree->exists(rf_gains_path)) { + for (const auto& name : _tree->list(rf_gains_path)) { + gg->register_fcns(name, + make_gain_fcns_from_subtree(_tree->subtree(rf_gains_path / name)), + 1 /* high prio */); + } + } + _rx_gain_groups[chan] = gg; + } } void x300_radio_ctrl_impl::set_rx_fe_corrections( diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp index 7cc0ea18d..63aac876d 100644 --- a/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp +++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp @@ -15,10 +15,12 @@ #include <uhd/usrp/dboard_eeprom.hpp> #include <uhd/usrp/dboard_manager.hpp> #include <uhd/usrp/gpio_defs.hpp> +#include <uhd/utils/gain_group.hpp> #include <uhdlib/rfnoc/radio_ctrl_impl.hpp> #include <uhdlib/usrp/cores/rx_frontend_core_3000.hpp> #include <uhdlib/usrp/cores/spi_core_3000.hpp> #include <uhdlib/usrp/cores/tx_frontend_core_200.hpp> +#include <unordered_map> namespace uhd { namespace rfnoc { @@ -54,6 +56,7 @@ public: double set_tx_gain(const double gain, const size_t chan); double set_rx_gain(const double gain, const size_t chan); + double get_rx_gain(const size_t chan); std::vector<std::string> get_rx_lo_names(const size_t chan); std::vector<std::string> get_rx_lo_sources( @@ -234,6 +237,8 @@ private: // members bool _ignore_cal_file; + std::unordered_map<size_t, uhd::gain_group::sptr> _tx_gain_groups; + std::unordered_map<size_t, uhd::gain_group::sptr> _rx_gain_groups; }; /* class radio_ctrl_impl */ }} /* namespace uhd::rfnoc */ |