From b43ab2705bdd3a26d5bff012cfd54fbf6775ffb9 Mon Sep 17 00:00:00 2001 From: Mark Meserve Date: Fri, 1 Sep 2017 15:21:29 -0700 Subject: N310: Updated controls for Mg daughterboard - Adds most API calls - Adds prop tree nodes --- host/include/uhd/rfnoc/blocks/radio_magnesium.xml | 12 - .../dboard/magnesium/magnesium_radio_ctrl_impl.cpp | 267 ++++++++++++++++----- .../dboard/magnesium/magnesium_radio_ctrl_impl.hpp | 26 +- 3 files changed, 234 insertions(+), 71 deletions(-) diff --git a/host/include/uhd/rfnoc/blocks/radio_magnesium.xml b/host/include/uhd/rfnoc/blocks/radio_magnesium.xml index a67e2722f..aa9ae5a6a 100644 --- a/host/include/uhd/rfnoc/blocks/radio_magnesium.xml +++ b/host/include/uhd/rfnoc/blocks/radio_magnesium.xml @@ -37,24 +37,12 @@ - - in1 - sc16 - - - out0 sc16 - - out1 - sc16 - - - 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 cc51562aa..53d1f7dab 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -31,8 +32,18 @@ using namespace uhd::usrp; using namespace uhd::rfnoc; static const size_t IO_MASTER_RADIO = 0; + +// TODO: some of these values are duplicated in ad937x_device.cpp static const double MAGNESIUM_TICK_RATE = 125e6; // Hz static const double MAGNESIUM_RADIO_RATE = 125e6; // Hz +static const double MAGNESIUM_MIN_FREQ = 300e6; // Hz +static const double MAGNESIUM_MAX_FREQ = 6e9; // Hz +static const double MAGNESIUM_MIN_RX_GAIN = 0.0; // dB +static const double MAGNESIUM_MAX_RX_GAIN = 30.0; // dB +static const double MAGNESIUM_RX_GAIN_STEP = 0.5; +static const double MAGNESIUM_MIN_TX_GAIN = 0.0; // dB +static const double MAGNESIUM_MAX_TX_GAIN = 41.95; // dB +static const double MAGNESIUM_TX_GAIN_STEP = 0.05; static const double MAGNESIUM_CENTER_FREQ = 2.5e9; // Hz static const double MAGNESIUM_DEFAULT_GAIN = 0.0; // dB static const double MAGNESIUM_DEFAULT_BANDWIDTH = 40e6; // Hz TODO: fix @@ -69,6 +80,19 @@ std::string _get_which(direction_t dir, size_t chan) return ss.str(); } +fs_path magnesium_radio_ctrl_impl::_get_fe_path(size_t chan, direction_t dir) +{ + switch (dir) + { + case TX_DIRECTION: + return fs_path("dboards" / _radio_slot / "tx_frontends" / get_dboard_fe_from_chan(chan, TX_DIRECTION)); + case RX_DIRECTION: + return fs_path("dboards" / _radio_slot / "rx_frontends" / get_dboard_fe_from_chan(chan, RX_DIRECTION)); + default: + UHD_THROW_INVALID_CODE_PATH(); + } +} + UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(magnesium_radio_ctrl) { UHD_LOG_TRACE("MAGNESIUM", "magnesium_radio_ctrl_impl::ctor() "); @@ -78,9 +102,9 @@ UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(magnesium_radio_ctrl) const size_t num_rx_chans = get_output_ports().size(); - UHD_ASSERT_THROW(num_rx_chans == MAGNESIUM_NUM_RX_CHANS); + //UHD_ASSERT_THROW(num_rx_chans == MAGNESIUM_NUM_RX_CHANS); const size_t num_tx_chans = get_input_ports().size(); - UHD_ASSERT_THROW(num_tx_chans == MAGNESIUM_NUM_TX_CHANS); + //UHD_ASSERT_THROW(num_tx_chans == MAGNESIUM_NUM_TX_CHANS); UHD_LOG_TRACE("MAGNESIUM", "Setting tick rate to " << MAGNESIUM_TICK_RATE / 1e6 << " MHz"); radio_ctrl_impl::set_rate(MAGNESIUM_TICK_RATE); @@ -104,56 +128,104 @@ UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(magnesium_radio_ctrl) // For use with multi_usrp APIs etc. // For legacy prop tree init: // TODO: determine DB number - fs_path fe_base = fs_path("dboards") / _radio_slot; - std::vector fe({ "rx_frontends" , "tx_frontends" }); - std::vector ant({ "RX" , "TX" }); + const fs_path fe_base = fs_path("dboards") / _radio_slot; + const std::vector dir({ RX_DIRECTION, TX_DIRECTION }); + const std::vector fe({ "rx_frontends", "tx_frontends" }); + const std::vector ant({ "RX" , "TX" }); + const std::vector num_chans({ MAGNESIUM_NUM_RX_CHANS , MAGNESIUM_NUM_TX_CHANS }); + const size_t RX_IDX = 0, TX_IDX = 1; - UHD_ASSERT_THROW(MAGNESIUM_NUM_RX_CHANS == MAGNESIUM_NUM_TX_CHANS); for (size_t fe_idx = 0; fe_idx < fe.size(); ++fe_idx) { - fs_path fe_direction_path = fe_base / fe[fe_idx]; - for (size_t chan = 0; chan < MAGNESIUM_NUM_RX_CHANS; ++chan) { - fs_path fe_path = fe_direction_path / chan; + const fs_path fe_direction_path = fe_base / fe[fe_idx]; + for (size_t chan = 0; chan < num_chans[fe_idx]; ++chan) + { + const fs_path fe_path = fe_direction_path / chan; UHD_LOG_TRACE("MAGNESIUM", "Adding FE at " << fe_path); + // Shared TX/RX attributes _tree->create(fe_path / "name") .set(str(boost::format("Magnesium %s %d") % ant[fe_idx] % chan)) ; _tree->create(fe_path / "connection") .set("IQ") ; - // TODO: fix antenna name - _tree->create(fe_path / "antenna" / "value") - .set(str(boost::format("%s%d") % ant[fe_idx] % (chan+1))) - .add_coerced_subscriber(boost::bind(&magnesium_radio_ctrl_impl::set_rx_antenna, this, _1, chan)) - .set_publisher(boost::bind(&radio_ctrl_impl::get_rx_antenna, this, chan)) - ; - _tree->create>(fe_path / "antenna" / "options") - .set(std::vector(1, str(boost::format("%s%d") % ant[fe_idx] % (chan + 1)))) - ; - _tree->create(fe_path / "freq" / "value") - .set(MAGNESIUM_CENTER_FREQ) - .set_coercer(boost::bind(&magnesium_radio_ctrl_impl::set_rx_frequency, this, _1, chan)) - .set_publisher(boost::bind(&radio_ctrl_impl::get_rx_frequency, this, chan)) - ; - _tree->create(fe_path / "freq" / "range") - .set(meta_range_t(MAGNESIUM_CENTER_FREQ, MAGNESIUM_CENTER_FREQ)) - ; - _tree->create(fe_path / "gains" / "null" / "value") - .set(MAGNESIUM_DEFAULT_GAIN) - .set_coercer(boost::bind(&magnesium_radio_ctrl_impl::set_rx_gain, this, _1, chan)) - .set_publisher(boost::bind(&radio_ctrl_impl::get_rx_gain, this, chan)) - ; - _tree->create(fe_path / "gains" / "null" / "range") - .set(meta_range_t(MAGNESIUM_DEFAULT_GAIN, MAGNESIUM_DEFAULT_GAIN)) - ; - _tree->create(fe_path / "bandwidth" / "value") - .set(MAGNESIUM_DEFAULT_BANDWIDTH) - .set_coercer(boost::bind(&magnesium_radio_ctrl_impl::set_rx_bandwidth, this, _1, chan)) - .set_publisher(boost::bind(&radio_ctrl_impl::get_rx_bandwidth, this, chan)) - ; + { + // TODO: fix antenna name + // Now witness the firepower of this fully armed and operational lambda + auto coerced_lambda = [this, chan, dir = dir[fe_idx]](const std::string &ant) + { + return this->_set_antenna(ant, chan, dir); + }; + auto publisher_lambda = [this, chan, dir = dir[fe_idx]]() + { + return this->_get_antenna(chan, dir); + }; + _tree->create(fe_path / "antenna" / "value") + .set(str(boost::format("%s%d") % ant[fe_idx] % (chan + 1))) + .add_coerced_subscriber(coerced_lambda) + .set_publisher(publisher_lambda); + // TODO: fix options + _tree->create>(fe_path / "antenna" / "options") + .set(std::vector(1, str(boost::format("%s%d") % ant[fe_idx] % (chan + 1)))); + } + { + auto coerced_lambda = [this, chan, dir = dir[fe_idx]](const double freq) + { + return this->_set_frequency(freq, chan, dir); + }; + auto publisher_lambda = [this, chan, dir = dir[fe_idx]]() + { + return this->_get_frequency(chan, dir); + }; + _tree->create(fe_path / "freq" / "value") + .set(MAGNESIUM_CENTER_FREQ) + .set_coercer(coerced_lambda) + .set_publisher(publisher_lambda); + _tree->create(fe_path / "freq" / "range") + .set(meta_range_t(MAGNESIUM_MIN_FREQ, MAGNESIUM_MAX_FREQ)); + } + { + auto coerced_lambda = [this, chan, dir = dir[fe_idx]](const double gain) + { + return this->_set_gain(gain, chan, dir); + }; + auto publisher_lambda = [this, chan, dir = dir[fe_idx]]() + { + return this->_get_gain(chan, dir); + }; + auto min_gain = (fe_idx == RX_IDX) ? MAGNESIUM_MIN_RX_GAIN : MAGNESIUM_MIN_TX_GAIN; + auto max_gain = (fe_idx == RX_IDX) ? MAGNESIUM_MAX_RX_GAIN : MAGNESIUM_MAX_TX_GAIN; + auto gain_step = (fe_idx == RX_IDX) ? MAGNESIUM_RX_GAIN_STEP : MAGNESIUM_TX_GAIN_STEP; + // TODO: change from null + _tree->create(fe_path / "gains" / "null" / "value") + .set(MAGNESIUM_DEFAULT_GAIN) + .set_coercer(coerced_lambda) + .set_publisher(publisher_lambda); + _tree->create(fe_path / "gains" / "null" / "range") + .set(meta_range_t(min_gain, max_gain, gain_step)); + } + // TODO: set up read/write of bandwidth properties correctly + if (fe_idx == RX_IDX) + { + auto coerced_lambda = [this, chan](const double bw) + { + return this->set_rx_bandwidth(bw, chan); + }; + auto publisher_lambda = [this, chan]() + { + return this->get_rx_bandwidth(chan); + }; + _tree->create(fe_path / "bandwidth" / "value") + .set(MAGNESIUM_DEFAULT_BANDWIDTH) + .set_coercer(coerced_lambda) + .set_publisher(publisher_lambda); + } + else { + _tree->create(fe_path / "bandwidth" / "value") + .set(MAGNESIUM_DEFAULT_BANDWIDTH); + } _tree->create(fe_path / "bandwidth" / "range") - .set(meta_range_t(MAGNESIUM_DEFAULT_BANDWIDTH, MAGNESIUM_DEFAULT_BANDWIDTH)) - ; + .set(meta_range_t(MAGNESIUM_DEFAULT_BANDWIDTH, MAGNESIUM_DEFAULT_BANDWIDTH)); } } @@ -187,32 +259,27 @@ double magnesium_radio_ctrl_impl::set_rate(double rate) void magnesium_radio_ctrl_impl::set_tx_antenna(const std::string &ant, const size_t chan) { - // TODO: implement - UHD_LOG_WARNING("MAGNESIUM", "Ignoring attempt to set Tx antenna"); - // CPLD control? + _set_antenna(ant, chan, TX_DIRECTION); } void magnesium_radio_ctrl_impl::set_rx_antenna(const std::string &ant, const size_t chan) { - // TODO: implement - UHD_LOG_WARNING("MAGNESIUM", "Ignoring attempt to set Rx antenna"); - // CPLD control? + _set_antenna(ant, chan, RX_DIRECTION); } double magnesium_radio_ctrl_impl::set_tx_frequency(const double freq, const size_t chan) { - return _set_freq(freq, chan, TX_DIRECTION); + return _set_frequency(freq, chan, TX_DIRECTION); } double magnesium_radio_ctrl_impl::set_rx_frequency(const double freq, const size_t chan) { - return _set_freq(freq, chan, RX_DIRECTION); + return _set_frequency(freq, chan, RX_DIRECTION); } double magnesium_radio_ctrl_impl::set_rx_bandwidth(const double bandwidth, const size_t chan) { - // TODO: implement - return get_rx_bandwidth(chan); + return _set_bandwidth(bandwidth, chan, RX_DIRECTION); } double magnesium_radio_ctrl_impl::set_tx_gain(const double gain, const size_t chan) @@ -225,15 +292,50 @@ double magnesium_radio_ctrl_impl::set_rx_gain(const double gain, const size_t ch return _set_gain(gain, chan, RX_DIRECTION); } +std::string magnesium_radio_ctrl_impl::get_tx_antenna(const size_t chan) /* const */ +{ + return _get_antenna(chan, TX_DIRECTION); +} + +std::string magnesium_radio_ctrl_impl::get_rx_antenna(const size_t chan) /* const */ +{ + return _get_antenna(chan, RX_DIRECTION); +} + +double magnesium_radio_ctrl_impl::get_tx_frequency(const size_t chan) /* const */ +{ + return _get_frequency(chan, TX_DIRECTION); +} + +double magnesium_radio_ctrl_impl::get_rx_frequency(const size_t chan) /* const */ +{ + return _get_frequency(chan, RX_DIRECTION); +} + +double magnesium_radio_ctrl_impl::get_tx_gain(const size_t chan) /* const */ +{ + return _get_gain(chan, TX_DIRECTION); +} + +double magnesium_radio_ctrl_impl::get_rx_gain(const size_t chan) /* const */ +{ + return _get_gain(chan, RX_DIRECTION); +} + +double magnesium_radio_ctrl_impl::get_rx_bandwidth(const size_t chan) /* const */ +{ + return _get_bandwidth(chan, RX_DIRECTION); +} + size_t magnesium_radio_ctrl_impl::get_chan_from_dboard_fe(const std::string &fe, const direction_t dir) { - UHD_LOG_TRACE("MAGNESIUM", "get_chan_from_dboard_fe " << fe << " returns " << boost::lexical_cast(fe)); + // UHD_LOG_TRACE("MAGNESIUM", "get_chan_from_dboard_fe " << fe << " returns " << boost::lexical_cast(fe)); return boost::lexical_cast(fe); } std::string magnesium_radio_ctrl_impl::get_dboard_fe_from_chan(const size_t chan, const direction_t dir) { - UHD_LOG_TRACE("MAGNESIUM", "get_dboard_fe_from_chan " << chan << " returns " << std::to_string(chan)); + // UHD_LOG_TRACE("MAGNESIUM", "get_dboard_fe_from_chan " << chan << " returns " << std::to_string(chan)); return std::to_string(chan); } @@ -251,18 +353,71 @@ void magnesium_radio_ctrl_impl::set_rpc_client( _block_args = block_args; } -double magnesium_radio_ctrl_impl::_set_freq(const double freq, const size_t chan, const direction_t dir) +double magnesium_radio_ctrl_impl::_set_frequency(const double freq, const size_t chan, const direction_t dir) { + // TODO: there is only one LO per RX or TX, so changing frequency will affect the adjacent channel in the same direction + // Update the adjacent channel when this occurs auto which = _get_which(dir, chan); UHD_LOG_TRACE("MAGNESIUM", "calling " << _slot_prefix << "set_freq on " << which << " with " << freq); - return _rpcc->request_with_token(_slot_prefix + "set_freq", which, freq, false); + auto retval = _rpcc->request_with_token(_slot_prefix + "set_freq", which, freq, false); + UHD_LOG_TRACE("MAGNESIUM", _slot_prefix << "set_freq returned " << retval); + return retval; } double magnesium_radio_ctrl_impl::_set_gain(const double gain, const size_t chan, const direction_t dir) { auto which = _get_which(dir, chan); UHD_LOG_TRACE("MAGNESIUM", "calling " << _slot_prefix << "set_gain on " << which << " with " << gain); - return _rpcc->request_with_token(_slot_prefix + "set_gain", which, gain); + auto retval = _rpcc->request_with_token(_slot_prefix + "set_gain", which, gain); + UHD_LOG_TRACE("MAGNESIUM", _slot_prefix << "set_gain returned " << retval); + return retval; +} + +void magnesium_radio_ctrl_impl::_set_antenna(const std::string &ant, const size_t chan, const direction_t dir) +{ + // TODO: implement + UHD_LOG_WARNING("MAGNESIUM", "Ignoring attempt to set antenna"); + // CPLD control? +} + +double magnesium_radio_ctrl_impl::_set_bandwidth(const double bandwidth, const size_t chan, const direction_t dir) +{ + // TODO: implement + UHD_LOG_WARNING("MAGNESIUM", "Ignoring attempt to set bandwidth"); + return get_rx_bandwidth(chan); +} + +double magnesium_radio_ctrl_impl::_get_frequency(const size_t chan, const direction_t dir) +{ + auto which = _get_which(dir, chan); + UHD_LOG_TRACE("MAGNESIUM", "calling " << _slot_prefix << "get_freq on " << which); + auto retval = _rpcc->request_with_token(_slot_prefix + "get_freq", which); + UHD_LOG_TRACE("MAGNESIUM", _slot_prefix << "get_freq returned " << retval); + return retval; +} + +double magnesium_radio_ctrl_impl::_get_gain(const size_t chan, const direction_t dir) +{ + auto which = _get_which(dir, chan); + UHD_LOG_TRACE("MAGNESIUM", "calling " << _slot_prefix << "get_gain on " << which); + auto retval = _rpcc->request_with_token(_slot_prefix + "get_gain", which); + UHD_LOG_TRACE("MAGNESIUM", _slot_prefix << "get_gain returned " << retval); + return retval; +} + +std::string magnesium_radio_ctrl_impl::_get_antenna(const size_t chan, const direction_t dir) +{ + // TODO: implement + UHD_LOG_WARNING("MAGNESIUM", "Ignoring attempt to get antenna"); + return "RX1"; + // CPLD control? +} + +double magnesium_radio_ctrl_impl::_get_bandwidth(const size_t chan, const direction_t dir) +{ + // TODO: implement + UHD_LOG_WARNING("MAGNESIUM", "Ignoring attempt to get bandwidth"); + return MAGNESIUM_DEFAULT_BANDWIDTH; } UHD_RFNOC_BLOCK_REGISTER(magnesium_radio_ctrl, "MagnesiumRadio"); 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 0bb1b26b8..9535be824 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp @@ -54,6 +54,16 @@ public: double set_tx_gain(const double gain, const size_t chan); double set_rx_gain(const double gain, const size_t chan); + std::string get_tx_antenna(const size_t chan); + std::string get_rx_antenna(const size_t chan); + + double get_tx_frequency(const size_t chan); + double get_rx_frequency(const size_t chan); + double get_rx_bandwidth(const size_t chan); + + double get_tx_gain(const size_t chan); + double get_rx_gain(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); @@ -65,11 +75,21 @@ public: ); private: - double _set_freq(const double freq, const size_t chan, const direction_t dir); - double _set_gain(const double gain, const size_t chan, const direction_t dir); - std::string _radio_slot; std::string _slot_prefix; + + fs_path _get_fe_path(size_t chan, direction_t dir); + + double _set_frequency(const double freq, const size_t chan, const direction_t dir); + double _set_gain(const double gain, const size_t chan, const direction_t dir); + void _set_antenna(const std::string &ant, const size_t chan, const direction_t dir); + double _set_bandwidth(const double bandwidth, const size_t chan, const direction_t dir); + + double _get_frequency(const size_t chan, const direction_t dir); + double _get_gain(const size_t chan, const direction_t dir); + std::string _get_antenna(const size_t chan, const direction_t dir); + double _get_bandwidth(const size_t chan, const direction_t dir); + //! Additional block args; gets set during set_rpc_client() uhd::device_addr_t _block_args; -- cgit v1.2.3