diff options
author | Brent Stapleton <brent.stapleton@ettus.com> | 2019-01-14 10:35:25 -0800 |
---|---|---|
committer | Brent Stapleton <brent.stapleton@ettus.com> | 2019-01-16 11:40:23 -0800 |
commit | 967be2a4e82b1a125b26bb72a60318a4fb2b50c4 (patch) | |
tree | 8a24954b54d1546dc8049a17e485adb0a605f74f /host/lib | |
parent | aafe4e8b742a0e21d3818f21f34e3c8613132530 (diff) | |
download | uhd-967be2a4e82b1a125b26bb72a60318a4fb2b50c4.tar.gz uhd-967be2a4e82b1a125b26bb72a60318a4fb2b50c4.tar.bz2 uhd-967be2a4e82b1a125b26bb72a60318a4fb2b50c4.zip |
uhd: mpm: apply clang-format to all files
Applying formatting changes to all .cpp and .hpp files in the following
directories:
```
find host/examples/ -iname *.hpp -o -iname *.cpp | \
xargs clang-format -i -style=file
find host/tests/ -iname *.hpp -o -iname *.cpp | \
xargs clang-format -i -style=file
find host/lib/usrp/dboard/neon/ -iname *.hpp -o -iname *.cpp | \
xargs clang-format -i -style=file
find host/lib/usrp/dboard/magnesium/ -iname *.hpp -o -iname *.cpp | \
xargs clang-format -i -style=file
find host/lib/usrp/device3/ -iname *.hpp -o -iname *.cpp | \
xargs clang-format -i -style=file
find host/lib/usrp/mpmd/ -iname *.hpp -o -iname *.cpp | \
xargs clang-format -i -style=file
find host/lib/usrp/x300/ -iname *.hpp -o -iname *.cpp | \
xargs clang-format -i -style=file
find host/utils/ -iname *.hpp -o -iname *.cpp | \
xargs clang-format -i -style=file
find mpm/ -iname *.hpp -o -iname *.cpp | \
xargs clang-format -i -style=file
```
Also formatted host/include/, except Cpp03 was used as a the language
standard instead of Cpp11.
```
sed -i 's/ Cpp11/ Cpp03/g' .clang-format
find host/include/ -iname *.hpp -o -iname *.cpp | \
xargs clang-format -i -style=file
```
Formatting style was designated by the .clang-format file.
Diffstat (limited to 'host/lib')
61 files changed, 6799 insertions, 7418 deletions
diff --git a/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.cpp b/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.cpp index 8fd82cbc8..6a14f3976 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.cpp @@ -6,93 +6,79 @@ #include "magnesium_ad9371_iface.hpp" #include <uhd/utils/log.hpp> -#include <uhd/utils/log.hpp> using namespace uhd; namespace { - /*! Return a valid 'which' string for use with AD9371 API calls - * - * These strings take the form of "RX1", "TX2", ... - */ - std::string _get_which( - const direction_t dir, - const size_t chan - ) { - UHD_ASSERT_THROW(dir == RX_DIRECTION or dir == TX_DIRECTION); - UHD_ASSERT_THROW(chan == 0 or chan == 1); - return str(boost::format("%s%d") - % (dir == RX_DIRECTION ? "RX" : "TX") - % (chan+1) - ); - } +/*! Return a valid 'which' string for use with AD9371 API calls + * + * These strings take the form of "RX1", "TX2", ... + */ +std::string _get_which(const direction_t dir, const size_t chan) +{ + UHD_ASSERT_THROW(dir == RX_DIRECTION or dir == TX_DIRECTION); + UHD_ASSERT_THROW(chan == 0 or chan == 1); + return str(boost::format("%s%d") % (dir == RX_DIRECTION ? "RX" : "TX") % (chan + 1)); } +} // namespace /****************************************************************************** * Structors *****************************************************************************/ magnesium_ad9371_iface::magnesium_ad9371_iface( - uhd::rpc_client::sptr rpcc, - const size_t slot_idx -) : _rpcc(rpcc) - , _slot_idx(slot_idx) - , _rpc_prefix((slot_idx == 0) ? "db_0_" : "db_1_") - , _log_prefix((slot_idx == 0) ? "AD9371-0" : "AD9371-1") + uhd::rpc_client::sptr rpcc, const size_t slot_idx) + : _rpcc(rpcc) + , _slot_idx(slot_idx) + , _rpc_prefix((slot_idx == 0) ? "db_0_" : "db_1_") + , _log_prefix((slot_idx == 0) ? "AD9371-0" : "AD9371-1") { UHD_LOG_TRACE(_log_prefix, - "Initialized controls with RPC prefix " << _rpc_prefix << - " for slot " << _slot_idx); + "Initialized controls with RPC prefix " << _rpc_prefix << " for slot " + << _slot_idx); } double magnesium_ad9371_iface::set_frequency( - const double freq, - const size_t chan, - const direction_t dir -) { + const double freq, const size_t chan, const direction_t dir) +{ // Note: This sets the frequency for both channels (1 and 2). - auto which = _get_which(dir, chan); + auto which = _get_which(dir, chan); auto actual_freq = request<double>("set_freq", which, freq, false); - UHD_LOG_TRACE(_log_prefix, - _rpc_prefix << "set_freq returned " << actual_freq); + UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "set_freq returned " << actual_freq); return actual_freq; } double magnesium_ad9371_iface::set_gain( - const double gain, - const size_t chan, - const direction_t dir -) { - auto which = _get_which(dir, chan); + const double gain, const size_t chan, const direction_t dir) +{ + auto which = _get_which(dir, chan); auto retval = request<double>("set_gain", which, gain); UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "set_gain returned " << retval); return retval; - //return 0.0; + // return 0.0; } -double magnesium_ad9371_iface::set_master_clock_rate( - const double freq -) { +double magnesium_ad9371_iface::set_master_clock_rate(const double freq) +{ const auto actual_freq = request<double>("set_master_clock_rate", freq); - UHD_LOG_TRACE(_log_prefix, - _rpc_prefix << "set_master_clock_rate returned successfully"); + UHD_LOG_TRACE( + _log_prefix, _rpc_prefix << "set_master_clock_rate returned successfully"); return actual_freq; } -double magnesium_ad9371_iface::set_bandwidth(const double bandwidth, const size_t chan, const direction_t dir) +double magnesium_ad9371_iface::set_bandwidth( + const double bandwidth, const size_t chan, const direction_t dir) { auto const which = _get_which(dir, chan); - auto retval = request<double>("set_bw_filter", which, bandwidth); + auto retval = request<double>("set_bw_filter", which, bandwidth); UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "set_bw_filter returned " << retval); return retval; } -double magnesium_ad9371_iface::get_frequency( - const size_t chan, - const direction_t dir -) { - auto which = _get_which(dir, chan); +double magnesium_ad9371_iface::get_frequency(const size_t chan, const direction_t dir) +{ + auto which = _get_which(dir, chan); auto retval = request<double>("get_freq", which); UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "get_freq returned " << retval); return retval; @@ -100,13 +86,14 @@ double magnesium_ad9371_iface::get_frequency( double magnesium_ad9371_iface::get_gain(const size_t chan, const direction_t dir) { - auto which = _get_which(dir, chan); + auto which = _get_which(dir, chan); auto retval = request<double>("get_gain", which); UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "get_gain returned " << retval); return retval; } -double magnesium_ad9371_iface::get_bandwidth(const size_t /*chan*/, const direction_t /*dir*/) +double magnesium_ad9371_iface::get_bandwidth( + const size_t /*chan*/, const direction_t /*dir*/) { // TODO: implement UHD_LOG_WARNING(_log_prefix, "Ignoring attempt to get bandwidth"); @@ -114,23 +101,20 @@ double magnesium_ad9371_iface::get_bandwidth(const size_t /*chan*/, const direct } std::string magnesium_ad9371_iface::set_lo_source( - const std::string &source, - const uhd::direction_t dir -) { + const std::string& source, const uhd::direction_t dir) +{ // There is only one LO for 2 channels. Using channel 0 for 'which' - auto which = _get_which(dir, 0); + auto which = _get_which(dir, 0); auto retval = request<std::string>("set_lo_source", which, source); UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "set_lo_source returned " << retval); return retval; } -std::string magnesium_ad9371_iface::get_lo_source( - const uhd::direction_t dir -) { +std::string magnesium_ad9371_iface::get_lo_source(const uhd::direction_t dir) +{ // There is only one LO for 2 channels. Using channel 0 for 'which' - auto which = _get_which(dir, 0); + auto which = _get_which(dir, 0); auto retval = request<std::string>("get_lo_source", which); UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "get_lo_source returned " << retval); return retval; } - diff --git a/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.hpp b/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.hpp index acfecf2df..245c302ba 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.hpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.hpp @@ -17,56 +17,27 @@ class magnesium_ad9371_iface public: using uptr = std::unique_ptr<magnesium_ad9371_iface>; - magnesium_ad9371_iface( - uhd::rpc_client::sptr rpcc, - const size_t slot_idx - ); + magnesium_ad9371_iface(uhd::rpc_client::sptr rpcc, const size_t slot_idx); double set_frequency( - const double freq, - const size_t chan, - const uhd::direction_t dir - ); - - double get_frequency( - const size_t chan, - const uhd::direction_t dir - ); - - double set_gain( - const double gain, - const size_t chan, - const uhd::direction_t dir - ); - - double get_gain( - const size_t chan, - const uhd::direction_t dir - ); - - double set_master_clock_rate( - const double freq - ); + const double freq, const size_t chan, const uhd::direction_t dir); + + double get_frequency(const size_t chan, const uhd::direction_t dir); + + double set_gain(const double gain, const size_t chan, const uhd::direction_t dir); + + double get_gain(const size_t chan, const uhd::direction_t dir); + + double set_master_clock_rate(const double freq); double set_bandwidth( - const double bandwidth, - const size_t chan, - const uhd::direction_t dir - ); + const double bandwidth, const size_t chan, const uhd::direction_t dir); - double get_bandwidth( - const size_t chan, - const uhd::direction_t dir - ); + double get_bandwidth(const size_t chan, const uhd::direction_t dir); - std::string set_lo_source( - const std::string &source, - const uhd::direction_t dir - ); + std::string set_lo_source(const std::string& source, const uhd::direction_t dir); - std::string get_lo_source( - const uhd::direction_t dir - ); + std::string get_lo_source(const uhd::direction_t dir); private: /*! Shorthand to perform an RPC request. Saves some typing. @@ -76,9 +47,7 @@ private: { UHD_LOG_TRACE(_log_prefix, "[RPC] Calling " << func_name); return _rpcc->request_with_token<return_type>( - _rpc_prefix + func_name, - std::forward<Args>(args)... - ); + _rpc_prefix + func_name, std::forward<Args>(args)...); }; //! Reference to the RPC client @@ -92,7 +61,6 @@ private: //! Logger prefix const std::string _log_prefix; - }; #endif /* INCLUDED_LIBUHD_RFNOC_MAGNESIUM_AD9371_IFACE_HPP */ diff --git a/host/lib/usrp/dboard/magnesium/magnesium_bands.cpp b/host/lib/usrp/dboard/magnesium/magnesium_bands.cpp index 656543653..4792dcac6 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_bands.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_bands.cpp @@ -6,8 +6,8 @@ // The band plan -#include "magnesium_radio_ctrl_impl.hpp" #include "magnesium_constants.hpp" +#include "magnesium_radio_ctrl_impl.hpp" #include <uhd/utils/math.hpp> /* @@ -43,66 +43,67 @@ using namespace uhd::rfnoc; using namespace uhd::math::fp_compare; namespace { - /* Note on the RX filter bank: - * - * The RX path has 7 bands, which we call BAND0 through BAND7. BAND0 is the - * lowest frequency band (it goes through F44, the 490 MHz low pass filter, - * on the first channel). BAND7 is the highest frequency band, it goes - * through the 2.7 GHz high pass filter (F43 on the first channel). - * - * For all frequencies, there are gain values where we bypass the filter - * bank. In this case, the band setting does not apply (does not have any - * meaning). - * - * The lowband, when not disabling the filter bank, always goes through - * BAND0, but there are non-lowband frequencies which can also go through - * BAND0. - * - * The following constants define lower cutoff frequencies for each band. - * BAND0 does not have a lower cutoff frequency, it is implied by - * MAGNESIUM_MIN_FREQ. MAGNESIUM_RX_BAND1_MIN_FREQ is the cutover frequency - * for switching from BAND0 to BAND1, and so on. - * - * Bands 1-6 have both high- and low-pass filters (effectively band - * passes). Frequencies need to be chosen to allow as much of the full - * bandwidth through unattenuated. - */ - constexpr double MAGNESIUM_RX_BAND1_MIN_FREQ = 430e6; - constexpr double MAGNESIUM_RX_BAND2_MIN_FREQ = 600e6; - constexpr double MAGNESIUM_RX_BAND3_MIN_FREQ = 1050e6; - constexpr double MAGNESIUM_RX_BAND4_MIN_FREQ = 1600e6; - constexpr double MAGNESIUM_RX_BAND5_MIN_FREQ = 2100e6; - constexpr double MAGNESIUM_RX_BAND6_MIN_FREQ = 2700e6; +/* Note on the RX filter bank: + * + * The RX path has 7 bands, which we call BAND0 through BAND7. BAND0 is the + * lowest frequency band (it goes through F44, the 490 MHz low pass filter, + * on the first channel). BAND7 is the highest frequency band, it goes + * through the 2.7 GHz high pass filter (F43 on the first channel). + * + * For all frequencies, there are gain values where we bypass the filter + * bank. In this case, the band setting does not apply (does not have any + * meaning). + * + * The lowband, when not disabling the filter bank, always goes through + * BAND0, but there are non-lowband frequencies which can also go through + * BAND0. + * + * The following constants define lower cutoff frequencies for each band. + * BAND0 does not have a lower cutoff frequency, it is implied by + * MAGNESIUM_MIN_FREQ. MAGNESIUM_RX_BAND1_MIN_FREQ is the cutover frequency + * for switching from BAND0 to BAND1, and so on. + * + * Bands 1-6 have both high- and low-pass filters (effectively band + * passes). Frequencies need to be chosen to allow as much of the full + * bandwidth through unattenuated. + */ +constexpr double MAGNESIUM_RX_BAND1_MIN_FREQ = 430e6; +constexpr double MAGNESIUM_RX_BAND2_MIN_FREQ = 600e6; +constexpr double MAGNESIUM_RX_BAND3_MIN_FREQ = 1050e6; +constexpr double MAGNESIUM_RX_BAND4_MIN_FREQ = 1600e6; +constexpr double MAGNESIUM_RX_BAND5_MIN_FREQ = 2100e6; +constexpr double MAGNESIUM_RX_BAND6_MIN_FREQ = 2700e6; - /* Note on the TX filter bank: - * - * The TX path has 4 bands, which we call BAND0 through BAND3. - * For all frequencies, there are gain values where we bypass the filter - * bank. In this case, the band setting does not apply (does not have any - * meaning). - * - * The lowband, when not disabling the filter bank, always goes through - * BAND0, but there are non-lowband frequencies which can also go through - * BAND0. - * - * The following constants define lower cutoff frequencies for each band. - * BAND0 does not have a lower cutoff frequency, it is implied by - * MAGNESIUM_MIN_FREQ. MAGNESIUM_TX_BAND1_MIN_FREQ is the cutover frequency - * for switching from BAND0 to BAND1, and so on. - * - * On current Magnesium revisions, all filters on the TX filter bank are - * low pass filters (no high pass filters). - * Frequencies need to be chosen to allow as much of the full bandwidth - * through unattenuated (so don't go all the way up to the cutoff frequency - * of that filter, OK). - */ - constexpr double MAGNESIUM_TX_BAND1_MIN_FREQ = 723.17e6; - constexpr double MAGNESIUM_TX_BAND2_MIN_FREQ = 1623.17e6; - constexpr double MAGNESIUM_TX_BAND3_MIN_FREQ = 3323.17e6; -} +/* Note on the TX filter bank: + * + * The TX path has 4 bands, which we call BAND0 through BAND3. + * For all frequencies, there are gain values where we bypass the filter + * bank. In this case, the band setting does not apply (does not have any + * meaning). + * + * The lowband, when not disabling the filter bank, always goes through + * BAND0, but there are non-lowband frequencies which can also go through + * BAND0. + * + * The following constants define lower cutoff frequencies for each band. + * BAND0 does not have a lower cutoff frequency, it is implied by + * MAGNESIUM_MIN_FREQ. MAGNESIUM_TX_BAND1_MIN_FREQ is the cutover frequency + * for switching from BAND0 to BAND1, and so on. + * + * On current Magnesium revisions, all filters on the TX filter bank are + * low pass filters (no high pass filters). + * Frequencies need to be chosen to allow as much of the full bandwidth + * through unattenuated (so don't go all the way up to the cutoff frequency + * of that filter, OK). + */ +constexpr double MAGNESIUM_TX_BAND1_MIN_FREQ = 723.17e6; +constexpr double MAGNESIUM_TX_BAND2_MIN_FREQ = 1623.17e6; +constexpr double MAGNESIUM_TX_BAND3_MIN_FREQ = 3323.17e6; +} // namespace -magnesium_radio_ctrl_impl::rx_band -magnesium_radio_ctrl_impl::_map_freq_to_rx_band(const double freq) { +magnesium_radio_ctrl_impl::rx_band magnesium_radio_ctrl_impl::_map_freq_to_rx_band( + const double freq) +{ magnesium_radio_ctrl_impl::rx_band band; if (fp_compare_epsilon<double>(freq) < MAGNESIUM_MIN_FREQ) { @@ -130,8 +131,9 @@ magnesium_radio_ctrl_impl::_map_freq_to_rx_band(const double freq) { return band; } -magnesium_radio_ctrl_impl::tx_band -magnesium_radio_ctrl_impl::_map_freq_to_tx_band(const double freq) { +magnesium_radio_ctrl_impl::tx_band magnesium_radio_ctrl_impl::_map_freq_to_tx_band( + const double freq) +{ magnesium_radio_ctrl_impl::tx_band band; if (fp_compare_epsilon<double>(freq) < MAGNESIUM_MIN_FREQ) { @@ -152,4 +154,3 @@ magnesium_radio_ctrl_impl::_map_freq_to_tx_band(const double freq) { return band; } - diff --git a/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp b/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp index e19603b94..a045d0558 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp @@ -7,17 +7,17 @@ #ifndef INCLUDED_LIBUHD_MAGNESIUM_CONSTANTS_HPP #define INCLUDED_LIBUHD_MAGNESIUM_CONSTANTS_HPP -#include <vector> -#include <string> -#include <cstddef> #include <uhd/types/ranges.hpp> +#include <cstddef> +#include <string> +#include <vector> -static constexpr size_t FPGPIO_MASTER_RADIO = 0; -static constexpr size_t TOTAL_RADIO_PORTS = 4; -static constexpr double AD9371_RX_MIN_BANDWIDTH = 20.0e6; // HZ +static constexpr size_t FPGPIO_MASTER_RADIO = 0; +static constexpr size_t TOTAL_RADIO_PORTS = 4; +static constexpr double AD9371_RX_MIN_BANDWIDTH = 20.0e6; // HZ static constexpr double AD9371_RX_MAX_BANDWIDTH = 100.0e6; // HZ -static constexpr double AD9371_TX_MIN_BANDWIDTH = 20.0e6; // HZ +static constexpr double AD9371_TX_MIN_BANDWIDTH = 20.0e6; // HZ static constexpr double AD9371_TX_MAX_BANDWIDTH = 100.0e6; // HZ static constexpr double AD9371_MIN_FREQ = 300.0e6; // Hz @@ -27,36 +27,36 @@ static constexpr double ADF4351_MIN_FREQ = 35.0e6; static constexpr double ADF4351_MAX_FREQ = 4.4e9; static const std::vector<double> MAGNESIUM_RADIO_RATES = {122.88e6, 125e6, 153.6e6}; -static constexpr double MAGNESIUM_RADIO_RATE = 125e6; // Hz -static constexpr double MAGNESIUM_MIN_FREQ = 1e6; // Hz -static constexpr double MAGNESIUM_MAX_FREQ = 6e9; // Hz +static constexpr double MAGNESIUM_RADIO_RATE = 125e6; // Hz +static constexpr double MAGNESIUM_MIN_FREQ = 1e6; // Hz +static constexpr double MAGNESIUM_MAX_FREQ = 6e9; // Hz static constexpr double MAGNESIUM_LOWBAND_FREQ = 300e6; -static constexpr double AD9371_MIN_RX_GAIN = 0.0; // dB -static constexpr double AD9371_MAX_RX_GAIN = 30.0; // dB +static constexpr double AD9371_MIN_RX_GAIN = 0.0; // dB +static constexpr double AD9371_MAX_RX_GAIN = 30.0; // dB static constexpr double AD9371_RX_GAIN_STEP = 0.5; -static constexpr double DSA_MIN_GAIN = 0; // dB -static constexpr double DSA_MAX_GAIN = 31.5; // dB -static constexpr double DSA_GAIN_STEP = 0.5; // db -static constexpr double AMP_MIN_GAIN = 0; // dB -static constexpr double AMP_MAX_GAIN = 10; // dB -static constexpr double AMP_GAIN_STEP = 10;// dB -static constexpr double AD9371_MIN_TX_GAIN = 0.0; // dB -static constexpr double AD9371_MAX_TX_GAIN = 41.95; // dB +static constexpr double DSA_MIN_GAIN = 0; // dB +static constexpr double DSA_MAX_GAIN = 31.5; // dB +static constexpr double DSA_GAIN_STEP = 0.5; // db +static constexpr double AMP_MIN_GAIN = 0; // dB +static constexpr double AMP_MAX_GAIN = 10; // dB +static constexpr double AMP_GAIN_STEP = 10; // dB +static constexpr double AD9371_MIN_TX_GAIN = 0.0; // dB +static constexpr double AD9371_MAX_TX_GAIN = 41.95; // dB static constexpr double AD9371_TX_GAIN_STEP = 0.05; -static constexpr double ALL_RX_MIN_GAIN = 0.0; -static constexpr double ALL_RX_MAX_GAIN = 75.0; -static constexpr double ALL_RX_GAIN_STEP = 0.5; -static constexpr double ALL_TX_MIN_GAIN = 0.0; -static constexpr double ALL_TX_MAX_GAIN = 65.0; -static constexpr double ALL_TX_GAIN_STEP = 0.5; +static constexpr double ALL_RX_MIN_GAIN = 0.0; +static constexpr double ALL_RX_MAX_GAIN = 75.0; +static constexpr double ALL_RX_GAIN_STEP = 0.5; +static constexpr double ALL_TX_MIN_GAIN = 0.0; +static constexpr double ALL_TX_MAX_GAIN = 65.0; +static constexpr double ALL_TX_GAIN_STEP = 0.5; -static const uhd::freq_range_t MAGNESIUM_FREQ_RANGE(MAGNESIUM_MIN_FREQ, MAGNESIUM_MAX_FREQ); +static const uhd::freq_range_t MAGNESIUM_FREQ_RANGE( + MAGNESIUM_MIN_FREQ, MAGNESIUM_MAX_FREQ); static const std::vector<std::string> MAGNESIUM_RX_ANTENNAS = { - "TX/RX", "RX2", "CAL", "LOCAL" -}; + "TX/RX", "RX2", "CAL", "LOCAL"}; //! AD9371 LO (for direct conversion) static constexpr char MAGNESIUM_LO1[] = "rfic"; @@ -72,7 +72,7 @@ static constexpr char MAGNESIUM_AMP[] = "amp"; // Note: MAGNESIUM_NUM_CHANS is independent of the number of chans per // RFNoC block. TODO: When we go to one radio per dboard, this comment can // be deleted. -static constexpr size_t MAGNESIUM_NUM_CHANS = 2; +static constexpr size_t MAGNESIUM_NUM_CHANS = 2; static constexpr double MAGNESIUM_RX_IF_FREQ = 2.44e9; static constexpr double MAGNESIUM_TX_IF_FREQ = 1.95e9; diff --git a/host/lib/usrp/dboard/magnesium/magnesium_cpld_ctrl.cpp b/host/lib/usrp/dboard/magnesium/magnesium_cpld_ctrl.cpp index 3e68e2011..172f26390 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_cpld_ctrl.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_cpld_ctrl.cpp @@ -11,35 +11,26 @@ #include <chrono> namespace { - //! Address of the CPLD scratch register - const uint8_t CPLD_REGS_SCRATCH = 0x0040; +//! Address of the CPLD scratch register +const uint8_t CPLD_REGS_SCRATCH = 0x0040; - //! Address of the CPLD reset register - const uint8_t CPLD_REGS_RESET = 0x0041; -} +//! Address of the CPLD reset register +const uint8_t CPLD_REGS_RESET = 0x0041; +} // namespace -magnesium_cpld_ctrl::magnesium_cpld_ctrl( - write_spi_t write_fn, - read_spi_t read_fn -) +magnesium_cpld_ctrl::magnesium_cpld_ctrl(write_spi_t write_fn, read_spi_t read_fn) { - _write_fn = [write_fn](const uint8_t addr, const uint32_t data){ + _write_fn = [write_fn](const uint8_t addr, const uint32_t data) { UHD_LOG_TRACE("MG_CPLD", - str(boost::format("Writing to CPLD: 0x%02X -> 0x%04X") - % uint32_t(addr) % data)); - const uint32_t spi_transaction = 0 - | ((addr & 0x7F) << 16) - | data - ; + str(boost::format("Writing to CPLD: 0x%02X -> 0x%04X") % uint32_t(addr) + % data)); + const uint32_t spi_transaction = 0 | ((addr & 0x7F) << 16) | data; write_fn(spi_transaction); }; - _read_fn = [read_fn](const uint8_t addr){ + _read_fn = [read_fn](const uint8_t addr) { UHD_LOG_TRACE("MG_CPLD", - str(boost::format("Reading from CPLD address 0x%02X") - % uint32_t(addr))); - const uint32_t spi_transaction = (1<<23) - | ((addr & 0x7F) << 16) - ; + str(boost::format("Reading from CPLD address 0x%02X") % uint32_t(addr))); + const uint32_t spi_transaction = (1 << 23) | ((addr & 0x7F) << 16); return read_fn(spi_transaction); }; @@ -82,23 +73,24 @@ uint16_t magnesium_cpld_ctrl::get_scratch() return get_reg(CPLD_REGS_SCRATCH); } -void magnesium_cpld_ctrl::set_tx_switches( - const chan_sel_t chan, +void magnesium_cpld_ctrl::set_tx_switches(const chan_sel_t chan, const tx_sw1_t tx_sw1, const tx_sw2_t tx_sw2, const tx_sw3_t tx_sw3, const lowband_mixer_path_sel_t select_lowband_mixer_path, const bool enb_lowband_mixer, const atr_state_t atr_state, - const bool defer_commit -) { + const bool defer_commit) +{ std::lock_guard<std::mutex> l(_set_mutex); if (chan == CHAN1 or chan == BOTH) { if (atr_state == IDLE or atr_state == ANY) { _regs.ch1_idle_tx_sw1 = magnesium_cpld_regs_t::ch1_idle_tx_sw1_t(tx_sw1); _regs.ch1_idle_tx_sw2 = magnesium_cpld_regs_t::ch1_idle_tx_sw2_t(tx_sw2); _regs.ch1_idle_tx_sw3 = magnesium_cpld_regs_t::ch1_idle_tx_sw3_t(tx_sw3); - _regs.ch1_idle_tx_lowband_mixer_path_select = magnesium_cpld_regs_t::ch1_idle_tx_lowband_mixer_path_select_t(select_lowband_mixer_path); + _regs.ch1_idle_tx_lowband_mixer_path_select = + magnesium_cpld_regs_t::ch1_idle_tx_lowband_mixer_path_select_t( + select_lowband_mixer_path); _regs.ch1_idle_tx_mixer_en = enb_lowband_mixer; } if (atr_state == ON or atr_state == ANY) { @@ -106,7 +98,8 @@ void magnesium_cpld_ctrl::set_tx_switches( _regs.ch1_on_tx_sw2 = magnesium_cpld_regs_t::ch1_on_tx_sw2_t(tx_sw2); _regs.ch1_on_tx_sw3 = magnesium_cpld_regs_t::ch1_on_tx_sw3_t(tx_sw3); _regs.ch1_on_tx_lowband_mixer_path_select = - magnesium_cpld_regs_t::ch1_on_tx_lowband_mixer_path_select_t(select_lowband_mixer_path); + magnesium_cpld_regs_t::ch1_on_tx_lowband_mixer_path_select_t( + select_lowband_mixer_path); _regs.ch1_on_tx_mixer_en = enb_lowband_mixer; } } @@ -116,7 +109,8 @@ void magnesium_cpld_ctrl::set_tx_switches( _regs.ch2_idle_tx_sw2 = magnesium_cpld_regs_t::ch2_idle_tx_sw2_t(tx_sw1); _regs.ch2_idle_tx_sw3 = magnesium_cpld_regs_t::ch2_idle_tx_sw3_t(tx_sw1); _regs.ch2_idle_tx_lowband_mixer_path_select = - magnesium_cpld_regs_t::ch2_idle_tx_lowband_mixer_path_select_t(select_lowband_mixer_path); + magnesium_cpld_regs_t::ch2_idle_tx_lowband_mixer_path_select_t( + select_lowband_mixer_path); _regs.ch2_idle_tx_mixer_en = enb_lowband_mixer; } if (atr_state == ON or atr_state == ANY) { @@ -124,7 +118,8 @@ void magnesium_cpld_ctrl::set_tx_switches( _regs.ch2_on_tx_sw2 = magnesium_cpld_regs_t::ch2_on_tx_sw2_t(tx_sw2); _regs.ch2_on_tx_sw3 = magnesium_cpld_regs_t::ch2_on_tx_sw3_t(tx_sw3); _regs.ch2_on_tx_lowband_mixer_path_select = - magnesium_cpld_regs_t::ch2_on_tx_lowband_mixer_path_select_t(select_lowband_mixer_path); + magnesium_cpld_regs_t::ch2_on_tx_lowband_mixer_path_select_t( + select_lowband_mixer_path); _regs.ch2_on_tx_mixer_en = enb_lowband_mixer; } } @@ -134,8 +129,7 @@ void magnesium_cpld_ctrl::set_tx_switches( } } -void magnesium_cpld_ctrl::set_rx_switches( - const chan_sel_t chan, +void magnesium_cpld_ctrl::set_rx_switches(const chan_sel_t chan, const rx_sw2_t rx_sw2, const rx_sw3_t rx_sw3, const rx_sw4_t rx_sw4, @@ -144,8 +138,8 @@ void magnesium_cpld_ctrl::set_rx_switches( const lowband_mixer_path_sel_t select_lowband_mixer_path, const bool enb_lowband_mixer, const atr_state_t atr_state, - const bool defer_commit -) { + const bool defer_commit) +{ std::lock_guard<std::mutex> l(_set_mutex); if (chan == CHAN1 or chan == BOTH) { if (atr_state == IDLE or atr_state == ANY) { @@ -154,7 +148,9 @@ void magnesium_cpld_ctrl::set_rx_switches( _regs.ch1_idle_rx_sw4 = magnesium_cpld_regs_t::ch1_idle_rx_sw4_t(rx_sw4); _regs.ch1_idle_rx_sw5 = magnesium_cpld_regs_t::ch1_idle_rx_sw5_t(rx_sw5); _regs.ch1_idle_rx_sw6 = magnesium_cpld_regs_t::ch1_idle_rx_sw6_t(rx_sw6); - _regs.ch1_idle_rx_loband_mixer_path_sel = magnesium_cpld_regs_t::ch1_idle_rx_loband_mixer_path_sel_t(select_lowband_mixer_path); + _regs.ch1_idle_rx_loband_mixer_path_sel = + magnesium_cpld_regs_t::ch1_idle_rx_loband_mixer_path_sel_t( + select_lowband_mixer_path); _regs.ch1_idle_rx_mixer_en = enb_lowband_mixer; } if (atr_state == ON or atr_state == ANY) { @@ -163,7 +159,9 @@ void magnesium_cpld_ctrl::set_rx_switches( _regs.ch1_on_rx_sw4 = magnesium_cpld_regs_t::ch1_on_rx_sw4_t(rx_sw4); _regs.ch1_on_rx_sw5 = magnesium_cpld_regs_t::ch1_on_rx_sw5_t(rx_sw5); _regs.ch1_on_rx_sw6 = magnesium_cpld_regs_t::ch1_on_rx_sw6_t(rx_sw6); - _regs.ch1_on_rx_loband_mixer_path_sel = magnesium_cpld_regs_t::ch1_on_rx_loband_mixer_path_sel_t(select_lowband_mixer_path); + _regs.ch1_on_rx_loband_mixer_path_sel = + magnesium_cpld_regs_t::ch1_on_rx_loband_mixer_path_sel_t( + select_lowband_mixer_path); _regs.ch1_on_rx_mixer_en = enb_lowband_mixer; } } @@ -175,7 +173,8 @@ void magnesium_cpld_ctrl::set_rx_switches( _regs.ch2_idle_rx_sw5 = magnesium_cpld_regs_t::ch2_idle_rx_sw5_t(rx_sw5); _regs.ch2_idle_rx_sw6 = magnesium_cpld_regs_t::ch2_idle_rx_sw6_t(rx_sw6); _regs.ch2_idle_rx_loband_mixer_path_sel = - magnesium_cpld_regs_t::ch2_idle_rx_loband_mixer_path_sel_t(select_lowband_mixer_path); + magnesium_cpld_regs_t::ch2_idle_rx_loband_mixer_path_sel_t( + select_lowband_mixer_path); _regs.ch2_idle_rx_mixer_en = enb_lowband_mixer; } if (atr_state == ON or atr_state == ANY) { @@ -184,7 +183,9 @@ void magnesium_cpld_ctrl::set_rx_switches( _regs.ch2_on_rx_sw4 = magnesium_cpld_regs_t::ch2_on_rx_sw4_t(rx_sw4); _regs.ch2_on_rx_sw5 = magnesium_cpld_regs_t::ch2_on_rx_sw5_t(rx_sw5); _regs.ch2_on_rx_sw6 = magnesium_cpld_regs_t::ch2_on_rx_sw6_t(rx_sw6); - _regs.ch2_on_rx_loband_mixer_path_sel = magnesium_cpld_regs_t::ch2_on_rx_loband_mixer_path_sel_t(select_lowband_mixer_path); + _regs.ch2_on_rx_loband_mixer_path_sel = + magnesium_cpld_regs_t::ch2_on_rx_loband_mixer_path_sel_t( + select_lowband_mixer_path); _regs.ch2_on_rx_mixer_en = enb_lowband_mixer; } } @@ -193,40 +194,39 @@ void magnesium_cpld_ctrl::set_rx_switches( } } -void magnesium_cpld_ctrl::set_tx_atr_bits( - const chan_sel_t chan, +void magnesium_cpld_ctrl::set_tx_atr_bits(const chan_sel_t chan, const atr_state_t atr_state, const bool tx_led, const bool tx_pa_enb, const bool tx_amp_enb, const bool tx_myk_en, - const bool defer_commit -) { + const bool defer_commit) +{ std::lock_guard<std::mutex> l(_set_mutex); if (chan == CHAN1 or chan == BOTH) { if (atr_state == IDLE or atr_state == ANY) { - _regs.ch1_idle_tx_led = tx_led; - _regs.ch1_idle_tx_pa_en = tx_pa_enb; + _regs.ch1_idle_tx_led = tx_led; + _regs.ch1_idle_tx_pa_en = tx_pa_enb; _regs.ch1_idle_tx_amp_en = tx_amp_enb; _regs.ch1_idle_tx_myk_en = tx_myk_en; } if (atr_state == ON or atr_state == ANY) { - _regs.ch1_on_tx_led = tx_led; - _regs.ch1_on_tx_pa_en = tx_pa_enb; + _regs.ch1_on_tx_led = tx_led; + _regs.ch1_on_tx_pa_en = tx_pa_enb; _regs.ch1_on_tx_amp_en = tx_amp_enb; _regs.ch1_on_tx_myk_en = tx_myk_en; } } if (chan == CHAN2 or chan == BOTH) { if (atr_state == IDLE or atr_state == ANY) { - _regs.ch2_idle_tx_led = tx_led; - _regs.ch2_idle_tx_pa_en = tx_pa_enb; + _regs.ch2_idle_tx_led = tx_led; + _regs.ch2_idle_tx_pa_en = tx_pa_enb; _regs.ch2_idle_tx_amp_en = tx_amp_enb; _regs.ch2_idle_tx_myk_en = tx_myk_en; } if (atr_state == ON or atr_state == ANY) { - _regs.ch2_on_tx_led = tx_led; - _regs.ch2_on_tx_pa_en = tx_pa_enb; + _regs.ch2_on_tx_led = tx_led; + _regs.ch2_on_tx_pa_en = tx_pa_enb; _regs.ch2_on_tx_amp_en = tx_amp_enb; _regs.ch2_on_tx_myk_en = tx_myk_en; } @@ -236,31 +236,26 @@ void magnesium_cpld_ctrl::set_tx_atr_bits( } } -void magnesium_cpld_ctrl::set_trx_sw_atr_bits( - const chan_sel_t chan, +void magnesium_cpld_ctrl::set_trx_sw_atr_bits(const chan_sel_t chan, const atr_state_t atr_state, const sw_trx_t trx_sw, - const bool defer_commit -) { + const bool defer_commit) +{ std::lock_guard<std::mutex> l(_set_mutex); if (chan == CHAN1 or chan == BOTH) { if (atr_state == IDLE or atr_state == ANY) { - _regs.ch1_idle_sw_trx = - magnesium_cpld_regs_t::ch1_idle_sw_trx_t(trx_sw); + _regs.ch1_idle_sw_trx = magnesium_cpld_regs_t::ch1_idle_sw_trx_t(trx_sw); } if (atr_state == ON or atr_state == ANY) { - _regs.ch1_on_sw_trx = - magnesium_cpld_regs_t::ch1_on_sw_trx_t(trx_sw); + _regs.ch1_on_sw_trx = magnesium_cpld_regs_t::ch1_on_sw_trx_t(trx_sw); } } if (chan == CHAN2 or chan == BOTH) { if (atr_state == IDLE or atr_state == ANY) { - _regs.ch2_idle_sw_trx = - magnesium_cpld_regs_t::ch2_idle_sw_trx_t(trx_sw); + _regs.ch2_idle_sw_trx = magnesium_cpld_regs_t::ch2_idle_sw_trx_t(trx_sw); } if (atr_state == ON or atr_state == ANY) { - _regs.ch2_on_sw_trx = - magnesium_cpld_regs_t::ch2_on_sw_trx_t(trx_sw); + _regs.ch2_on_sw_trx = magnesium_cpld_regs_t::ch2_on_sw_trx_t(trx_sw); } } if (not defer_commit) { @@ -268,40 +263,35 @@ void magnesium_cpld_ctrl::set_trx_sw_atr_bits( } } -void magnesium_cpld_ctrl::set_rx_input_atr_bits( - const chan_sel_t chan, +void magnesium_cpld_ctrl::set_rx_input_atr_bits(const chan_sel_t chan, const atr_state_t atr_state, const rx_sw1_t rx_sw1, const bool rx_led, const bool rx2_led, - const bool defer_commit -) { + const bool defer_commit) +{ std::lock_guard<std::mutex> l(_set_mutex); if (chan == CHAN1 or chan == BOTH) { if (atr_state == IDLE or atr_state == ANY) { - _regs.ch1_idle_rx_sw1 = - magnesium_cpld_regs_t::ch1_idle_rx_sw1_t(rx_sw1); - _regs.ch1_idle_rx_led = rx_led; + _regs.ch1_idle_rx_sw1 = magnesium_cpld_regs_t::ch1_idle_rx_sw1_t(rx_sw1); + _regs.ch1_idle_rx_led = rx_led; _regs.ch1_idle_rx2_led = rx2_led; } if (atr_state == ON or atr_state == ANY) { - _regs.ch1_on_rx_sw1 = - magnesium_cpld_regs_t::ch1_on_rx_sw1_t(rx_sw1); - _regs.ch1_on_rx_led = rx_led; + _regs.ch1_on_rx_sw1 = magnesium_cpld_regs_t::ch1_on_rx_sw1_t(rx_sw1); + _regs.ch1_on_rx_led = rx_led; _regs.ch1_on_rx2_led = rx2_led; } } if (chan == CHAN2 or chan == BOTH) { if (atr_state == IDLE or atr_state == ANY) { - _regs.ch2_idle_rx_sw1 = - magnesium_cpld_regs_t::ch2_idle_rx_sw1_t(rx_sw1); - _regs.ch2_idle_rx_led = rx_led; + _regs.ch2_idle_rx_sw1 = magnesium_cpld_regs_t::ch2_idle_rx_sw1_t(rx_sw1); + _regs.ch2_idle_rx_led = rx_led; _regs.ch2_idle_rx2_led = rx2_led; } if (atr_state == ON or atr_state == ANY) { - _regs.ch2_on_rx_sw1 = - magnesium_cpld_regs_t::ch2_on_rx_sw1_t(rx_sw1); - _regs.ch2_on_rx_led = rx_led; + _regs.ch2_on_rx_sw1 = magnesium_cpld_regs_t::ch2_on_rx_sw1_t(rx_sw1); + _regs.ch2_on_rx_led = rx_led; _regs.ch2_on_rx2_led = rx2_led; } } @@ -311,13 +301,12 @@ void magnesium_cpld_ctrl::set_rx_input_atr_bits( } } -void magnesium_cpld_ctrl::set_rx_atr_bits( - const chan_sel_t chan, +void magnesium_cpld_ctrl::set_rx_atr_bits(const chan_sel_t chan, const atr_state_t atr_state, const bool rx_amp_enb, const bool rx_myk_en, - const bool defer_commit -) { + const bool defer_commit) +{ std::lock_guard<std::mutex> l(_set_mutex); if (chan == CHAN1 or chan == BOTH) { if (atr_state == IDLE or atr_state == ANY) { @@ -345,13 +334,12 @@ void magnesium_cpld_ctrl::set_rx_atr_bits( } } -void magnesium_cpld_ctrl::set_rx_lna_atr_bits( - const chan_sel_t chan, +void magnesium_cpld_ctrl::set_rx_lna_atr_bits(const chan_sel_t chan, const atr_state_t atr_state, const bool rx_lna1_enb, const bool rx_lna2_enb, - const bool defer_commit -) { + const bool defer_commit) +{ std::lock_guard<std::mutex> l(_set_mutex); if (chan == CHAN1 or chan == BOTH) { if (atr_state == IDLE or atr_state == ANY) { @@ -394,9 +382,7 @@ void magnesium_cpld_ctrl::_loopback_test() if (actual != random_number) { UHD_LOGGER_ERROR("MG_CPLD") << "CPLD scratch loopback failed! " - << boost::format("Expected: 0x%04X Got: 0x%04X") - % random_number % actual - ; + << boost::format("Expected: 0x%04X Got: 0x%04X") % random_number % actual; throw uhd::runtime_error("CPLD scratch loopback failed!"); } UHD_LOG_TRACE("MG_CPLD", "CPLD scratch loopback test passed!"); @@ -406,19 +392,16 @@ void magnesium_cpld_ctrl::_loopback_test() void magnesium_cpld_ctrl::commit(const bool save_all) { UHD_LOGGER_TRACE("MG_CPLD") - << "Storing register cache " - << (save_all ? "completely" : "selectively") - << " to CPLD via SPI..." - ; - auto changed_addrs = save_all ? - _regs.get_all_addrs() : - _regs.get_changed_addrs<size_t>(); - for (const auto addr: changed_addrs) { + << "Storing register cache " << (save_all ? "completely" : "selectively") + << " to CPLD via SPI..."; + auto changed_addrs = save_all ? _regs.get_all_addrs() + : _regs.get_changed_addrs<size_t>(); + for (const auto addr : changed_addrs) { _write_fn(addr, _regs.get_reg(addr)); } _regs.save_state(); UHD_LOG_TRACE("MG_CPLD", - "Storing cache complete: " \ - "Updated " << changed_addrs.size() << " registers."); + "Storing cache complete: " + "Updated " + << changed_addrs.size() << " registers."); } - diff --git a/host/lib/usrp/dboard/magnesium/magnesium_cpld_ctrl.hpp b/host/lib/usrp/dboard/magnesium/magnesium_cpld_ctrl.hpp index fc3af77de..05455e3fd 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_cpld_ctrl.hpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_cpld_ctrl.hpp @@ -8,10 +8,10 @@ #define INCLUDED_LIBUHD_MAGNESIUM_CPLD_CTRL_HPP #include "adf4351_regs.hpp" -#include <uhd/types/serial.hpp> #include "magnesium_cpld_regs.hpp" -#include <mutex> +#include <uhd/types/serial.hpp> #include <memory> +#include <mutex> //! Controls the CPLD on a Magnesium daughterboard // @@ -31,21 +31,13 @@ public: //! ATR state: The CPLD has 2 states for RX and TX each, not like the radio // which has 4 states (one for every RX/TX state combo). - enum atr_state_t { - IDLE, - ON, - ANY - }; + enum atr_state_t { IDLE, ON, ANY }; //! Channel select: One CPLD controls both channels on a daughterboard - enum chan_sel_t { - CHAN1, - CHAN2, - BOTH - }; + enum chan_sel_t { CHAN1, CHAN2, BOTH }; enum tx_sw1_t { - TX_SW1_SHUTDOWNTXSW1 = 0, + TX_SW1_SHUTDOWNTXSW1 = 0, TX_SW1_FROMTXFILTERLP1700MHZ = 1, TX_SW1_FROMTXFILTERLP3400MHZ = 2, TX_SW1_FROMTXFILTERLP0800MHZ = 3 @@ -58,59 +50,56 @@ public: TX_SW2_TOTXFILTERLP6400MHZ = 8 }; - enum tx_sw3_t { - TX_SW3_TOTXFILTERBANKS = 0, - TX_SW3_BYPASSPATHTOTRXSW = 1 - }; + enum tx_sw3_t { TX_SW3_TOTXFILTERBANKS = 0, TX_SW3_BYPASSPATHTOTRXSW = 1 }; enum sw_trx_t { - SW_TRX_FROMLOWERFILTERBANKTXSW1 = 0, + SW_TRX_FROMLOWERFILTERBANKTXSW1 = 0, SW_TRX_FROMTXUPPERFILTERBANKLP6400MHZ = 1, - SW_TRX_RXCHANNELPATH = 2, - SW_TRX_BYPASSPATHTOTXSW3 = 3 + SW_TRX_RXCHANNELPATH = 2, + SW_TRX_BYPASSPATHTOTXSW3 = 3 }; enum rx_sw1_t { - RX_SW1_TXRXINPUT = 0, - RX_SW1_RXLOCALINPUT = 1, + RX_SW1_TXRXINPUT = 0, + RX_SW1_RXLOCALINPUT = 1, RX_SW1_TRXSWITCHOUTPUT = 2, - RX_SW1_RX2INPUT = 3 + RX_SW1_RX2INPUT = 3 }; enum rx_sw2_t { - RX_SW2_SHUTDOWNSW2 = 0, + RX_SW2_SHUTDOWNSW2 = 0, RX_SW2_LOWERFILTERBANKTOSWITCH3 = 1, - RX_SW2_BYPASSPATHTOSWITCH6 = 2, + RX_SW2_BYPASSPATHTOSWITCH6 = 2, RX_SW2_UPPERFILTERBANKTOSWITCH4 = 3 }; enum rx_sw3_t { RX_SW3_FILTER2100X2850MHZ = 0, - RX_SW3_FILTER0490LPMHZ = 1, + RX_SW3_FILTER0490LPMHZ = 1, RX_SW3_FILTER1600X2250MHZ = 2, RX_SW3_FILTER0440X0530MHZ = 4, RX_SW3_FILTER0650X1000MHZ = 5, RX_SW3_FILTER1100X1575MHZ = 6, - RX_SW3_SHUTDOWNSW3 = 7 + RX_SW3_SHUTDOWNSW3 = 7 }; enum rx_sw4_t { RX_SW4_FILTER2100X2850MHZFROM = 1, RX_SW4_FILTER1600X2250MHZFROM = 2, - RX_SW4_FILTER2700HPMHZ = 4 + RX_SW4_FILTER2700HPMHZ = 4 }; enum rx_sw5_t { RX_SW5_FILTER0440X0530MHZFROM = 1, RX_SW5_FILTER1100X1575MHZFROM = 2, - RX_SW5_FILTER0490LPMHZFROM = 4, + RX_SW5_FILTER0490LPMHZFROM = 4, RX_SW5_FILTER0650X1000MHZFROM = 8 }; enum rx_sw6_t { RX_SW6_LOWERFILTERBANKFROMSWITCH5 = 1, RX_SW6_UPPERFILTERBANKFROMSWITCH4 = 2, - RX_SW6_BYPASSPATHFROMSWITCH2 = 4 + RX_SW6_BYPASSPATHFROMSWITCH2 = 4 }; enum lowband_mixer_path_sel_t { @@ -124,10 +113,7 @@ public: * \param write_spi_fn SPI write functor * \param read_spi_fn SPI read functor */ - magnesium_cpld_ctrl( - write_spi_t write_spi_fn, - read_spi_t read_spi_fn - ); + magnesium_cpld_ctrl(write_spi_t write_spi_fn, read_spi_t read_spi_fn); /************************************************************************** * API @@ -167,16 +153,14 @@ public: * \param atr_state If IDLE, only update the idle register. If ON, only * enable the on register. If ANY, update both. */ - void set_tx_switches( - const chan_sel_t chan, + void set_tx_switches(const chan_sel_t chan, const tx_sw1_t tx_sw1, const tx_sw2_t tx_sw2, const tx_sw3_t tx_sw3, const lowband_mixer_path_sel_t select_lowband_mixer_path, const bool enb_lowband_mixer, const atr_state_t atr_state = ANY, - const bool defer_commit = false - ); + const bool defer_commit = false); /*! Frequency-related settings, receive side * @@ -194,8 +178,7 @@ public: * \param atr_state If IDLE, only update the idle register. If ON, only * enable the on register. If ANY, update both. */ - void set_rx_switches( - const chan_sel_t chan, + void set_rx_switches(const chan_sel_t chan, const rx_sw2_t rx_sw2, const rx_sw3_t rx_sw3, const rx_sw4_t rx_sw4, @@ -204,8 +187,7 @@ public: const lowband_mixer_path_sel_t select_lowband_mixer_path, const bool enb_lowband_mixer, const atr_state_t atr_state = ANY, - const bool defer_commit = false - ); + const bool defer_commit = false); /*! ATR settings: LEDs, PAs, LNAs, ... for TX side * @@ -223,15 +205,13 @@ public: * \param tx_amp_enb State of the TX amp for this ATR state (on or off) * \param tx_myk_enb State of the AD9371 TX enable pin for this ATR state */ - void set_tx_atr_bits( - const chan_sel_t chan, + void set_tx_atr_bits(const chan_sel_t chan, const atr_state_t atr_state, const bool tx_led, const bool tx_pa_enb, const bool tx_amp_enb, const bool tx_myk_enb, - const bool defer_commit = false - ); + const bool defer_commit = false); /*! ATR settings: TRX switch * @@ -242,12 +222,10 @@ public: * \param atr_state TX state for which these settings apply. * \param trx_sw State of the TRX switch for this ATR state */ - void set_trx_sw_atr_bits( - const chan_sel_t chan, + void set_trx_sw_atr_bits(const chan_sel_t chan, const atr_state_t atr_state, const sw_trx_t trx_sw, - const bool defer_commit = false - ); + const bool defer_commit = false); /*! ATR settings: LEDs, input switches for RX side * @@ -263,14 +241,12 @@ public: * \param rx2_led State of the RX LED for this ATR state (on or off). This * is the LED on the RX2 port. */ - void set_rx_input_atr_bits( - const chan_sel_t chan, + void set_rx_input_atr_bits(const chan_sel_t chan, const atr_state_t atr_state, const rx_sw1_t rx_sw1, const bool rx_led, const bool rx2_led, - const bool defer_commit = false - ); + const bool defer_commit = false); /*! ATR settings: Amp, Mykonos settings for RX side * @@ -287,13 +263,11 @@ public: * \param rx_amp_enb State of RX amp for this ATR state (on or off). * \param rx_myk_enb State of the AD9371 RX enable pin for this ATR state */ - void set_rx_atr_bits( - const chan_sel_t chan, + void set_rx_atr_bits(const chan_sel_t chan, const atr_state_t atr_state, const bool rx_amp_enb, const bool rx_myk_en, - const bool defer_commit = false - ); + const bool defer_commit = false); /*! ATR settings: LNAs for RX side * @@ -311,13 +285,11 @@ public: * \param rx_lna2_enb State of RX LNA 2 for this ATR state (on or off). * This is the low-band LNA. */ - void set_rx_lna_atr_bits( - const chan_sel_t chan, + void set_rx_lna_atr_bits(const chan_sel_t chan, const atr_state_t atr_state, const bool rx_lna1_enb, const bool rx_lna2_enb, - const bool defer_commit = false - ); + const bool defer_commit = false); private: //! Write functor: Take address / data pair, craft SPI transaction diff --git a/host/lib/usrp/dboard/magnesium/magnesium_gain_table.cpp b/host/lib/usrp/dboard/magnesium/magnesium_gain_table.cpp index 05b6dbe8f..67b20f5fa 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_gain_table.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_gain_table.cpp @@ -15,47 +15,45 @@ using namespace uhd::rfnoc; using namespace magnesium; namespace { - typedef magnesium_radio_ctrl_impl::rx_band rx_band; - typedef magnesium_radio_ctrl_impl::tx_band tx_band; +typedef magnesium_radio_ctrl_impl::rx_band rx_band; +typedef magnesium_radio_ctrl_impl::tx_band tx_band; - const size_t TX_LOWBAND = 0; - const size_t TX_HIGHBAND = 1; - const size_t RX_LOWBAND = 0; - const size_t RX_MIDBAND = 1; - const size_t RX_HIGHBAND = 2; +const size_t TX_LOWBAND = 0; +const size_t TX_HIGHBAND = 1; +const size_t RX_LOWBAND = 0; +const size_t RX_MIDBAND = 1; +const size_t RX_HIGHBAND = 2; - size_t map_tx_band(const tx_band band) - { - if (band == tx_band::LOWBAND) { - return TX_LOWBAND; - } - return TX_HIGHBAND; +size_t map_tx_band(const tx_band band) +{ + if (band == tx_band::LOWBAND) { + return TX_LOWBAND; } + return TX_HIGHBAND; +} - size_t map_rx_band(const rx_band band) - { - if (band == rx_band::LOWBAND) { - return RX_LOWBAND; - } - if (band == rx_band::BAND0 or - band == rx_band::BAND1 or - band == rx_band::BAND2 or - band == rx_band::BAND3) { - return RX_MIDBAND; - } - return RX_HIGHBAND; +size_t map_rx_band(const rx_band band) +{ + if (band == rx_band::LOWBAND) { + return RX_LOWBAND; + } + if (band == rx_band::BAND0 or band == rx_band::BAND1 or band == rx_band::BAND2 + or band == rx_band::BAND3) { + return RX_MIDBAND; } + return RX_HIGHBAND; +} - //! Maps gain index -> gain_tuple_t - // - // Note: This is an int, for easier lookups. We're basically hardcoding the - // knowledge that the gain map has a 1 dB granularity. - using gain_tuple_map_t = std::map<int, gain_tuple_t>; +//! Maps gain index -> gain_tuple_t +// +// Note: This is an int, for easier lookups. We're basically hardcoding the +// knowledge that the gain map has a 1 dB granularity. +using gain_tuple_map_t = std::map<int, gain_tuple_t>; - //! Maps band -> gain_tuple_map_t - using gain_tables_t = std::map<size_t, gain_tuple_map_t>; +//! Maps band -> gain_tuple_map_t +using gain_tables_t = std::map<size_t, gain_tuple_map_t>; - // clang-format off +// clang-format off /*! RX gain tables */ const gain_tables_t rx_gain_tables = { @@ -437,53 +435,38 @@ namespace { {65, {0, 0, false}} }} }; /* tx_gain_tables */ - // clang-format on +// clang-format on - gain_tuple_t fine_tune_ad9371_att( - const gain_tuple_t gain_tuple, - const double gain_index - ) { - // Here, we hardcode the half-dB steps. We soak up all half-dB - // steps by twiddling the AD9371 attenuation, but we need to make - // sure we don't make it negative. - if (gain_index - int(gain_index) >= .5) { - gain_tuple_t gt2 = gain_tuple; - gt2.ad9371_att = std::max(0.0, gain_tuple.ad9371_att - .5); - return gt2; - } - return gain_tuple; +gain_tuple_t fine_tune_ad9371_att(const gain_tuple_t gain_tuple, const double gain_index) +{ + // Here, we hardcode the half-dB steps. We soak up all half-dB + // steps by twiddling the AD9371 attenuation, but we need to make + // sure we don't make it negative. + if (gain_index - int(gain_index) >= .5) { + gain_tuple_t gt2 = gain_tuple; + gt2.ad9371_att = std::max(0.0, gain_tuple.ad9371_att - .5); + return gt2; } + return gain_tuple; +} -} /* namespace ANON */ +} // namespace gain_tuple_t magnesium::get_rx_gain_tuple( - const double gain_index, - const magnesium_radio_ctrl_impl::rx_band band -) { - UHD_ASSERT_THROW( - gain_index <= ALL_RX_MAX_GAIN and gain_index >= ALL_RX_MIN_GAIN - ); - auto &gain_table = rx_gain_tables.at(map_rx_band(band)); + const double gain_index, const magnesium_radio_ctrl_impl::rx_band band) +{ + UHD_ASSERT_THROW(gain_index <= ALL_RX_MAX_GAIN and gain_index >= ALL_RX_MIN_GAIN); + auto& gain_table = rx_gain_tables.at(map_rx_band(band)); const int gain_index_truncd = int(gain_index); - return fine_tune_ad9371_att( - gain_table.at(gain_index_truncd), - gain_index - ); + return fine_tune_ad9371_att(gain_table.at(gain_index_truncd), gain_index); } gain_tuple_t magnesium::get_tx_gain_tuple( - const double gain_index, - const magnesium_radio_ctrl_impl::tx_band band -) { - UHD_ASSERT_THROW( - gain_index <= ALL_TX_MAX_GAIN and gain_index >= ALL_TX_MIN_GAIN - ); - auto &gain_table = tx_gain_tables.at(map_tx_band(band)); + const double gain_index, const magnesium_radio_ctrl_impl::tx_band band) +{ + UHD_ASSERT_THROW(gain_index <= ALL_TX_MAX_GAIN and gain_index >= ALL_TX_MIN_GAIN); + auto& gain_table = tx_gain_tables.at(map_tx_band(band)); const int gain_index_truncd = int(gain_index); - return fine_tune_ad9371_att( - gain_table.at(gain_index_truncd), - gain_index - ); + return fine_tune_ad9371_att(gain_table.at(gain_index_truncd), gain_index); } - diff --git a/host/lib/usrp/dboard/magnesium/magnesium_gain_table.hpp b/host/lib/usrp/dboard/magnesium/magnesium_gain_table.hpp index e36bdd59c..8769b44ac 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_gain_table.hpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_gain_table.hpp @@ -31,16 +31,12 @@ struct gain_tuple_t /*! Given a gain index, return a tuple of gain-related settings (Rx) */ gain_tuple_t get_rx_gain_tuple( - const double gain_index, - const uhd::rfnoc::magnesium_radio_ctrl_impl::rx_band band_ -); + const double gain_index, const uhd::rfnoc::magnesium_radio_ctrl_impl::rx_band band_); /*! Given a gain index, return a tuple of gain-related settings (Tx) */ gain_tuple_t get_tx_gain_tuple( - const double gain_index, - const uhd::rfnoc::magnesium_radio_ctrl_impl::tx_band band_ -); + const double gain_index, const uhd::rfnoc::magnesium_radio_ctrl_impl::tx_band band_); } /* namespace magnesium */ diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_cpld.cpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_cpld.cpp index 9ddb2cfcb..3c66a3b62 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_cpld.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_cpld.cpp @@ -4,37 +4,32 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include "magnesium_radio_ctrl_impl.hpp" -#include "magnesium_cpld_ctrl.hpp" #include "magnesium_constants.hpp" +#include "magnesium_cpld_ctrl.hpp" +#include "magnesium_radio_ctrl_impl.hpp" #include <uhd/utils/log.hpp> using namespace uhd; using namespace uhd::usrp; using namespace uhd::rfnoc; -void magnesium_radio_ctrl_impl::_identify_with_leds( - const int identify_duration -) { - auto end_time = std::chrono::steady_clock::now() - + std::chrono::seconds(identify_duration); +void magnesium_radio_ctrl_impl::_identify_with_leds(const int identify_duration) +{ + auto end_time = + std::chrono::steady_clock::now() + std::chrono::seconds(identify_duration); bool led_state = true; while (std::chrono::steady_clock::now() < end_time) { - _cpld->set_tx_atr_bits( - magnesium_cpld_ctrl::BOTH, + _cpld->set_tx_atr_bits(magnesium_cpld_ctrl::BOTH, magnesium_cpld_ctrl::ANY, led_state, false, false, - true - ); - _cpld->set_rx_input_atr_bits( - magnesium_cpld_ctrl::BOTH, + true); + _cpld->set_rx_input_atr_bits(magnesium_cpld_ctrl::BOTH, magnesium_cpld_ctrl::ANY, magnesium_cpld_ctrl::RX_SW1_TXRXINPUT, /* whatever */ led_state, - led_state - ); + led_state); led_state = !led_state; std::this_thread::sleep_for(std::chrono::milliseconds(500)); } @@ -44,27 +39,26 @@ void magnesium_radio_ctrl_impl::_identify_with_leds( void magnesium_radio_ctrl_impl::_update_atr_switches( const magnesium_cpld_ctrl::chan_sel_t chan, const direction_t dir, - const std::string &ant -){ + const std::string& ant) +{ if (dir == RX_DIRECTION or dir == DX_DIRECTION) { // These default values work for RX2 bool trx_led = false; bool rx2_led = true; - auto rx_sw1 = magnesium_cpld_ctrl::RX_SW1_RX2INPUT; + auto rx_sw1 = magnesium_cpld_ctrl::RX_SW1_RX2INPUT; // The TRX switch in TX-idle mode defaults to TX-on mode. When TX is // off, and we're receiving on TX/RX however, we need to point TRX to // RX SW1. In all other cases, a TX state toggle (on to idle or vice // versa) won't trigger a change of the TRX switch. auto sw_trx = _sw_trx[chan]; - UHD_LOG_TRACE(unique_id(), - "Updating all RX-ATR related switches for antenna==" << ant); + UHD_LOG_TRACE( + unique_id(), "Updating all RX-ATR related switches for antenna==" << ant); if (ant == "TX/RX") { - rx_sw1 = magnesium_cpld_ctrl::RX_SW1_TRXSWITCHOUTPUT; - sw_trx = magnesium_cpld_ctrl::SW_TRX_RXCHANNELPATH; + rx_sw1 = magnesium_cpld_ctrl::RX_SW1_TRXSWITCHOUTPUT; + sw_trx = magnesium_cpld_ctrl::SW_TRX_RXCHANNELPATH; trx_led = true; rx2_led = false; - } - else if (ant == "CAL") { + } else if (ant == "CAL") { // It makes intuitive sense to illuminate the green TX/RX LED when // receiving on CAL (because it goes over to the TX/RX port), but // the problem is that CAL is only useful when we're both TXing and @@ -72,35 +66,30 @@ void magnesium_radio_ctrl_impl::_update_atr_switches( // So, for CAL, we light up the green RX2 LED. trx_led = false; rx2_led = true; - rx_sw1 = magnesium_cpld_ctrl::RX_SW1_TXRXINPUT; - } - else if (ant == "LOCAL") { + rx_sw1 = magnesium_cpld_ctrl::RX_SW1_TXRXINPUT; + } else if (ant == "LOCAL") { rx_sw1 = magnesium_cpld_ctrl::RX_SW1_RXLOCALINPUT; } - _cpld->set_rx_input_atr_bits( - chan, + _cpld->set_rx_input_atr_bits(chan, magnesium_cpld_ctrl::ON, rx_sw1, trx_led, rx2_led, true /* defer commit */ ); - _cpld->set_rx_atr_bits( - chan, + _cpld->set_rx_atr_bits(chan, magnesium_cpld_ctrl::ON, - true, /* amp on */ - true, /* mykonos on */ - true /* defer commit */ + true, /* amp on */ + true, /* mykonos on */ + true /* defer commit */ ); - _cpld->set_rx_atr_bits( - chan, + _cpld->set_rx_atr_bits(chan, magnesium_cpld_ctrl::IDLE, - true, /* amp stays on */ - true, /* mykonos on */ - true /* defer commit */ + true, /* amp stays on */ + true, /* mykonos on */ + true /* defer commit */ ); - _cpld->set_trx_sw_atr_bits( - chan, + _cpld->set_trx_sw_atr_bits(chan, magnesium_cpld_ctrl::IDLE, /* idle here means TX is off */ sw_trx, false /* don't defer commit */ @@ -108,220 +97,203 @@ void magnesium_radio_ctrl_impl::_update_atr_switches( } if (dir == TX_DIRECTION or dir == DX_DIRECTION) { UHD_LOG_TRACE(unique_id(), "Updating all TX-ATR related switches..."); - _cpld->set_tx_atr_bits( - chan, + _cpld->set_tx_atr_bits(chan, magnesium_cpld_ctrl::ON, true, /* LED on */ true, /* PA on */ true, /* AMP on */ true, /* Myk on */ - true /* defer commit */ + true /* defer commit */ ); // Leaving PA on since we want shorter tx settling time. - _cpld->set_tx_atr_bits( - chan, + _cpld->set_tx_atr_bits(chan, magnesium_cpld_ctrl::IDLE, false, /* LED off */ true, /* PA on */ true, /* AMP on */ - true, /* Myk on */ - false /* don't defer commit */ + true, /* Myk on */ + false /* don't defer commit */ ); }; } -void magnesium_radio_ctrl_impl::_update_rx_freq_switches( - const double freq, +void magnesium_radio_ctrl_impl::_update_rx_freq_switches(const double freq, const bool bypass_lnas, - const magnesium_cpld_ctrl::chan_sel_t chan_sel -) { + const magnesium_cpld_ctrl::chan_sel_t chan_sel) +{ UHD_LOG_TRACE(unique_id(), - "Update all RX freq related switches. f=" << freq << " Hz, " - "bypass LNAS: " << (bypass_lnas ? "Yes" : "No") << ", chan=" << chan_sel - ); - auto rx_sw2 = magnesium_cpld_ctrl::RX_SW2_BYPASSPATHTOSWITCH6; - auto rx_sw3 = magnesium_cpld_ctrl::RX_SW3_SHUTDOWNSW3; - auto rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER2100X2850MHZFROM; - auto rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER1100X1575MHZFROM; - auto rx_sw6 = magnesium_cpld_ctrl::RX_SW6_BYPASSPATHFROMSWITCH2; - const auto band = _map_freq_to_rx_band(freq); + "Update all RX freq related switches. f=" << freq + << " Hz, " + "bypass LNAS: " + << (bypass_lnas ? "Yes" : "No") + << ", chan=" << chan_sel); + auto rx_sw2 = magnesium_cpld_ctrl::RX_SW2_BYPASSPATHTOSWITCH6; + auto rx_sw3 = magnesium_cpld_ctrl::RX_SW3_SHUTDOWNSW3; + auto rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER2100X2850MHZFROM; + auto rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER1100X1575MHZFROM; + auto rx_sw6 = magnesium_cpld_ctrl::RX_SW6_BYPASSPATHFROMSWITCH2; + const auto band = _map_freq_to_rx_band(freq); const bool is_lowband = (band == rx_band::LOWBAND); - const auto select_lowband_mixer_path = is_lowband ? - magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_LOBAND : - magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_BYPASS; + const auto select_lowband_mixer_path = + is_lowband ? magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_LOBAND + : magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_BYPASS; const bool enable_lowband_mixer = is_lowband; const bool rx_lna1_enable = - not bypass_lnas and ( - band == rx_band::BAND4 or - band == rx_band::BAND5 or - band == rx_band::BAND6); + not bypass_lnas + and (band == rx_band::BAND4 or band == rx_band::BAND5 or band == rx_band::BAND6); const bool rx_lna2_enable = not bypass_lnas and not rx_lna1_enable; UHD_LOG_TRACE(unique_id(), - " Enabling LNA1: " << (rx_lna1_enable ? "Yes" : "No") << - " Enabling LNA2: " << (rx_lna2_enable ? "Yes" : "No")); + " Enabling LNA1: " << (rx_lna1_enable ? "Yes" : "No") + << " Enabling LNA2: " << (rx_lna2_enable ? "Yes" : "No")); // All the defaults are OK when using the bypass path. if (not bypass_lnas) { - switch(band) { - case rx_band::LOWBAND: - case rx_band::BAND0: - rx_sw2 = magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3; - rx_sw3 = magnesium_cpld_ctrl::RX_SW3_FILTER0490LPMHZ; - rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ; - rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER0490LPMHZFROM; - rx_sw6 = magnesium_cpld_ctrl::RX_SW6_LOWERFILTERBANKFROMSWITCH5; - break; - case rx_band::BAND1: - rx_sw2 = magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3; - rx_sw3 = magnesium_cpld_ctrl::RX_SW3_FILTER0440X0530MHZ; - rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ; - rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER0440X0530MHZFROM; - rx_sw6 = magnesium_cpld_ctrl::RX_SW6_LOWERFILTERBANKFROMSWITCH5; - break; - case rx_band::BAND2: - rx_sw2 = magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3; - rx_sw3 = magnesium_cpld_ctrl::RX_SW3_FILTER0650X1000MHZ; - rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ; - rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER0650X1000MHZFROM; - rx_sw6 = magnesium_cpld_ctrl::RX_SW6_LOWERFILTERBANKFROMSWITCH5; - break; - case rx_band::BAND3: - rx_sw2 = magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3; - rx_sw3 = magnesium_cpld_ctrl::RX_SW3_FILTER1100X1575MHZ; - rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ; - rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER1100X1575MHZFROM; - rx_sw6 = magnesium_cpld_ctrl::RX_SW6_LOWERFILTERBANKFROMSWITCH5; - break; - case rx_band::BAND4: - rx_sw2 = magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3; - rx_sw3 = magnesium_cpld_ctrl::RX_SW3_FILTER1600X2250MHZ; - rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER1600X2250MHZFROM; - rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER0440X0530MHZFROM; - rx_sw6 = magnesium_cpld_ctrl::RX_SW6_UPPERFILTERBANKFROMSWITCH4; - break; - case rx_band::BAND5: - rx_sw2 = magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3; - rx_sw3 = magnesium_cpld_ctrl::RX_SW3_FILTER2100X2850MHZ; - rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER2100X2850MHZFROM; - rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER0440X0530MHZFROM; - rx_sw6 = magnesium_cpld_ctrl::RX_SW6_UPPERFILTERBANKFROMSWITCH4; - break; - case rx_band::BAND6: - rx_sw2 = magnesium_cpld_ctrl::RX_SW2_UPPERFILTERBANKTOSWITCH4; - rx_sw3 = magnesium_cpld_ctrl::RX_SW3_SHUTDOWNSW3; - rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ; - rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER0440X0530MHZFROM; - rx_sw6 = magnesium_cpld_ctrl::RX_SW6_UPPERFILTERBANKFROMSWITCH4; - break; - case rx_band::INVALID_BAND: - UHD_LOG_ERROR(unique_id(), - "Cannot map RX frequency to band: " << freq); - break; - default: - UHD_THROW_INVALID_CODE_PATH(); + switch (band) { + case rx_band::LOWBAND: + case rx_band::BAND0: + rx_sw2 = magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3; + rx_sw3 = magnesium_cpld_ctrl::RX_SW3_FILTER0490LPMHZ; + rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ; + rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER0490LPMHZFROM; + rx_sw6 = magnesium_cpld_ctrl::RX_SW6_LOWERFILTERBANKFROMSWITCH5; + break; + case rx_band::BAND1: + rx_sw2 = magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3; + rx_sw3 = magnesium_cpld_ctrl::RX_SW3_FILTER0440X0530MHZ; + rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ; + rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER0440X0530MHZFROM; + rx_sw6 = magnesium_cpld_ctrl::RX_SW6_LOWERFILTERBANKFROMSWITCH5; + break; + case rx_band::BAND2: + rx_sw2 = magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3; + rx_sw3 = magnesium_cpld_ctrl::RX_SW3_FILTER0650X1000MHZ; + rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ; + rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER0650X1000MHZFROM; + rx_sw6 = magnesium_cpld_ctrl::RX_SW6_LOWERFILTERBANKFROMSWITCH5; + break; + case rx_band::BAND3: + rx_sw2 = magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3; + rx_sw3 = magnesium_cpld_ctrl::RX_SW3_FILTER1100X1575MHZ; + rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ; + rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER1100X1575MHZFROM; + rx_sw6 = magnesium_cpld_ctrl::RX_SW6_LOWERFILTERBANKFROMSWITCH5; + break; + case rx_band::BAND4: + rx_sw2 = magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3; + rx_sw3 = magnesium_cpld_ctrl::RX_SW3_FILTER1600X2250MHZ; + rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER1600X2250MHZFROM; + rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER0440X0530MHZFROM; + rx_sw6 = magnesium_cpld_ctrl::RX_SW6_UPPERFILTERBANKFROMSWITCH4; + break; + case rx_band::BAND5: + rx_sw2 = magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3; + rx_sw3 = magnesium_cpld_ctrl::RX_SW3_FILTER2100X2850MHZ; + rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER2100X2850MHZFROM; + rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER0440X0530MHZFROM; + rx_sw6 = magnesium_cpld_ctrl::RX_SW6_UPPERFILTERBANKFROMSWITCH4; + break; + case rx_band::BAND6: + rx_sw2 = magnesium_cpld_ctrl::RX_SW2_UPPERFILTERBANKTOSWITCH4; + rx_sw3 = magnesium_cpld_ctrl::RX_SW3_SHUTDOWNSW3; + rx_sw4 = magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ; + rx_sw5 = magnesium_cpld_ctrl::RX_SW5_FILTER0440X0530MHZFROM; + rx_sw6 = magnesium_cpld_ctrl::RX_SW6_UPPERFILTERBANKFROMSWITCH4; + break; + case rx_band::INVALID_BAND: + UHD_LOG_ERROR(unique_id(), "Cannot map RX frequency to band: " << freq); + break; + default: + UHD_THROW_INVALID_CODE_PATH(); } } - _cpld->set_rx_lna_atr_bits( - chan_sel, + _cpld->set_rx_lna_atr_bits(chan_sel, magnesium_cpld_ctrl::ANY, rx_lna1_enable, rx_lna2_enable, true /* defer commit */ ); - _cpld->set_rx_switches( - chan_sel, + _cpld->set_rx_switches(chan_sel, rx_sw2, rx_sw3, rx_sw4, rx_sw5, rx_sw6, select_lowband_mixer_path, - enable_lowband_mixer - ); + enable_lowband_mixer); } -void magnesium_radio_ctrl_impl::_update_tx_freq_switches( - const double freq, +void magnesium_radio_ctrl_impl::_update_tx_freq_switches(const double freq, const bool bypass_amp, - const magnesium_cpld_ctrl::chan_sel_t chan_sel -){ + const magnesium_cpld_ctrl::chan_sel_t chan_sel) +{ UHD_LOG_TRACE(unique_id(), - "Update all TX freq related switches. f=" << freq << " Hz, " - "bypass amp: " << (bypass_amp ? "Yes" : "No") << ", chan=" << chan_sel - ); - auto tx_sw1 = magnesium_cpld_ctrl::TX_SW1_SHUTDOWNTXSW1; - auto tx_sw2 = magnesium_cpld_ctrl::TX_SW2_TOTXFILTERLP6400MHZ; - auto tx_sw3 = magnesium_cpld_ctrl::TX_SW3_BYPASSPATHTOTRXSW; - const auto band = _map_freq_to_tx_band(freq); + "Update all TX freq related switches. f=" << freq + << " Hz, " + "bypass amp: " + << (bypass_amp ? "Yes" : "No") + << ", chan=" << chan_sel); + auto tx_sw1 = magnesium_cpld_ctrl::TX_SW1_SHUTDOWNTXSW1; + auto tx_sw2 = magnesium_cpld_ctrl::TX_SW2_TOTXFILTERLP6400MHZ; + auto tx_sw3 = magnesium_cpld_ctrl::TX_SW3_BYPASSPATHTOTRXSW; + const auto band = _map_freq_to_tx_band(freq); const bool is_lowband = (band == tx_band::LOWBAND); - const auto select_lowband_mixer_path = is_lowband ? - magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_LOBAND : - magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_BYPASS; + const auto select_lowband_mixer_path = + is_lowband ? magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_LOBAND + : magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_BYPASS; const bool enable_lowband_mixer = is_lowband; // Defaults are fine for bypassing the amp stage if (bypass_amp) { _sw_trx[chan_sel] = magnesium_cpld_ctrl::SW_TRX_BYPASSPATHTOTXSW3; } else { - // Set filters based on frequency - switch(band) { - case tx_band::LOWBAND: - _sw_trx[chan_sel] = - magnesium_cpld_ctrl::SW_TRX_FROMLOWERFILTERBANKTXSW1; - tx_sw1 = magnesium_cpld_ctrl::TX_SW1_FROMTXFILTERLP0800MHZ; - tx_sw2 = magnesium_cpld_ctrl::TX_SW2_TOTXFILTERLP0800MHZ; - tx_sw3 = magnesium_cpld_ctrl::TX_SW3_TOTXFILTERBANKS; - break; - case tx_band::BAND0: - _sw_trx[chan_sel] = - magnesium_cpld_ctrl::SW_TRX_FROMLOWERFILTERBANKTXSW1; - tx_sw1 = magnesium_cpld_ctrl::TX_SW1_FROMTXFILTERLP0800MHZ; - tx_sw2 = magnesium_cpld_ctrl::TX_SW2_TOTXFILTERLP0800MHZ; - tx_sw3 = magnesium_cpld_ctrl::TX_SW3_TOTXFILTERBANKS; - break; - case tx_band::BAND1: - _sw_trx[chan_sel] = - magnesium_cpld_ctrl::SW_TRX_FROMLOWERFILTERBANKTXSW1; - tx_sw1 = magnesium_cpld_ctrl::TX_SW1_FROMTXFILTERLP1700MHZ; - tx_sw2 = magnesium_cpld_ctrl::TX_SW2_TOTXFILTERLP1700MHZ; - tx_sw3 = magnesium_cpld_ctrl::TX_SW3_TOTXFILTERBANKS; - break; - case tx_band::BAND2: - _sw_trx[chan_sel] = - magnesium_cpld_ctrl::SW_TRX_FROMLOWERFILTERBANKTXSW1; - tx_sw1 = magnesium_cpld_ctrl::TX_SW1_FROMTXFILTERLP3400MHZ; - tx_sw2 = magnesium_cpld_ctrl::TX_SW2_TOTXFILTERLP3400MHZ; - tx_sw3 = magnesium_cpld_ctrl::TX_SW3_TOTXFILTERBANKS; - break; - case tx_band::BAND3: - _sw_trx[chan_sel] = - magnesium_cpld_ctrl::SW_TRX_FROMTXUPPERFILTERBANKLP6400MHZ; - tx_sw1 = magnesium_cpld_ctrl::TX_SW1_SHUTDOWNTXSW1; - tx_sw2 = magnesium_cpld_ctrl::TX_SW2_TOTXFILTERLP6400MHZ; - tx_sw3 = magnesium_cpld_ctrl::TX_SW3_TOTXFILTERBANKS; - break; - case tx_band::INVALID_BAND: - UHD_LOG_ERROR(unique_id(), - "Cannot map TX frequency to band: " << freq); - break; - default: - UHD_THROW_INVALID_CODE_PATH(); + // Set filters based on frequency + switch (band) { + case tx_band::LOWBAND: + _sw_trx[chan_sel] = magnesium_cpld_ctrl::SW_TRX_FROMLOWERFILTERBANKTXSW1; + tx_sw1 = magnesium_cpld_ctrl::TX_SW1_FROMTXFILTERLP0800MHZ; + tx_sw2 = magnesium_cpld_ctrl::TX_SW2_TOTXFILTERLP0800MHZ; + tx_sw3 = magnesium_cpld_ctrl::TX_SW3_TOTXFILTERBANKS; + break; + case tx_band::BAND0: + _sw_trx[chan_sel] = magnesium_cpld_ctrl::SW_TRX_FROMLOWERFILTERBANKTXSW1; + tx_sw1 = magnesium_cpld_ctrl::TX_SW1_FROMTXFILTERLP0800MHZ; + tx_sw2 = magnesium_cpld_ctrl::TX_SW2_TOTXFILTERLP0800MHZ; + tx_sw3 = magnesium_cpld_ctrl::TX_SW3_TOTXFILTERBANKS; + break; + case tx_band::BAND1: + _sw_trx[chan_sel] = magnesium_cpld_ctrl::SW_TRX_FROMLOWERFILTERBANKTXSW1; + tx_sw1 = magnesium_cpld_ctrl::TX_SW1_FROMTXFILTERLP1700MHZ; + tx_sw2 = magnesium_cpld_ctrl::TX_SW2_TOTXFILTERLP1700MHZ; + tx_sw3 = magnesium_cpld_ctrl::TX_SW3_TOTXFILTERBANKS; + break; + case tx_band::BAND2: + _sw_trx[chan_sel] = magnesium_cpld_ctrl::SW_TRX_FROMLOWERFILTERBANKTXSW1; + tx_sw1 = magnesium_cpld_ctrl::TX_SW1_FROMTXFILTERLP3400MHZ; + tx_sw2 = magnesium_cpld_ctrl::TX_SW2_TOTXFILTERLP3400MHZ; + tx_sw3 = magnesium_cpld_ctrl::TX_SW3_TOTXFILTERBANKS; + break; + case tx_band::BAND3: + _sw_trx[chan_sel] = + magnesium_cpld_ctrl::SW_TRX_FROMTXUPPERFILTERBANKLP6400MHZ; + tx_sw1 = magnesium_cpld_ctrl::TX_SW1_SHUTDOWNTXSW1; + tx_sw2 = magnesium_cpld_ctrl::TX_SW2_TOTXFILTERLP6400MHZ; + tx_sw3 = magnesium_cpld_ctrl::TX_SW3_TOTXFILTERBANKS; + break; + case tx_band::INVALID_BAND: + UHD_LOG_ERROR(unique_id(), "Cannot map TX frequency to band: " << freq); + break; + default: + UHD_THROW_INVALID_CODE_PATH(); } } _cpld->set_trx_sw_atr_bits( - chan_sel, - magnesium_cpld_ctrl::ON, - _sw_trx[chan_sel], - true /* defer commit */ + chan_sel, magnesium_cpld_ctrl::ON, _sw_trx[chan_sel], true /* defer commit */ ); - _cpld->set_tx_switches( - chan_sel, + _cpld->set_tx_switches(chan_sel, tx_sw1, tx_sw2, tx_sw3, select_lowband_mixer_path, enable_lowband_mixer, - magnesium_cpld_ctrl::ON - ); + magnesium_cpld_ctrl::ON); } - 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 e58e1706e..1370fde3a 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_gain.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_gain.cpp @@ -4,9 +4,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include "magnesium_radio_ctrl_impl.hpp" -#include "magnesium_gain_table.hpp" #include "magnesium_constants.hpp" +#include "magnesium_gain_table.hpp" +#include "magnesium_radio_ctrl_impl.hpp" #include <uhd/utils/log.hpp> using namespace uhd; @@ -15,72 +15,69 @@ using namespace uhd::rfnoc; using namespace magnesium; double magnesium_radio_ctrl_impl::_set_all_gain( - const double gain, - const double freq, - const size_t chan, - const direction_t dir -) { + const double gain, const double freq, const size_t chan, const direction_t dir) +{ UHD_LOG_TRACE(unique_id(), - __func__ << "(gain=" << gain << "dB, " - "freq=" << freq << " Hz, " - "chan=" << chan << ", " - "dir=" << dir); + __func__ << "(gain=" << gain + << "dB, " + "freq=" + << freq + << " Hz, " + "chan=" + << chan + << ", " + "dir=" + << dir); const size_t ad9371_chan = chan; - auto chan_sel = static_cast<magnesium_cpld_ctrl::chan_sel_t>(chan); - 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)); + auto chan_sel = static_cast<magnesium_cpld_ctrl::chan_sel_t>(chan); + 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"){ + 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], + 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"){ + } 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]) + } 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) + ((dir == RX_DIRECTION) ? AD9371_MAX_RX_GAIN : AD9371_MAX_TX_GAIN) - gain_tuple.ad9371_att; UHD_LOG_TRACE(unique_id(), - "AD9371 attenuation==" << gain_tuple.ad9371_att << " dB, " - "AD9371 gain==" << ad9371_gain << " dB, " - "DSA attenuation == " << gain_tuple.dsa_att << " dB." - ); + "AD9371 attenuation==" << gain_tuple.ad9371_att + << " dB, " + "AD9371 gain==" + << ad9371_gain + << " dB, " + "DSA attenuation == " + << gain_tuple.dsa_att << " dB."); _ad9371->set_gain(ad9371_gain, ad9371_chan, dir); _dsa_set_att(gain_tuple.dsa_att, chan, dir); if (dir == RX_DIRECTION or dir == DX_DIRECTION) { - _all_rx_gain = gain; + _all_rx_gain = gain; _rx_bypass_lnas = gain_tuple.bypass; - _update_rx_freq_switches( - this->get_rx_frequency(chan), - _rx_bypass_lnas, - chan_sel - ); + _update_rx_freq_switches(this->get_rx_frequency(chan), _rx_bypass_lnas, chan_sel); } if (dir == TX_DIRECTION or dir == DX_DIRECTION) { - _all_tx_gain = gain; + _all_tx_gain = gain; _tx_bypass_amp = gain_tuple.bypass; - _update_tx_freq_switches( - this->get_tx_frequency(chan), - _tx_bypass_amp, - chan_sel - ); + _update_tx_freq_switches(this->get_tx_frequency(chan), _tx_bypass_amp, chan_sel); } return gain; } double magnesium_radio_ctrl_impl::_get_all_gain( - const size_t /* chan */, - const direction_t dir -) { + const size_t /* chan */, const direction_t dir) +{ UHD_LOG_TRACE(unique_id(), "Getting all gain "); if (dir == RX_DIRECTION) { - return _all_rx_gain; + return _all_rx_gain; } return _all_tx_gain; } @@ -89,14 +86,12 @@ double magnesium_radio_ctrl_impl::_get_all_gain( * DSA Controls *****************************************************************************/ double magnesium_radio_ctrl_impl::_dsa_set_att( - const double att, - const size_t chan, - const direction_t dir -) { + const double att, const size_t chan, const direction_t dir) +{ UHD_LOG_TRACE(unique_id(), - __func__ << - "(att=" << "att dB, chan=" << chan << ", dir=" << dir << ")") - const uint32_t dsa_val = 2*att; + __func__ << "(att=" + << "att dB, chan=" << chan << ", dir=" << dir << ")") + const uint32_t dsa_val = 2 * att; _set_dsa_val(chan, dir, dsa_val); if (dir == RX_DIRECTION or dir == DX_DIRECTION) { @@ -109,33 +104,29 @@ double magnesium_radio_ctrl_impl::_dsa_set_att( } double magnesium_radio_ctrl_impl::_dsa_get_att( - const size_t /*chan*/, - const direction_t dir -) { + const size_t /*chan*/, const direction_t dir) +{ if (dir == RX_DIRECTION) { - return _dsa_rx_att; + return _dsa_rx_att; } return _dsa_tx_att; } void magnesium_radio_ctrl_impl::_set_dsa_val( - const size_t chan, - const direction_t dir, - const uint32_t dsa_val -) { + const size_t chan, const direction_t dir, const uint32_t dsa_val) +{ // The DSA register holds 12 bits. The lower 6 bits are for RX, the upper // 6 bits are for TX. - if (dir == RX_DIRECTION or dir == DX_DIRECTION){ + if (dir == RX_DIRECTION or dir == DX_DIRECTION) { UHD_LOG_TRACE(unique_id(), __func__ << "(chan=" << chan << ", dir=RX" - << ", dsa_val=" << dsa_val << ")") + << ", dsa_val=" << dsa_val << ")") _gpio[chan]->set_gpio_out(dsa_val, 0x003F); } - if (dir == TX_DIRECTION or dir == DX_DIRECTION){ + if (dir == TX_DIRECTION or dir == DX_DIRECTION) { UHD_LOG_TRACE(unique_id(), __func__ << "(chan=" << chan << ", dir=TX" - << ", dsa_val=" << dsa_val << ")") - _gpio[chan]->set_gpio_out(dsa_val<<6, 0x0FC0); + << ", dsa_val=" << dsa_val << ")") + _gpio[chan]->set_gpio_out(dsa_val << 6, 0x0FC0); } } - 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 952cebdf8..c216b0777 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp @@ -7,20 +7,20 @@ #include "magnesium_radio_ctrl_impl.hpp" #include "magnesium_constants.hpp" #include "magnesium_gain_table.hpp" -#include <uhd/utils/log.hpp> +#include <uhd/exception.hpp> #include <uhd/rfnoc/node_ctrl_base.hpp> #include <uhd/transport/chdr.hpp> -#include <uhd/utils/algorithm.hpp> -#include <uhd/utils/math.hpp> #include <uhd/types/direction.hpp> #include <uhd/types/eeprom.hpp> -#include <uhd/exception.hpp> +#include <uhd/utils/algorithm.hpp> +#include <uhd/utils/log.hpp> +#include <uhd/utils/math.hpp> #include <boost/algorithm/string.hpp> -#include <boost/make_shared.hpp> #include <boost/format.hpp> -#include <sstream> +#include <boost/make_shared.hpp> #include <cmath> #include <cstdlib> +#include <sstream> using namespace uhd; using namespace uhd::usrp; @@ -28,76 +28,69 @@ using namespace uhd::rfnoc; using namespace uhd::math::fp_compare; namespace { - /************************************************************************** - * ADF4351 Controls - *************************************************************************/ - /*! - * \param lo_iface Reference to the LO object - * \param freq Frequency (in Hz) of the tone to be generated from the LO - * \param ref_clock_freq Frequency (in Hz) of the reference clock at the - * PLL input of the LO - * \param int_n_mode Integer-N mode on or off - */ - double _lo_set_frequency( - adf435x_iface::sptr lo_iface, - const double freq, - const double ref_clock_freq, - const bool int_n_mode - ) { - UHD_LOG_TRACE("MG/ADF4351", - "Attempting to tune low band LO to " << freq << - " Hz with ref clock freq " << ref_clock_freq); - lo_iface->set_feedback_select(adf435x_iface::FB_SEL_DIVIDED); - lo_iface->set_reference_freq(ref_clock_freq); - lo_iface->set_prescaler(adf435x_iface::PRESCALER_4_5); - const double actual_freq = lo_iface->set_frequency(freq, int_n_mode); - lo_iface->set_output_power( - adf435x_iface::RF_OUTPUT_A, - adf435x_iface::OUTPUT_POWER_2DBM - ); - lo_iface->set_output_power( - adf435x_iface::RF_OUTPUT_B, - adf435x_iface::OUTPUT_POWER_2DBM - ); - lo_iface->set_charge_pump_current( - adf435x_iface::CHARGE_PUMP_CURRENT_0_31MA); - return actual_freq; - } - - /*! Configure and enable LO - * - * Will tune it to requested frequency and enable outputs. - * - * \param lo_iface Reference to the LO object - * \param lo_freq Frequency (in Hz) of the tone to be generated from the LO - * \param ref_clock_freq Frequency (in Hz) of the reference clock at the - * PLL input of the LO - * \param int_n_mode Integer-N mode on or off - * \returns the actual frequency the LO is running at - */ - double _lo_enable( - adf435x_iface::sptr lo_iface, - const double lo_freq, - const double ref_clock_freq, - const bool int_n_mode - ) { - const double actual_lo_freq = - _lo_set_frequency(lo_iface, lo_freq, ref_clock_freq, int_n_mode); - lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_A, true); - lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_B, true); - lo_iface->commit(); - return actual_lo_freq; - } +/************************************************************************** + * ADF4351 Controls + *************************************************************************/ +/*! + * \param lo_iface Reference to the LO object + * \param freq Frequency (in Hz) of the tone to be generated from the LO + * \param ref_clock_freq Frequency (in Hz) of the reference clock at the + * PLL input of the LO + * \param int_n_mode Integer-N mode on or off + */ +double _lo_set_frequency(adf435x_iface::sptr lo_iface, + const double freq, + const double ref_clock_freq, + const bool int_n_mode) +{ + UHD_LOG_TRACE("MG/ADF4351", + "Attempting to tune low band LO to " << freq << " Hz with ref clock freq " + << ref_clock_freq); + lo_iface->set_feedback_select(adf435x_iface::FB_SEL_DIVIDED); + lo_iface->set_reference_freq(ref_clock_freq); + lo_iface->set_prescaler(adf435x_iface::PRESCALER_4_5); + const double actual_freq = lo_iface->set_frequency(freq, int_n_mode); + lo_iface->set_output_power( + adf435x_iface::RF_OUTPUT_A, adf435x_iface::OUTPUT_POWER_2DBM); + lo_iface->set_output_power( + adf435x_iface::RF_OUTPUT_B, adf435x_iface::OUTPUT_POWER_2DBM); + lo_iface->set_charge_pump_current(adf435x_iface::CHARGE_PUMP_CURRENT_0_31MA); + return actual_freq; +} + +/*! Configure and enable LO + * + * Will tune it to requested frequency and enable outputs. + * + * \param lo_iface Reference to the LO object + * \param lo_freq Frequency (in Hz) of the tone to be generated from the LO + * \param ref_clock_freq Frequency (in Hz) of the reference clock at the + * PLL input of the LO + * \param int_n_mode Integer-N mode on or off + * \returns the actual frequency the LO is running at + */ +double _lo_enable(adf435x_iface::sptr lo_iface, + const double lo_freq, + const double ref_clock_freq, + const bool int_n_mode) +{ + const double actual_lo_freq = + _lo_set_frequency(lo_iface, lo_freq, ref_clock_freq, int_n_mode); + lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_A, true); + lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_B, true); + lo_iface->commit(); + return actual_lo_freq; +} - /*! Disable LO - */ - void _lo_disable(adf435x_iface::sptr lo_iface) - { - lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_A, false); - lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_B, false); - lo_iface->commit(); - } +/*! Disable LO + */ +void _lo_disable(adf435x_iface::sptr lo_iface) +{ + lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_A, false); + lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_B, false); + lo_iface->commit(); } +} // namespace /****************************************************************************** @@ -107,10 +100,9 @@ UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(magnesium_radio_ctrl) { UHD_LOG_TRACE(unique_id(), "Entering magnesium_radio_ctrl_impl ctor..."); const char radio_slot_name[2] = {'A', 'B'}; - _radio_slot = radio_slot_name[get_block_id().get_block_count()]; + _radio_slot = radio_slot_name[get_block_id().get_block_count()]; UHD_LOG_TRACE(unique_id(), "Radio slot: " << _radio_slot); - _rpc_prefix = - (_radio_slot == "A") ? "db_0_" : "db_1_"; + _rpc_prefix = (_radio_slot == "A") ? "db_0_" : "db_1_"; _init_defaults(); _init_peripherals(); @@ -135,17 +127,16 @@ double magnesium_radio_ctrl_impl::set_rate(double requested_rate) const double rate = rates.clip(requested_rate); if (!math::frequencies_are_equal(requested_rate, rate)) { - UHD_LOG_WARNING(unique_id(), - "Coercing requested sample rate from " << (requested_rate/1e6) << - " to " << (rate/1e6) - ); + UHD_LOG_WARNING(unique_id(), + "Coercing requested sample rate from " << (requested_rate / 1e6) << " to " + << (rate / 1e6)); } const double current_rate = get_rate(); if (math::frequencies_are_equal(current_rate, rate)) { - UHD_LOG_DEBUG(unique_id(), - "Rate is already at " << rate << ". Skipping set_rate()"); - return current_rate; + UHD_LOG_DEBUG( + unique_id(), "Rate is already at " << rate << ". Skipping set_rate()"); + return current_rate; } std::lock_guard<std::mutex> l(_set_lock); @@ -159,84 +150,72 @@ double magnesium_radio_ctrl_impl::set_rate(double requested_rate) set_tx_frequency(get_tx_frequency(0), 0); // Gain and bandwidth need to be looped: for (size_t radio_idx = 0; radio_idx < _get_num_radios(); radio_idx++) { - set_rx_gain(get_rx_gain(radio_idx), radio_idx); - set_tx_gain(get_rx_gain(radio_idx), radio_idx); - set_rx_bandwidth(get_rx_bandwidth(radio_idx), radio_idx); - set_tx_bandwidth(get_tx_bandwidth(radio_idx), radio_idx); + set_rx_gain(get_rx_gain(radio_idx), radio_idx); + set_tx_gain(get_rx_gain(radio_idx), radio_idx); + set_rx_bandwidth(get_rx_bandwidth(radio_idx), radio_idx); + set_tx_bandwidth(get_tx_bandwidth(radio_idx), radio_idx); } radio_ctrl_impl::set_rate(new_rate); return new_rate; } -void magnesium_radio_ctrl_impl::set_tx_antenna( - const std::string &ant, - const size_t chan -) { +void magnesium_radio_ctrl_impl::set_tx_antenna(const std::string& ant, const size_t chan) +{ if (ant != get_tx_antenna(chan)) { - throw uhd::value_error(str( - boost::format("[%s] Requesting invalid TX antenna value: %s") - % unique_id() - % ant - )); + throw uhd::value_error( + str(boost::format("[%s] Requesting invalid TX antenna value: %s") + % unique_id() % ant)); } // We can't actually set the TX antenna, so let's stop here. } -void magnesium_radio_ctrl_impl::set_rx_antenna( - const std::string &ant, - const size_t chan -) { +void magnesium_radio_ctrl_impl::set_rx_antenna(const std::string& ant, const size_t chan) +{ UHD_ASSERT_THROW(chan <= MAGNESIUM_NUM_CHANS); - if (std::find(MAGNESIUM_RX_ANTENNAS.begin(), - MAGNESIUM_RX_ANTENNAS.end(), - ant) == MAGNESIUM_RX_ANTENNAS.end()) { - throw uhd::value_error(str( - boost::format("[%s] Requesting invalid RX antenna value: %s") - % unique_id() - % ant - )); - } - UHD_LOG_TRACE(unique_id(), - "Setting RX antenna to " << ant << " for chan " << chan); - magnesium_cpld_ctrl::chan_sel_t chan_sel = - chan == 0 ? magnesium_cpld_ctrl::CHAN1 : magnesium_cpld_ctrl::CHAN2; + if (std::find(MAGNESIUM_RX_ANTENNAS.begin(), MAGNESIUM_RX_ANTENNAS.end(), ant) + == MAGNESIUM_RX_ANTENNAS.end()) { + throw uhd::value_error( + str(boost::format("[%s] Requesting invalid RX antenna value: %s") + % unique_id() % ant)); + } + UHD_LOG_TRACE(unique_id(), "Setting RX antenna to " << ant << " for chan " << chan); + magnesium_cpld_ctrl::chan_sel_t chan_sel = chan == 0 ? magnesium_cpld_ctrl::CHAN1 + : magnesium_cpld_ctrl::CHAN2; _update_atr_switches(chan_sel, RX_DIRECTION, ant); radio_ctrl_impl::set_rx_antenna(ant, chan); } double magnesium_radio_ctrl_impl::set_tx_frequency( - const double req_freq, - const size_t chan -) { + const double req_freq, const size_t chan) +{ const double freq = MAGNESIUM_FREQ_RANGE.clip(req_freq); - UHD_LOG_TRACE(unique_id(), - "set_tx_frequency(f=" << freq << ", chan=" << chan << ")"); - _desired_rf_freq[TX_DIRECTION]=freq; + UHD_LOG_TRACE(unique_id(), "set_tx_frequency(f=" << freq << ", chan=" << chan << ")"); + _desired_rf_freq[TX_DIRECTION] = freq; std::lock_guard<std::mutex> l(_set_lock); // We need to set the switches on both channels, because they share an LO. // This way, if we tune channel 0 it will not put channel 1 into a bad // state. _update_tx_freq_switches(freq, _tx_bypass_amp, magnesium_cpld_ctrl::BOTH); - const std::string ad9371_source = this->get_tx_lo_source(MAGNESIUM_LO1, chan); + const std::string ad9371_source = this->get_tx_lo_source(MAGNESIUM_LO1, chan); const std::string adf4351_source = this->get_tx_lo_source(MAGNESIUM_LO2, chan); UHD_ASSERT_THROW(adf4351_source == "internal"); double coerced_if_freq = freq; if (_map_freq_to_tx_band(freq) == tx_band::LOWBAND) { - _is_low_band[TX_DIRECTION] = true; + _is_low_band[TX_DIRECTION] = true; const double desired_low_freq = MAGNESIUM_TX_IF_FREQ - freq; coerced_if_freq = - this->_set_tx_lo_freq(adf4351_source, MAGNESIUM_LO2, desired_low_freq, chan) + freq; + this->_set_tx_lo_freq(adf4351_source, MAGNESIUM_LO2, desired_low_freq, chan) + + freq; UHD_LOG_TRACE(unique_id(), "coerced_if_freq = " << coerced_if_freq); } else { _is_low_band[TX_DIRECTION] = false; _lo_disable(_tx_lo); } // external LO required to tune at 2xdesired_frequency. - const double desired_if_freq = (ad9371_source == "internal") ? - coerced_if_freq : - 2*coerced_if_freq; + const double desired_if_freq = (ad9371_source == "internal") ? coerced_if_freq + : 2 * coerced_if_freq; this->_set_tx_lo_freq(ad9371_source, MAGNESIUM_LO1, desired_if_freq, chan); this->_update_freq(chan, TX_DIRECTION); @@ -245,81 +224,69 @@ double magnesium_radio_ctrl_impl::set_tx_frequency( } void magnesium_radio_ctrl_impl::_update_gain( - const size_t chan, - const uhd::direction_t dir -) { - const std::string fe = - (dir == TX_DIRECTION) ? "tx_frontends" : "rx_frontends"; - const double freq = (dir == TX_DIRECTION) ? - this->get_tx_frequency(chan) : - this->get_rx_frequency(chan); + const size_t chan, const uhd::direction_t dir) +{ + const std::string fe = (dir == TX_DIRECTION) ? "tx_frontends" : "rx_frontends"; + const double freq = (dir == TX_DIRECTION) ? this->get_tx_frequency(chan) + : this->get_rx_frequency(chan); this->_set_all_gain(this->_get_all_gain(chan, dir), freq, chan, dir); } void magnesium_radio_ctrl_impl::_update_freq( - const size_t chan, - const uhd::direction_t dir -) { - const std::string ad9371_source = dir == TX_DIRECTION ? - this->get_tx_lo_source(MAGNESIUM_LO1, chan) : - this->get_rx_lo_source(MAGNESIUM_LO1, chan) - ; - - const double ad9371_freq = ad9371_source == "external" ? - _ad9371_freq[dir]/2 : - _ad9371_freq[dir] - ; - const double rf_freq = _is_low_band[dir] ? - ad9371_freq - _adf4351_freq[dir] : - ad9371_freq - ; - - UHD_LOG_TRACE(unique_id(), - "RF freq = " << rf_freq); - UHD_ASSERT_THROW(fp_compare_epsilon<double>(rf_freq) >= 0); - UHD_ASSERT_THROW( - fp_compare_epsilon<double>(std::abs(rf_freq - _desired_rf_freq[dir])) <= _master_clock_rate/2); - if (dir == RX_DIRECTION){ + const size_t chan, const uhd::direction_t dir) +{ + const std::string ad9371_source = dir == TX_DIRECTION + ? this->get_tx_lo_source(MAGNESIUM_LO1, chan) + : this->get_rx_lo_source(MAGNESIUM_LO1, chan); + + const double ad9371_freq = ad9371_source == "external" ? _ad9371_freq[dir] / 2 + : _ad9371_freq[dir]; + const double rf_freq = _is_low_band[dir] ? ad9371_freq - _adf4351_freq[dir] + : ad9371_freq; + + UHD_LOG_TRACE(unique_id(), "RF freq = " << rf_freq); + UHD_ASSERT_THROW(fp_compare_epsilon<double>(rf_freq) >= 0); + UHD_ASSERT_THROW(fp_compare_epsilon<double>(std::abs(rf_freq - _desired_rf_freq[dir])) + <= _master_clock_rate / 2); + if (dir == RX_DIRECTION) { radio_ctrl_impl::set_rx_frequency(rf_freq, chan); - }else if (dir == TX_DIRECTION){ + } else if (dir == TX_DIRECTION) { radio_ctrl_impl::set_tx_frequency(rf_freq, chan); - }else{ + } else { UHD_THROW_INVALID_CODE_PATH(); } } double magnesium_radio_ctrl_impl::set_rx_frequency( - const double req_freq, - const size_t chan -) { + const double req_freq, const size_t chan) +{ const double freq = MAGNESIUM_FREQ_RANGE.clip(req_freq); - UHD_LOG_TRACE(unique_id(), - "set_rx_frequency(f=" << freq << ", chan=" << chan << ")"); - _desired_rf_freq[RX_DIRECTION]=freq; + UHD_LOG_TRACE(unique_id(), "set_rx_frequency(f=" << freq << ", chan=" << chan << ")"); + _desired_rf_freq[RX_DIRECTION] = freq; std::lock_guard<std::mutex> l(_set_lock); // We need to set the switches on both channels, because they share an LO. // This way, if we tune channel 0 it will not put channel 1 into a bad // state. _update_rx_freq_switches(freq, _rx_bypass_lnas, magnesium_cpld_ctrl::BOTH); - const std::string ad9371_source = this->get_rx_lo_source(MAGNESIUM_LO1, chan); + const std::string ad9371_source = this->get_rx_lo_source(MAGNESIUM_LO1, chan); const std::string adf4351_source = this->get_rx_lo_source(MAGNESIUM_LO2, chan); UHD_ASSERT_THROW(adf4351_source == "internal"); double coerced_if_freq = freq; if (_map_freq_to_rx_band(freq) == rx_band::LOWBAND) { - _is_low_band[RX_DIRECTION] = true; + _is_low_band[RX_DIRECTION] = true; const double desired_low_freq = MAGNESIUM_RX_IF_FREQ - freq; coerced_if_freq = - this->_set_rx_lo_freq(adf4351_source, MAGNESIUM_LO2, desired_low_freq, chan) + freq; + this->_set_rx_lo_freq(adf4351_source, MAGNESIUM_LO2, desired_low_freq, chan) + + freq; UHD_LOG_TRACE(unique_id(), "coerced_if_freq = " << coerced_if_freq); } else { _is_low_band[RX_DIRECTION] = false; _lo_disable(_rx_lo); } // external LO required to tune at 2xdesired_frequency. - const double desired_if_freq = ad9371_source == "internal" ? - coerced_if_freq : - 2*coerced_if_freq; + const double desired_if_freq = ad9371_source == "internal" ? coerced_if_freq + : 2 * coerced_if_freq; this->_set_rx_lo_freq(ad9371_source, MAGNESIUM_LO1, desired_if_freq, chan); @@ -329,25 +296,20 @@ double magnesium_radio_ctrl_impl::set_rx_frequency( return radio_ctrl_impl::get_rx_frequency(chan); } -double magnesium_radio_ctrl_impl::get_tx_frequency( - const size_t chan) +double magnesium_radio_ctrl_impl::get_tx_frequency(const size_t chan) { - UHD_LOG_TRACE(unique_id(), - "get_tx_frequency(chan=" << chan << ")"); + UHD_LOG_TRACE(unique_id(), "get_tx_frequency(chan=" << chan << ")"); return radio_ctrl_impl::get_tx_frequency(chan); } -double magnesium_radio_ctrl_impl::get_rx_frequency( - const size_t chan) +double magnesium_radio_ctrl_impl::get_rx_frequency(const size_t chan) { - UHD_LOG_TRACE(unique_id(), - "get_rx_frequency(chan=" << chan << ")"); + UHD_LOG_TRACE(unique_id(), "get_rx_frequency(chan=" << chan << ")"); return radio_ctrl_impl::get_rx_frequency(chan); } double magnesium_radio_ctrl_impl::set_rx_bandwidth( - const double bandwidth, - const size_t chan -) { + const double bandwidth, const size_t chan) +{ std::lock_guard<std::mutex> l(_set_lock); _ad9371->set_bandwidth(bandwidth, chan, RX_DIRECTION); // FIXME: setting analog bandwidth on AD9371 take no effect. @@ -359,9 +321,8 @@ double magnesium_radio_ctrl_impl::set_rx_bandwidth( } double magnesium_radio_ctrl_impl::set_tx_bandwidth( - const double bandwidth, - const size_t chan -) { + const double bandwidth, const size_t chan) +{ std::lock_guard<std::mutex> l(_set_lock); _ad9371->set_bandwidth(bandwidth, chan, TX_DIRECTION); // FIXME: setting analog bandwidth on AD9371 take no effect. @@ -369,182 +330,155 @@ double magnesium_radio_ctrl_impl::set_tx_bandwidth( UHD_LOG_WARNING(unique_id(), "set_tx_bandwidth take no effect on AD9371. " "Default analog bandwidth is 100MHz"); - return AD9371_TX_MAX_BANDWIDTH ; + return AD9371_TX_MAX_BANDWIDTH; } -double magnesium_radio_ctrl_impl::set_tx_gain( - const double gain, - const size_t chan -) { +double magnesium_radio_ctrl_impl::set_tx_gain(const double gain, const size_t chan) +{ std::lock_guard<std::mutex> l(_set_lock); - UHD_LOG_TRACE(unique_id(), - "set_tx_gain(gain=" << gain << ", chan=" << chan << ")"); - const double coerced_gain = _set_all_gain( - gain, - this->get_tx_frequency(chan), - chan, - TX_DIRECTION - ); + UHD_LOG_TRACE(unique_id(), "set_tx_gain(gain=" << gain << ", chan=" << chan << ")"); + const double coerced_gain = + _set_all_gain(gain, this->get_tx_frequency(chan), chan, TX_DIRECTION); radio_ctrl_impl::set_tx_gain(coerced_gain, chan); return coerced_gain; } double magnesium_radio_ctrl_impl::_set_tx_gain( - const std::string &name, - const double gain, - const size_t chan -) { + 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 << ")"); - UHD_LOG_TRACE(unique_id(), + UHD_LOG_TRACE(unique_id(), "_set_tx_gain(name=" << name << ", gain=" << gain << ", chan=" << chan << ")"); double clip_gain = 0; - if (name == MAGNESIUM_GAIN1){ + if (name == MAGNESIUM_GAIN1) { clip_gain = uhd::clip(gain, AD9371_MIN_TX_GAIN, AD9371_MAX_TX_GAIN); _ad9371_att[TX_DIRECTION] = clip_gain; - }else if (name == MAGNESIUM_GAIN2){ - clip_gain = uhd::clip(gain, DSA_MIN_GAIN, DSA_MAX_GAIN); + } else if (name == MAGNESIUM_GAIN2) { + clip_gain = uhd::clip(gain, DSA_MIN_GAIN, DSA_MAX_GAIN); _dsa_att[TX_DIRECTION] = clip_gain; - }else if (name == MAGNESIUM_AMP){ - clip_gain = gain > 0.0 ? AMP_MAX_GAIN: AMP_MIN_GAIN; + } else if (name == MAGNESIUM_AMP) { + clip_gain = gain > 0.0 ? AMP_MAX_GAIN : AMP_MIN_GAIN; _amp_bypass[TX_DIRECTION] = clip_gain == 0.0; - }else { + } 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), + 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 - ); + TX_DIRECTION); return clip_gain; } double magnesium_radio_ctrl_impl::_get_tx_gain( - const std::string &name, - const size_t /*chan*/ -) { + const std::string& name, const size_t /*chan*/ +) +{ std::lock_guard<std::mutex> l(_set_lock); - if (name == MAGNESIUM_GAIN1){ + if (name == MAGNESIUM_GAIN1) { return _ad9371_att[TX_DIRECTION]; - }else if (name == MAGNESIUM_GAIN2){ + } 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 { + } 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 -) { +double magnesium_radio_ctrl_impl::set_rx_gain(const double gain, const size_t chan) +{ std::lock_guard<std::mutex> l(_set_lock); - UHD_LOG_TRACE(unique_id(), - "set_rx_gain(gain=" << gain << ", chan=" << chan << ")"); - const double coerced_gain = _set_all_gain( - gain, - this->get_rx_frequency(chan), - chan, - RX_DIRECTION - ); + UHD_LOG_TRACE(unique_id(), "set_rx_gain(gain=" << gain << ", chan=" << chan << ")"); + const double coerced_gain = + _set_all_gain(gain, this->get_rx_frequency(chan), chan, RX_DIRECTION); radio_ctrl_impl::set_rx_gain(coerced_gain, chan); return coerced_gain; } double magnesium_radio_ctrl_impl::_set_rx_gain( - const std::string &name, - const double gain, - const size_t chan -) { + 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 << ")"); double clip_gain = 0; - if (name == MAGNESIUM_GAIN1){ + if (name == MAGNESIUM_GAIN1) { clip_gain = uhd::clip(gain, AD9371_MIN_RX_GAIN, AD9371_MAX_RX_GAIN); _ad9371_att[RX_DIRECTION] = clip_gain; - }else if (name == MAGNESIUM_GAIN2){ - clip_gain = uhd::clip(gain, DSA_MIN_GAIN, DSA_MAX_GAIN); + } else if (name == MAGNESIUM_GAIN2) { + clip_gain = uhd::clip(gain, DSA_MIN_GAIN, DSA_MAX_GAIN); _dsa_att[RX_DIRECTION] = clip_gain; - }else if (name == MAGNESIUM_AMP){ - clip_gain = gain > 0.0 ? AMP_MAX_GAIN: AMP_MIN_GAIN; + } else if (name == MAGNESIUM_AMP) { + clip_gain = gain > 0.0 ? AMP_MAX_GAIN : AMP_MIN_GAIN; _amp_bypass[RX_DIRECTION] = clip_gain == 0.0; - }else { + } 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), + 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 - ); + RX_DIRECTION); return clip_gain; // not really any coreced here (only clip) for individual gain } double magnesium_radio_ctrl_impl::_get_rx_gain( - const std::string &name, - const size_t /*chan*/ -) { + const std::string& name, const size_t /*chan*/ +) +{ std::lock_guard<std::mutex> l(_set_lock); - if (name == MAGNESIUM_GAIN1){ + if (name == MAGNESIUM_GAIN1) { return _ad9371_att[RX_DIRECTION]; - }else if (name == MAGNESIUM_GAIN2){ + } 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{ + } 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*/ -) { - return std::vector<std::string> {MAGNESIUM_LO1, MAGNESIUM_LO2}; +std::vector<std::string> magnesium_radio_ctrl_impl::get_rx_lo_names(const size_t /*chan*/ +) +{ + return std::vector<std::string>{MAGNESIUM_LO1, MAGNESIUM_LO2}; } std::vector<std::string> magnesium_radio_ctrl_impl::get_rx_lo_sources( - const std::string &name, - const size_t /*chan*/ -) { - if (name == MAGNESIUM_LO2){ - return std::vector<std::string> { "internal" }; - }else if (name == MAGNESIUM_LO1){ - return std::vector<std::string> { "internal", "external" }; - }else { + const std::string& name, const size_t /*chan*/ +) +{ + if (name == MAGNESIUM_LO2) { + return std::vector<std::string>{"internal"}; + } else if (name == MAGNESIUM_LO1) { + return std::vector<std::string>{"internal", "external"}; + } else { throw uhd::value_error("Could not find LO stage " + name); - } + } } freq_range_t magnesium_radio_ctrl_impl::get_rx_lo_freq_range( - const std::string & name, - const size_t /*chan*/ -) { - if (name == MAGNESIUM_LO1){ + const std::string& name, const size_t /*chan*/ +) +{ + if (name == MAGNESIUM_LO1) { return freq_range_t{ADF4351_MIN_FREQ, ADF4351_MAX_FREQ}; - } - else if(name == MAGNESIUM_LO2){ + } else if (name == MAGNESIUM_LO2) { return freq_range_t{AD9371_MIN_FREQ, AD9371_MAX_FREQ}; - } - else { + } else { throw uhd::value_error("Could not find LO stage " + name); } } void magnesium_radio_ctrl_impl::set_rx_lo_source( - const std::string &src, - const std::string &name, - const size_t /*chan*/ -) { - //TODO: checking what options are there + const std::string& src, const std::string& name, const size_t /*chan*/ +) +{ + // TODO: checking what options are there std::lock_guard<std::mutex> l(_set_lock); UHD_LOG_TRACE(unique_id(), "Setting RX LO " << name << " to " << src); @@ -552,180 +486,179 @@ void magnesium_radio_ctrl_impl::set_rx_lo_source( _ad9371->set_lo_source(src, RX_DIRECTION); } else { UHD_LOG_ERROR(unique_id(), - "RX LO " << name << " does not support setting source to " << src); + "RX LO " << name << " does not support setting source to " << src); } } const std::string magnesium_radio_ctrl_impl::get_rx_lo_source( - const std::string &name, - const size_t /*chan*/ -) { - if (name == MAGNESIUM_LO1){ - //TODO: should we use this from cache? + const std::string& name, const size_t /*chan*/ +) +{ + if (name == MAGNESIUM_LO1) { + // TODO: should we use this from cache? return _ad9371->get_lo_source(RX_DIRECTION); } return "internal"; } -double magnesium_radio_ctrl_impl::_set_rx_lo_freq( - const std::string source, +double magnesium_radio_ctrl_impl::_set_rx_lo_freq(const std::string source, const std::string name, const double freq, - const size_t chan -){ + const size_t chan) +{ double coerced_lo_freq = freq; - if (source != "internal"){ - UHD_LOG_WARNING(unique_id(), "LO source is not internal. This set frequency will be ignored"); - if(name == MAGNESIUM_LO1){ + if (source != "internal") { + UHD_LOG_WARNING( + unique_id(), "LO source is not internal. This set frequency will be ignored"); + if (name == MAGNESIUM_LO1) { // handle ad9371 external LO case - coerced_lo_freq = freq; + coerced_lo_freq = freq; _ad9371_freq[RX_DIRECTION] = coerced_lo_freq; } - }else { - if(name == MAGNESIUM_LO1){ - coerced_lo_freq = _ad9371->set_frequency(freq, chan, RX_DIRECTION); + } else { + if (name == MAGNESIUM_LO1) { + coerced_lo_freq = _ad9371->set_frequency(freq, chan, RX_DIRECTION); _ad9371_freq[RX_DIRECTION] = coerced_lo_freq; - }else if (name == MAGNESIUM_LO2 ){ + } else if (name == MAGNESIUM_LO2) { // TODO: no hardcode the init_n_mode - coerced_lo_freq = _lo_enable(_rx_lo, freq, _master_clock_rate, false); + coerced_lo_freq = _lo_enable(_rx_lo, freq, _master_clock_rate, false); _adf4351_freq[RX_DIRECTION] = coerced_lo_freq; - }else { - UHD_LOG_WARNING(unique_id(), "There's no LO with this name of "<<name << " in the system. This set rx lo freq will be ignored"); + } else { + UHD_LOG_WARNING(unique_id(), + "There's no LO with this name of " + << name << " in the system. This set rx lo freq will be ignored"); }; } return coerced_lo_freq; } double magnesium_radio_ctrl_impl::set_rx_lo_freq( - double freq, - const std::string &name, - const size_t chan -) { - UHD_LOG_TRACE(unique_id(), "Setting rx lo frequency for " <<name << " with freq = " <<freq); + double freq, const std::string& name, const size_t chan) +{ + UHD_LOG_TRACE( + unique_id(), "Setting rx lo frequency for " << name << " with freq = " << freq); std::lock_guard<std::mutex> l(_set_lock); - std::string source = this->get_rx_lo_source(name, chan); + std::string source = this->get_rx_lo_source(name, chan); const double coerced_lo_freq = this->_set_rx_lo_freq(source, name, freq, chan); - this->_update_freq(chan,RX_DIRECTION); - this->_update_gain(chan,RX_DIRECTION); + this->_update_freq(chan, RX_DIRECTION); + this->_update_gain(chan, RX_DIRECTION); return coerced_lo_freq; } double magnesium_radio_ctrl_impl::get_rx_lo_freq( - const std::string & name, - const size_t chan -) { - - UHD_LOG_TRACE(unique_id(),"Getting rx lo frequency for " <<name); - std::string source = this->get_rx_lo_source(name,chan); - if(name == MAGNESIUM_LO1){ + const std::string& name, const size_t chan) +{ + UHD_LOG_TRACE(unique_id(), "Getting rx lo frequency for " << name); + std::string source = this->get_rx_lo_source(name, chan); + if (name == MAGNESIUM_LO1) { return _ad9371_freq[RX_DIRECTION]; - }else if (name == "adf4531" ){ + } else if (name == "adf4531") { return _adf4351_freq[RX_DIRECTION]; - }else { - UHD_LOG_ERROR(unique_id(), "There's no LO with this name of "<<name << " in the system. This set rx lo freq will be ignored"); + } else { + UHD_LOG_ERROR(unique_id(), + "There's no LO with this name of " + << name << " in the system. This set rx lo freq will be ignored"); } UHD_THROW_INVALID_CODE_PATH(); } -//TX LO -std::vector<std::string> magnesium_radio_ctrl_impl::get_tx_lo_names( - const size_t /*chan*/ -) { - return std::vector<std::string> {MAGNESIUM_LO1, MAGNESIUM_LO2}; +// TX LO +std::vector<std::string> magnesium_radio_ctrl_impl::get_tx_lo_names(const size_t /*chan*/ +) +{ + return std::vector<std::string>{MAGNESIUM_LO1, MAGNESIUM_LO2}; } std::vector<std::string> magnesium_radio_ctrl_impl::get_tx_lo_sources( - const std::string &name, - const size_t /*chan*/ -) { - if (name == MAGNESIUM_LO2){ - return std::vector<std::string> { "internal" }; - }else if (name == MAGNESIUM_LO1){ - return std::vector<std::string> { "internal", "external" }; - }else { + const std::string& name, const size_t /*chan*/ +) +{ + if (name == MAGNESIUM_LO2) { + return std::vector<std::string>{"internal"}; + } else if (name == MAGNESIUM_LO1) { + return std::vector<std::string>{"internal", "external"}; + } else { throw uhd::value_error("Could not find LO stage " + name); - } + } } freq_range_t magnesium_radio_ctrl_impl::get_tx_lo_freq_range( - const std::string &name, - const size_t /*chan*/ -) { - if (name == MAGNESIUM_LO2){ + const std::string& name, const size_t /*chan*/ +) +{ + if (name == MAGNESIUM_LO2) { return freq_range_t{ADF4351_MIN_FREQ, ADF4351_MAX_FREQ}; - } - else if(name == MAGNESIUM_LO1){ + } else if (name == MAGNESIUM_LO1) { return freq_range_t{AD9371_MIN_FREQ, AD9371_MAX_FREQ}; - } - else { + } else { throw uhd::value_error("Could not find LO stage " + name); } } void magnesium_radio_ctrl_impl::set_tx_lo_source( - const std::string &src, - const std::string &name, - const size_t /*chan*/ -) { - //TODO: checking what options are there + const std::string& src, const std::string& name, const size_t /*chan*/ +) +{ + // TODO: checking what options are there std::lock_guard<std::mutex> l(_set_lock); UHD_LOG_TRACE(unique_id(), "Setting TX LO " << name << " to " << src); if (name == MAGNESIUM_LO1) { _ad9371->set_lo_source(src, TX_DIRECTION); } else { UHD_LOG_ERROR(unique_id(), - "TX LO " << name << " does not support setting source to " << src); + "TX LO " << name << " does not support setting source to " << src); } } const std::string magnesium_radio_ctrl_impl::get_tx_lo_source( - const std::string &name, - const size_t /*chan*/ -) { - if (name == MAGNESIUM_LO1){ - //TODO: should we use this from cache? + const std::string& name, const size_t /*chan*/ +) +{ + if (name == MAGNESIUM_LO1) { + // TODO: should we use this from cache? return _ad9371->get_lo_source(TX_DIRECTION); } return "internal"; } -double magnesium_radio_ctrl_impl::_set_tx_lo_freq( - const std::string source, +double magnesium_radio_ctrl_impl::_set_tx_lo_freq(const std::string source, const std::string name, const double freq, - const size_t chan -){ + const size_t chan) +{ double coerced_lo_freq = freq; - if (source != "internal"){ - UHD_LOG_WARNING(unique_id(), "LO source is not internal. This set frequency will be ignored"); - if(name == MAGNESIUM_LO1){ + if (source != "internal") { + UHD_LOG_WARNING( + unique_id(), "LO source is not internal. This set frequency will be ignored"); + if (name == MAGNESIUM_LO1) { // handle ad9371 external LO case - coerced_lo_freq = freq; + coerced_lo_freq = freq; _ad9371_freq[TX_DIRECTION] = coerced_lo_freq; } - }else { - if(name == MAGNESIUM_LO1){ - coerced_lo_freq = _ad9371->set_frequency(freq, chan, TX_DIRECTION); + } else { + if (name == MAGNESIUM_LO1) { + coerced_lo_freq = _ad9371->set_frequency(freq, chan, TX_DIRECTION); _ad9371_freq[TX_DIRECTION] = coerced_lo_freq; - }else if (name == MAGNESIUM_LO2 ){ + } else if (name == MAGNESIUM_LO2) { // TODO: no hardcode the int_n_mode const bool int_n_mode = false; coerced_lo_freq = _lo_enable(_tx_lo, freq, _master_clock_rate, int_n_mode); _adf4351_freq[TX_DIRECTION] = coerced_lo_freq; - }else { - UHD_LOG_WARNING(unique_id(), "There's no LO with this name of "<<name << " in the system. This set tx lo freq will be ignored"); + } else { + UHD_LOG_WARNING(unique_id(), + "There's no LO with this name of " + << name << " in the system. This set tx lo freq will be ignored"); }; } return coerced_lo_freq; } double magnesium_radio_ctrl_impl::set_tx_lo_freq( - double freq, - const std::string &name, - const size_t chan -) { - UHD_LOG_TRACE(unique_id(), "Setting tx lo frequency for " <<name << " with freq = " <<freq); - std::string source = this->get_tx_lo_source(name,chan); + double freq, const std::string& name, const size_t chan) +{ + UHD_LOG_TRACE( + unique_id(), "Setting tx lo frequency for " << name << " with freq = " << freq); + std::string source = this->get_tx_lo_source(name, chan); const double return_freq = this->_set_tx_lo_freq(source, name, freq, chan); this->_update_freq(chan, TX_DIRECTION); this->_update_gain(chan, TX_DIRECTION); @@ -733,61 +666,56 @@ double magnesium_radio_ctrl_impl::set_tx_lo_freq( } double magnesium_radio_ctrl_impl::get_tx_lo_freq( - const std::string & name, - const size_t chan -) { - UHD_LOG_TRACE(unique_id(),"Getting tx lo frequency for " <<name); - std::string source = this->get_tx_lo_source(name,chan); - if(name == MAGNESIUM_LO1){ + const std::string& name, const size_t chan) +{ + UHD_LOG_TRACE(unique_id(), "Getting tx lo frequency for " << name); + std::string source = this->get_tx_lo_source(name, chan); + if (name == MAGNESIUM_LO1) { return _ad9371_freq[TX_DIRECTION]; - }else if (name == MAGNESIUM_LO2){ + } else if (name == MAGNESIUM_LO2) { return _adf4351_freq[TX_DIRECTION]; - }else { - UHD_LOG_ERROR(unique_id(), "There's no LO with this name of "<<name << " in the system."); + } else { + UHD_LOG_ERROR( + unique_id(), "There's no LO with this name of " << name << " in the system."); }; UHD_THROW_INVALID_CODE_PATH(); } - size_t magnesium_radio_ctrl_impl::get_chan_from_dboard_fe( - const std::string &fe, const direction_t /* dir */ -) { + const std::string& fe, const direction_t /* dir */ +) +{ return boost::lexical_cast<size_t>(fe); } std::string magnesium_radio_ctrl_impl::get_dboard_fe_from_chan( - const size_t chan, - const direction_t /* dir */ -) { + const size_t chan, const direction_t /* dir */ +) +{ return std::to_string(chan); } void magnesium_radio_ctrl_impl::set_rpc_client( - uhd::rpc_client::sptr rpcc, - const uhd::device_addr_t &block_args -) { - _rpcc = rpcc; + uhd::rpc_client::sptr rpcc, const uhd::device_addr_t& block_args) +{ + _rpcc = rpcc; _block_args = block_args; UHD_LOG_TRACE(unique_id(), "Instantiating AD9371 control object..."); _ad9371 = magnesium_ad9371_iface::uptr( - new magnesium_ad9371_iface( - _rpcc, - (_radio_slot == "A") ? 0 : 1 - ) - ); + new magnesium_ad9371_iface(_rpcc, (_radio_slot == "A") ? 0 : 1)); if (block_args.has_key("identify")) { const std::string identify_val = block_args.get("identify"); - int identify_duration = std::atoi(identify_val.c_str()); + int identify_duration = std::atoi(identify_val.c_str()); if (identify_duration == 0) { identify_duration = 5; } UHD_LOG_INFO(unique_id(), "Running LED identification process for " << identify_duration - << " seconds."); + << " seconds."); _identify_with_leds(identify_duration); } @@ -795,68 +723,60 @@ void magnesium_radio_ctrl_impl::set_rpc_client( // in arguments from the device args. So if block_args contains a // master_clock_rate key, then it should better be whatever the device is // configured to do. - _master_clock_rate = _rpcc->request_with_token<double>( - _rpc_prefix + "get_master_clock_rate"); + _master_clock_rate = + _rpcc->request_with_token<double>(_rpc_prefix + "get_master_clock_rate"); if (block_args.cast<double>("master_clock_rate", _master_clock_rate) - != _master_clock_rate) { + != _master_clock_rate) { throw uhd::runtime_error(str( boost::format("Master clock rate mismatch. Device returns %f MHz, " "but should have been %f MHz.") % (_master_clock_rate / 1e6) - % (block_args.cast<double>( - "master_clock_rate", _master_clock_rate) / 1e6) - )); + % (block_args.cast<double>("master_clock_rate", _master_clock_rate) / 1e6))); } - UHD_LOG_DEBUG(unique_id(), - "Master Clock Rate is: " << (_master_clock_rate / 1e6) << " MHz."); + UHD_LOG_DEBUG( + unique_id(), "Master Clock Rate is: " << (_master_clock_rate / 1e6) << " MHz."); radio_ctrl_impl::set_rate(_master_clock_rate); // EEPROM paths subject to change FIXME const size_t db_idx = get_block_id().get_block_count(); _tree->access<eeprom_map_t>(_root_path / "eeprom") - .add_coerced_subscriber([this, db_idx](const eeprom_map_t& db_eeprom){ + .add_coerced_subscriber([this, db_idx](const eeprom_map_t& db_eeprom) { this->_rpcc->notify_with_token("set_db_eeprom", db_idx, db_eeprom); }) - .set_publisher([this, db_idx](){ - return this->_rpcc->request_with_token<eeprom_map_t>( - "get_db_eeprom", db_idx - ); - }) - ; + .set_publisher([this, db_idx]() { + return this->_rpcc->request_with_token<eeprom_map_t>("get_db_eeprom", db_idx); + }); // Init sensors - for (const auto &dir : std::vector<direction_t>{RX_DIRECTION, TX_DIRECTION}) { + for (const auto& dir : std::vector<direction_t>{RX_DIRECTION, TX_DIRECTION}) { for (size_t chan_idx = 0; chan_idx < MAGNESIUM_NUM_CHANS; chan_idx++) { _init_mpm_sensors(dir, chan_idx); } } } -bool magnesium_radio_ctrl_impl::get_lo_lock_status( - const direction_t dir -) { - if (not (bool(_rpcc))) { - UHD_LOG_DEBUG(unique_id(), - "Reported no LO lock due to lack of RPC connection."); +bool magnesium_radio_ctrl_impl::get_lo_lock_status(const direction_t dir) +{ + if (not(bool(_rpcc))) { + UHD_LOG_DEBUG(unique_id(), "Reported no LO lock due to lack of RPC connection."); return false; } const std::string trx = (dir == RX_DIRECTION) ? "rx" : "tx"; - const size_t chan = 0; // They're the same after all - const double freq = (dir == RX_DIRECTION) ? - get_rx_frequency(chan) : - get_tx_frequency(chan); + const size_t chan = 0; // They're the same after all + const double freq = (dir == RX_DIRECTION) ? get_rx_frequency(chan) + : get_tx_frequency(chan); - bool lo_lock = _rpcc->request_with_token<bool>( - _rpc_prefix + "get_ad9371_lo_lock", trx); + bool lo_lock = + _rpcc->request_with_token<bool>(_rpc_prefix + "get_ad9371_lo_lock", trx); UHD_LOG_TRACE(unique_id(), "AD9371 " << trx << " LO reports lock: " << (lo_lock ? "Yes" : "No")); if (lo_lock and _map_freq_to_rx_band(freq) == rx_band::LOWBAND) { - lo_lock = lo_lock && _rpcc->request_with_token<bool>( - _rpc_prefix + "get_lowband_lo_lock", trx); + lo_lock = + lo_lock + && _rpcc->request_with_token<bool>(_rpc_prefix + "get_lowband_lo_lock", trx); UHD_LOG_TRACE(unique_id(), - "ADF4351 " << trx << " LO reports lock: " - << (lo_lock ? "Yes" : "No")); + "ADF4351 " << trx << " LO reports lock: " << (lo_lock ? "Yes" : "No")); } return lo_lock; 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 3d35206ed..dcadb5dea 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp @@ -11,20 +11,19 @@ #ifndef INCLUDED_LIBUHD_RFNOC_MAGNESIUM_RADIO_CTRL_IMPL_HPP #define INCLUDED_LIBUHD_RFNOC_MAGNESIUM_RADIO_CTRL_IMPL_HPP +#include "magnesium_ad9371_iface.hpp" #include "magnesium_cpld_ctrl.hpp" #include "magnesium_cpld_regs.hpp" -#include "magnesium_ad9371_iface.hpp" #include <uhd/types/serial.hpp> #include <uhd/usrp/dboard_manager.hpp> #include <uhd/usrp/gpio_defs.hpp> -#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> -#include <uhdlib/rfnoc/rpc_block_ctrl.hpp> #include <uhdlib/rfnoc/radio_ctrl_impl.hpp> +#include <uhdlib/rfnoc/rpc_block_ctrl.hpp> #include <uhdlib/usrp/common/adf435x.hpp> +#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> #include <mutex> -namespace uhd { - namespace rfnoc { +namespace uhd { namespace rfnoc { /*! \brief RFNoC block / daughterboard driver for a "Magnesium" daughterboard. * @@ -49,14 +48,7 @@ public: }; //! Frequency bands for TX. Bands are a function of the analog filter banks - enum class tx_band { - INVALID_BAND, - LOWBAND, - BAND0, - BAND1, - BAND2, - BAND3 - }; + enum class tx_band { INVALID_BAND, LOWBAND, BAND0, BAND1, BAND2, BAND3 }; /************************************************************************ * Structors @@ -71,8 +63,8 @@ public: // not reimplemented here double set_rate(double rate); - void set_tx_antenna(const std::string &ant, const size_t chan); - void set_rx_antenna(const std::string &ant, const size_t chan); + void set_tx_antenna(const std::string& ant, const size_t chan); + void set_rx_antenna(const std::string& ant, const size_t chan); double set_tx_frequency(const double freq, const size_t chan); double set_rx_frequency(const double freq, const size_t chan); @@ -84,90 +76,59 @@ public: // RX LO std::vector<std::string> get_rx_lo_names(const size_t chan); std::vector<std::string> get_rx_lo_sources( - const std::string &name, - const size_t chan - ); - freq_range_t get_rx_lo_freq_range( - const std::string &name, - const size_t chan - ); + const std::string& name, const size_t chan); + freq_range_t get_rx_lo_freq_range(const std::string& name, const size_t chan); void set_rx_lo_source( - const std::string &src, - const std::string &name, - const size_t chan - ); - const std::string get_rx_lo_source( - const std::string &name, - const size_t chan - ); - - double set_rx_lo_freq( - double freq, - const std::string &name, - const size_t chan - ); - double get_rx_lo_freq(const std::string &name, const size_t chan); + const std::string& src, const std::string& name, const size_t chan); + const std::string get_rx_lo_source(const std::string& name, const size_t chan); + + double set_rx_lo_freq(double freq, const std::string& name, const size_t chan); + double get_rx_lo_freq(const std::string& name, const size_t chan); // TX LO std::vector<std::string> get_tx_lo_names(const size_t chan); std::vector<std::string> get_tx_lo_sources( - const std::string &name, - const size_t chan - ); - freq_range_t get_tx_lo_freq_range( - const std::string &name, - const size_t chan - ); + const std::string& name, const size_t chan); + freq_range_t get_tx_lo_freq_range(const std::string& name, const size_t chan); void set_tx_lo_source( - const std::string &src, - const std::string &name, - const size_t chan - ); - const std::string get_tx_lo_source( - const std::string &name, - const size_t chan - ); - - double set_tx_lo_freq( - double freq, - const std::string &name, - const size_t chan - ); - double get_tx_lo_freq(const std::string &name, const size_t chan); + const std::string& src, const std::string& name, const size_t chan); + const std::string get_tx_lo_source(const std::string& name, const size_t chan); + + double set_tx_lo_freq(double freq, const std::string& name, const size_t chan); + double get_tx_lo_freq(const std::string& name, const size_t chan); // 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); + 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); + 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); + 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); - void set_rpc_client( - uhd::rpc_client::sptr rpcc, - const uhd::device_addr_t &block_args - ); + void set_rpc_client(uhd::rpc_client::sptr rpcc, const uhd::device_addr_t& block_args); private: /************************************************************************** * Helpers *************************************************************************/ //! Set tx gain on each gain element - double _set_tx_gain(const std::string &name, const double gain, const size_t chan); + 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); + 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); + 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); + double _get_rx_gain(const std::string& name, const size_t chan); //! Initialize all the peripherals connected to this block void _init_peripherals(); @@ -176,18 +137,12 @@ private: void _init_defaults(); //! Init a subtree for the RF frontends - void _init_frontend_subtree( - uhd::property_tree::sptr subtree, - const size_t chan_idx - ); + void _init_frontend_subtree(uhd::property_tree::sptr subtree, const size_t chan_idx); //! Initialize property tree void _init_prop_tree(); - void _init_mpm_sensors( - const direction_t dir, - const size_t chan_idx - ); + void _init_mpm_sensors(const direction_t dir, const size_t chan_idx); //! Map a frequency in Hz to an rx_band value. Will return // rx_band::INVALID_BAND if the frequency is out of range. @@ -201,92 +156,57 @@ private: *************************************************************************/ //! Return LO lock status. Factors in current band (low/high) and // direction (TX/RX) - bool get_lo_lock_status( - const direction_t dir - ); + bool get_lo_lock_status(const direction_t dir); /************************************************************************** * Gain Controls (implemented in magnesium_radio_ctrl_gain.cpp) *************************************************************************/ //! Set the attenuation of the DSA - double _dsa_set_att( - const double att, - const size_t chan, - const direction_t dir - ); + double _dsa_set_att(const double att, const size_t chan, const direction_t dir); - double _dsa_get_att( - const size_t chan, - const direction_t dir - ); + double _dsa_get_att(const size_t chan, const direction_t dir); //! Write the DSA word - void _set_dsa_val( - const size_t chan, - const direction_t dir, - const uint32_t dsa_val - ); + void _set_dsa_val(const size_t chan, const direction_t dir, const uint32_t dsa_val); double _set_all_gain( - const double gain, - const double freq, - const size_t chan, - const direction_t dir - ); + const double gain, const double freq, const size_t chan, const direction_t dir); - double _get_all_gain( - const size_t chan, - const direction_t dir - ); + double _get_all_gain(const size_t chan, const direction_t dir); void _update_gain(const size_t chan, direction_t dir); - void _update_freq( - const size_t chan, - const uhd::direction_t dir - ); + void _update_freq(const size_t chan, const uhd::direction_t dir); /************************************************************************** * CPLD Controls (implemented in magnesium_radio_ctrl_cpld.cpp) *************************************************************************/ //! Blink the front-panel LEDs for \p identify_duration, then reset CPLD // and resume normal operation. - void _identify_with_leds( - const int identify_duration - ); + void _identify_with_leds(const int identify_duration); - void _update_rx_freq_switches( - const double freq, + void _update_rx_freq_switches(const double freq, const bool bypass_lnas, - const magnesium_cpld_ctrl::chan_sel_t chan_sel - ); + const magnesium_cpld_ctrl::chan_sel_t chan_sel); - void _update_tx_freq_switches( - const double freq, + void _update_tx_freq_switches(const double freq, const bool bypass_amps, - const magnesium_cpld_ctrl::chan_sel_t chan_sel - ); + const magnesium_cpld_ctrl::chan_sel_t chan_sel); - void _update_atr_switches( - const magnesium_cpld_ctrl::chan_sel_t chan, + void _update_atr_switches(const magnesium_cpld_ctrl::chan_sel_t chan, const direction_t dir, - const std::string &ant - ); + const std::string& ant); - double _set_rx_lo_freq( - const std::string source, + double _set_rx_lo_freq(const std::string source, const std::string name, const double freq, - const size_t chan - ); + const size_t chan); - double _set_tx_lo_freq( - const std::string source, + double _set_tx_lo_freq(const std::string source, const std::string name, const double freq, - const size_t chan - ); + const size_t chan); /************************************************************************** * Private attributes *************************************************************************/ @@ -334,30 +254,37 @@ private: //! Sampling rate, and also ref clock frequency for the lowband LOs. double _master_clock_rate = 1.0; - //! Desired RF frequency - std::map<direction_t,double> _desired_rf_freq = { {RX_DIRECTION, 2.44e9}, {TX_DIRECTION, 2.44e9} }; + //! Desired RF frequency + std::map<direction_t, double> _desired_rf_freq = { + {RX_DIRECTION, 2.44e9}, {TX_DIRECTION, 2.44e9}}; //! Coerced adf4351 frequency //! Coerced ad9371 frequency - std::map<direction_t,double> _ad9371_freq = { {RX_DIRECTION, 2.44e9}, {TX_DIRECTION, 2.44e9} }; + std::map<direction_t, double> _ad9371_freq = { + {RX_DIRECTION, 2.44e9}, {TX_DIRECTION, 2.44e9}}; //! Coerced adf4351 frequency - std::map<direction_t,double> _adf4351_freq = { {RX_DIRECTION, 2.44e9}, {TX_DIRECTION, 2.44e9} }; + std::map<direction_t, double> _adf4351_freq = { + {RX_DIRECTION, 2.44e9}, {TX_DIRECTION, 2.44e9}}; //! Low band enable - std::map<direction_t,bool> _is_low_band = { {RX_DIRECTION, false}, {TX_DIRECTION, false} }; + std::map<direction_t, bool> _is_low_band = { + {RX_DIRECTION, false}, {TX_DIRECTION, false}}; //! 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} }; + 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} }; + 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} }; + 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"} }; + std::map<direction_t, std::string> _gain_profile = { + {RX_DIRECTION, "default"}, {TX_DIRECTION, "default"}}; bool _rx_bypass_lnas = true; bool _tx_bypass_amp = true; @@ -367,11 +294,11 @@ private: {magnesium_cpld_ctrl::CHAN1, magnesium_cpld_ctrl::SW_TRX_FROMLOWERFILTERBANKTXSW1}, {magnesium_cpld_ctrl::CHAN2, - magnesium_cpld_ctrl::SW_TRX_FROMLOWERFILTERBANKTXSW1} - }; + magnesium_cpld_ctrl::SW_TRX_FROMLOWERFILTERBANKTXSW1}}; //! RX LO SOURCE - // NOTE for magnesium only ad9371 LO that can be connected to the external LO so we only need one var here + // NOTE for magnesium only ad9371 LO that can be connected to the external LO so we + // only need one var here std::string _rx_lo_source = "internal"; }; /* class radio_ctrl_impl */ @@ -379,4 +306,3 @@ private: }} /* namespace uhd::rfnoc */ #endif /* INCLUDED_LIBUHD_RFNOC_MAGNESIUM_RADIO_CTRL_IMPL_HPP */ - 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 901bb1474..422b07ebb 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp @@ -4,40 +4,32 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include "magnesium_radio_ctrl_impl.hpp" #include "magnesium_constants.hpp" -#include <uhd/utils/log.hpp> +#include "magnesium_radio_ctrl_impl.hpp" +#include <uhd/transport/chdr.hpp> #include <uhd/types/eeprom.hpp> #include <uhd/types/sensors.hpp> -#include <uhd/transport/chdr.hpp> +#include <uhd/utils/log.hpp> #include <uhdlib/usrp/cores/spi_core_3000.hpp> -#include <vector> -#include <string> #include <boost/algorithm/string.hpp> -#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/case_conv.hpp> +#include <boost/algorithm/string/split.hpp> +#include <string> +#include <vector> using namespace uhd; using namespace uhd::rfnoc; namespace { - enum slave_select_t { - SEN_CPLD = 1, - SEN_TX_LO = 2, - SEN_RX_LO = 4, - SEN_PHASE_DAC = 8 - }; - - constexpr double MAGNESIUM_DEFAULT_FREQ = 2.5e9; // Hz - constexpr double MAGNESIUM_DEFAULT_BANDWIDTH = 100e6; // Hz - constexpr char MAGNESIUM_DEFAULT_RX_ANTENNA[] = "RX2"; - constexpr char MAGNESIUM_DEFAULT_TX_ANTENNA[] = "TX/RX"; - - //! Magnesium gain profile options - const std::vector<std::string> MAGNESIUM_GP_OPTIONS = { - "manual", - "default" - }; -} +enum slave_select_t { SEN_CPLD = 1, SEN_TX_LO = 2, SEN_RX_LO = 4, SEN_PHASE_DAC = 8 }; + +constexpr double MAGNESIUM_DEFAULT_FREQ = 2.5e9; // Hz +constexpr double MAGNESIUM_DEFAULT_BANDWIDTH = 100e6; // Hz +constexpr char MAGNESIUM_DEFAULT_RX_ANTENNA[] = "RX2"; +constexpr char MAGNESIUM_DEFAULT_TX_ANTENNA[] = "TX/RX"; + +//! Magnesium gain profile options +const std::vector<std::string> MAGNESIUM_GP_OPTIONS = {"manual", "default"}; +} // namespace //! Helper function to extract single value of port number. // @@ -45,32 +37,34 @@ namespace { // This function convert the format of attribute "Radio_N_M" // to a single value port number = N*number_of_port_per_radio + M -uint32_t extract_port_number(std::string radio_src_string, uhd::property_tree::sptr ptree){ +uint32_t extract_port_number(std::string radio_src_string, uhd::property_tree::sptr ptree) +{ std::string s_val = "0"; std::vector<std::string> radio_strings; - boost::algorithm::split( - radio_strings, + boost::algorithm::split(radio_strings, radio_src_string, boost::is_any_of("_/"), boost::token_compress_on); boost::to_lower(radio_strings[0]); - if (radio_strings.size()<3) { - throw uhd::runtime_error(str(boost::format("%s is an invalid GPIO source string.") % radio_src_string)); + if (radio_strings.size() < 3) { + throw uhd::runtime_error(str( + boost::format("%s is an invalid GPIO source string.") % radio_src_string)); } size_t radio_num = std::stoi(radio_strings[1]); - size_t port_num = std::stoi(radio_strings[2]); + size_t port_num = std::stoi(radio_strings[2]); if (radio_strings[0] != "radio") { - throw uhd::runtime_error("Front panel GPIO bank can only accept a radio block as its driver."); + throw uhd::runtime_error( + "Front panel GPIO bank can only accept a radio block as its driver."); } - std::string radio_port_out = "Radio_"+ radio_strings[1] + "/ports/out"; - std::string radio_port_path = radio_port_out + "/"+ radio_strings[2]; - auto found = ptree->exists(fs_path("xbar")/ radio_port_path); - if (not found){ - throw uhd::runtime_error(str(boost::format( - "Could not find radio port %s.\n") % radio_port_path)); + std::string radio_port_out = "Radio_" + radio_strings[1] + "/ports/out"; + std::string radio_port_path = radio_port_out + "/" + radio_strings[2]; + auto found = ptree->exists(fs_path("xbar") / radio_port_path); + if (not found) { + throw uhd::runtime_error( + str(boost::format("Could not find radio port %s.\n") % radio_port_path)); } - size_t port_size = ptree->list(fs_path("xbar")/ radio_port_out).size(); - return radio_num*port_size + port_num; + size_t port_size = ptree->list(fs_path("xbar") / radio_port_out).size(); + return radio_num * port_size + port_num; } void magnesium_radio_ctrl_impl::_init_defaults() @@ -80,8 +74,7 @@ void magnesium_radio_ctrl_impl::_init_defaults() const size_t num_tx_chans = get_input_ports().size(); UHD_LOG_TRACE(unique_id(), - "Num TX chans: " << num_tx_chans - << " Num RX chans: " << num_rx_chans); + "Num TX chans: " << num_tx_chans << " Num RX chans: " << num_rx_chans); for (size_t chan = 0; chan < num_rx_chans; chan++) { radio_ctrl_impl::set_rx_frequency(MAGNESIUM_DEFAULT_FREQ, chan); @@ -104,8 +97,7 @@ void magnesium_radio_ctrl_impl::_init_defaults() const size_t default_spp = (_tree->access<size_t>("mtu/recv").get() - max_bytes_header) / (2 * sizeof(int16_t)); - UHD_LOG_DEBUG(unique_id(), - "Setting default spp to " << default_spp); + UHD_LOG_DEBUG(unique_id(), "Setting default spp to " << default_spp); _tree->access<int>(get_arg_path("spp") / "value").set(default_spp); } @@ -113,606 +105,453 @@ void magnesium_radio_ctrl_impl::_init_peripherals() { UHD_LOG_TRACE(unique_id(), "Initializing peripherals..."); UHD_LOG_TRACE(unique_id(), "Initializing SPI core..."); - _spi = spi_core_3000::make(_get_ctrl(0), - regs::sr_addr(regs::SPI), - regs::rb_addr(regs::RB_SPI) - ); + _spi = spi_core_3000::make( + _get_ctrl(0), regs::sr_addr(regs::SPI), regs::rb_addr(regs::RB_SPI)); UHD_LOG_TRACE(unique_id(), "Initializing CPLD..."); UHD_LOG_TRACE(unique_id(), "Creating new CPLD object..."); spi_config_t spi_config; spi_config.use_custom_divider = true; - spi_config.divider = 125; - spi_config.mosi_edge = spi_config_t::EDGE_RISE; - spi_config.miso_edge = spi_config_t::EDGE_FALL; + spi_config.divider = 125; + spi_config.mosi_edge = spi_config_t::EDGE_RISE; + spi_config.miso_edge = spi_config_t::EDGE_FALL; UHD_LOG_TRACE(unique_id(), "Making CPLD object..."); _cpld = std::make_shared<magnesium_cpld_ctrl>( - [this, spi_config](const uint32_t transaction){ // Write functor - this->_spi->write_spi( - SEN_CPLD, - spi_config, - transaction, - 24 - ); + [this, spi_config](const uint32_t transaction) { // Write functor + this->_spi->write_spi(SEN_CPLD, spi_config, transaction, 24); }, - [this, spi_config](const uint32_t transaction){ // Read functor - return this->_spi->read_spi( - SEN_CPLD, - spi_config, - transaction, - 24 - ); - } - ); + [this, spi_config](const uint32_t transaction) { // Read functor + return this->_spi->read_spi(SEN_CPLD, spi_config, transaction, 24); + }); _update_atr_switches( - magnesium_cpld_ctrl::BOTH, - DX_DIRECTION, - radio_ctrl_impl::get_rx_antenna(0) - ); + magnesium_cpld_ctrl::BOTH, DX_DIRECTION, radio_ctrl_impl::get_rx_antenna(0)); UHD_LOG_TRACE(unique_id(), "Initializing TX LO..."); - _tx_lo = adf435x_iface::make_adf4351( - [this](const std::vector<uint32_t> transactions){ - for (const uint32_t transaction: transactions) { - this->_spi->write_spi( - SEN_TX_LO, - spi_config_t::EDGE_RISE, - transaction, - 32 - ); - } + _tx_lo = adf435x_iface::make_adf4351([this]( + const std::vector<uint32_t> transactions) { + for (const uint32_t transaction : transactions) { + this->_spi->write_spi(SEN_TX_LO, spi_config_t::EDGE_RISE, transaction, 32); } - ); + }); UHD_LOG_TRACE(unique_id(), "Initializing RX LO..."); - _rx_lo = adf435x_iface::make_adf4351( - [this](const std::vector<uint32_t> transactions){ - for (const uint32_t transaction: transactions) { - this->_spi->write_spi( - SEN_RX_LO, - spi_config_t::EDGE_RISE, - transaction, - 32 - ); - } + _rx_lo = adf435x_iface::make_adf4351([this]( + const std::vector<uint32_t> transactions) { + for (const uint32_t transaction : transactions) { + this->_spi->write_spi(SEN_RX_LO, spi_config_t::EDGE_RISE, transaction, 32); } - ); + }); _gpio.clear(); // Following the as-if rule, this can get optimized out for (size_t radio_idx = 0; radio_idx < _get_num_radios(); radio_idx++) { - UHD_LOG_TRACE(unique_id(), - "Initializing GPIOs for channel " << radio_idx); - _gpio.emplace_back( - usrp::gpio_atr::gpio_atr_3000::make( - _get_ctrl(radio_idx), - regs::sr_addr(regs::GPIO), - regs::rb_addr(regs::RB_DB_GPIO) - ) - ); + UHD_LOG_TRACE(unique_id(), "Initializing GPIOs for channel " << radio_idx); + _gpio.emplace_back(usrp::gpio_atr::gpio_atr_3000::make(_get_ctrl(radio_idx), + regs::sr_addr(regs::GPIO), + regs::rb_addr(regs::RB_DB_GPIO))); // DSA and AD9371 gain bits do *not* toggle on ATR modes. If we ever // connect anything else to this core, we might need to set_atr_mode() // to MODE_ATR on those bits. For now, all bits simply do what they're // told, and don't toggle on RX/TX state changes. - _gpio.back()->set_atr_mode( - usrp::gpio_atr::MODE_GPIO, // Disable ATR mode - usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL - ); - _gpio.back()->set_gpio_ddr( - usrp::gpio_atr::DDR_OUTPUT, // Make all GPIOs outputs - usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL - ); + _gpio.back()->set_atr_mode(usrp::gpio_atr::MODE_GPIO, // Disable ATR mode + usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL); + _gpio.back()->set_gpio_ddr(usrp::gpio_atr::DDR_OUTPUT, // Make all GPIOs outputs + usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL); } UHD_LOG_TRACE(unique_id(), "Initializing front-panel GPIO control...") _fp_gpio = usrp::gpio_atr::gpio_atr_3000::make( - _get_ctrl(0), - regs::sr_addr(regs::FP_GPIO), - regs::rb_addr(regs::RB_FP_GPIO) - ); + _get_ctrl(0), regs::sr_addr(regs::FP_GPIO), regs::rb_addr(regs::RB_FP_GPIO)); } void magnesium_radio_ctrl_impl::_init_frontend_subtree( - uhd::property_tree::sptr subtree, - const size_t chan_idx -) { + uhd::property_tree::sptr subtree, const size_t chan_idx) +{ const fs_path tx_fe_path = fs_path("tx_frontends") / chan_idx; const fs_path rx_fe_path = fs_path("rx_frontends") / chan_idx; UHD_LOG_TRACE(unique_id(), - "Adding non-RFNoC block properties for channel " << chan_idx << - " to prop tree path " << tx_fe_path << " and " << rx_fe_path); + "Adding non-RFNoC block properties for channel " + << chan_idx << " to prop tree path " << tx_fe_path << " and " << rx_fe_path); // TX Standard attributes subtree->create<std::string>(tx_fe_path / "name") - .set(str(boost::format("Magnesium"))) - ; - subtree->create<std::string>(tx_fe_path / "connection") - .set("IQ") - ; + .set(str(boost::format("Magnesium"))); + subtree->create<std::string>(tx_fe_path / "connection").set("IQ"); // RX Standard attributes subtree->create<std::string>(rx_fe_path / "name") - .set(str(boost::format("Magnesium"))) - ; - subtree->create<std::string>(rx_fe_path / "connection") - .set("IQ") - ; + .set(str(boost::format("Magnesium"))); + subtree->create<std::string>(rx_fe_path / "connection").set("IQ"); // TX Antenna subtree->create<std::string>(tx_fe_path / "antenna" / "value") - .add_coerced_subscriber([this, chan_idx](const std::string &ant){ + .add_coerced_subscriber([this, chan_idx](const std::string& ant) { this->set_tx_antenna(ant, chan_idx); }) - .set_publisher([this, chan_idx](){ - return this->get_tx_antenna(chan_idx); - }) - ; + .set_publisher([this, chan_idx]() { return this->get_tx_antenna(chan_idx); }); subtree->create<std::vector<std::string>>(tx_fe_path / "antenna" / "options") .set({MAGNESIUM_DEFAULT_TX_ANTENNA}) - .add_coerced_subscriber([](const std::vector<std::string> &){ - throw uhd::runtime_error( - "Attempting to update antenna options!"); - }) - ; + .add_coerced_subscriber([](const std::vector<std::string>&) { + throw uhd::runtime_error("Attempting to update antenna options!"); + }); // RX Antenna subtree->create<std::string>(rx_fe_path / "antenna" / "value") - .add_coerced_subscriber([this, chan_idx](const std::string &ant){ + .add_coerced_subscriber([this, chan_idx](const std::string& ant) { this->set_rx_antenna(ant, chan_idx); }) - .set_publisher([this, chan_idx](){ - return this->get_rx_antenna(chan_idx); - }) - ; + .set_publisher([this, chan_idx]() { return this->get_rx_antenna(chan_idx); }); subtree->create<std::vector<std::string>>(rx_fe_path / "antenna" / "options") .set(MAGNESIUM_RX_ANTENNAS) - .add_coerced_subscriber([](const std::vector<std::string> &){ - throw uhd::runtime_error( - "Attempting to update antenna options!"); - }) - ; + .add_coerced_subscriber([](const std::vector<std::string>&) { + throw uhd::runtime_error("Attempting to update antenna options!"); + }); // TX frequency subtree->create<double>(tx_fe_path / "freq" / "value") - .set_coercer([this, chan_idx](const double freq){ + .set_coercer([this, chan_idx](const double freq) { return this->set_tx_frequency(freq, chan_idx); }) - .set_publisher([this, chan_idx](){ - return this->get_tx_frequency(chan_idx); - }) - ; + .set_publisher([this, chan_idx]() { return this->get_tx_frequency(chan_idx); }); subtree->create<meta_range_t>(tx_fe_path / "freq" / "range") .set(meta_range_t(MAGNESIUM_MIN_FREQ, MAGNESIUM_MAX_FREQ, 1.0)) - .add_coerced_subscriber([](const meta_range_t &){ - throw uhd::runtime_error( - "Attempting to update freq range!"); - }) - ; + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update freq range!"); + }); // RX frequency subtree->create<double>(rx_fe_path / "freq" / "value") - .set_coercer([this, chan_idx](const double freq){ + .set_coercer([this, chan_idx](const double freq) { return this->set_rx_frequency(freq, chan_idx); }) - .set_publisher([this, chan_idx](){ - return this->get_rx_frequency(chan_idx); - }) - ; + .set_publisher([this, chan_idx]() { return this->get_rx_frequency(chan_idx); }); subtree->create<meta_range_t>(rx_fe_path / "freq" / "range") .set(meta_range_t(MAGNESIUM_MIN_FREQ, MAGNESIUM_MAX_FREQ, 1.0)) - .add_coerced_subscriber([](const meta_range_t &){ - throw uhd::runtime_error( - "Attempting to update freq range!"); - }) - ; + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update freq range!"); + }); // TX bandwidth subtree->create<double>(tx_fe_path / "bandwidth" / "value") .set(AD9371_TX_MAX_BANDWIDTH) - .set_coercer([this, chan_idx](const double bw){ + .set_coercer([this, chan_idx](const double bw) { return this->set_tx_bandwidth(bw, chan_idx); }) - .set_publisher([this, chan_idx](){ - return this->get_tx_bandwidth(chan_idx); - }) - ; + .set_publisher([this, chan_idx]() { return this->get_tx_bandwidth(chan_idx); }); subtree->create<meta_range_t>(tx_fe_path / "bandwidth" / "range") .set(meta_range_t(AD9371_TX_MIN_BANDWIDTH, AD9371_TX_MAX_BANDWIDTH)) - .add_coerced_subscriber([](const meta_range_t &){ - throw uhd::runtime_error( - "Attempting to update bandwidth range!"); - }) - ; + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update bandwidth range!"); + }); // RX bandwidth subtree->create<double>(rx_fe_path / "bandwidth" / "value") .set(AD9371_RX_MAX_BANDWIDTH) - .set_coercer([this, chan_idx](const double bw){ + .set_coercer([this, chan_idx](const double bw) { return this->set_rx_bandwidth(bw, chan_idx); - }) - ; + }); subtree->create<meta_range_t>(rx_fe_path / "bandwidth" / "range") .set(meta_range_t(AD9371_RX_MIN_BANDWIDTH, AD9371_RX_MAX_BANDWIDTH)) - .add_coerced_subscriber([](const meta_range_t &){ - throw uhd::runtime_error( - "Attempting to update bandwidth range!"); - }) - ; + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update bandwidth range!"); + }); // TX gains subtree->create<double>(tx_fe_path / "gains" / "all" / "value") - .set_coercer([this, chan_idx](const double gain){ - return this->set_tx_gain(gain, chan_idx); - }) - .set_publisher([this, chan_idx](){ - return radio_ctrl_impl::get_tx_gain(chan_idx); - }) - ; + .set_coercer([this, chan_idx]( + const double gain) { return this->set_tx_gain(gain, chan_idx); }) + .set_publisher( + [this, chan_idx]() { return radio_ctrl_impl::get_tx_gain(chan_idx); }); subtree->create<meta_range_t>(tx_fe_path / "gains" / "all" / "range") - .add_coerced_subscriber([](const meta_range_t &){ - throw uhd::runtime_error( - "Attempting to update gain range!"); + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update gain range!"); }) - .set_publisher([this](){ + .set_publisher([this]() { 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 - ); + 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({"manual", "default"}); subtree->create<std::string>(tx_fe_path / "gains/all/profile/value") - .set_coercer([this](const std::string& profile){ + .set_coercer([this](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()) - { + 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](){ - return _gain_profile[TX_DIRECTION]; - }) - ; + .set_publisher([this]() { 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 radio_ctrl_impl::get_rx_gain(chan_idx); - }) - ; + .set_coercer([this, chan_idx]( + const double gain) { return this->set_rx_gain(gain, chan_idx); }) + .set_publisher( + [this, chan_idx]() { return radio_ctrl_impl::get_rx_gain(chan_idx); }); subtree->create<meta_range_t>(rx_fe_path / "gains" / "all" / "range") - .add_coerced_subscriber([](const meta_range_t &){ - throw uhd::runtime_error( - "Attempting to update gain range!"); + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update gain range!"); }) - .set_publisher([this](){ + .set_publisher([this]() { 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 - ); + 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::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](const std::string& profile){ + .set_coercer([this](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()) - { + 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](){ - return _gain_profile[RX_DIRECTION]; - }) - ; + .set_publisher([this]() { return _gain_profile[RX_DIRECTION]; }); // TX mykonos attenuation subtree->create<double>(tx_fe_path / "gains" / MAGNESIUM_GAIN1 / "value") - .set_coercer([this, chan_idx](const double gain){ + .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); - }) - ; + .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!"); + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update gain range!"); }) - .set_publisher([this](){ + .set_publisher([this]() { if (_gain_profile[TX_DIRECTION] == "manual") { return meta_range_t( - AD9371_MIN_TX_GAIN, - AD9371_MAX_TX_GAIN, - AD9371_TX_GAIN_STEP - ); + 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 + }); + // TX DSA subtree->create<double>(tx_fe_path / "gains" / MAGNESIUM_GAIN2 / "value") - .set_coercer([this, chan_idx](const double gain){ + .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); - }) - ; + .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!"); + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update gain range!"); }) - .set_publisher([this](){ + .set_publisher([this]() { if (_gain_profile[TX_DIRECTION] == "manual") { return meta_range_t(DSA_MIN_GAIN, DSA_MAX_GAIN, DSA_GAIN_STEP); - }else{ + } else { return meta_range_t(0.0, 0.0, 0.0); } - }) - ; - //TX amp + }); + // 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); - }) - ; + .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!"); + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update gain range!"); }) - .set_publisher([this](){ + .set_publisher([this]() { if (_gain_profile[TX_DIRECTION] == "manual") { return meta_range_t(AMP_MIN_GAIN, AMP_MAX_GAIN, AMP_GAIN_STEP); - }else{ + } 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); + .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); - }) - ; + .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!"); + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update gain range!"); }) - .set_publisher([this](){ + .set_publisher([this]() { if (_gain_profile[RX_DIRECTION] == "manual") { return meta_range_t( - AD9371_MIN_RX_GAIN, - AD9371_MAX_RX_GAIN, - AD9371_RX_GAIN_STEP - ); + 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 + }); + // 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); - }) - ; + .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!"); + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update gain range!"); }) - .set_publisher([this](){ + .set_publisher([this]() { if (_gain_profile[RX_DIRECTION] == "manual") { return meta_range_t(DSA_MIN_GAIN, DSA_MAX_GAIN, DSA_MAX_GAIN); - }else{ + } else { return meta_range_t(0.0, 0.0, 0.0); } - }) - ; + }); - //RX amp + // 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); - }) - ; + .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!"); + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update gain range!"); }) - .set_publisher([this](){ + .set_publisher([this]() { if (_gain_profile[RX_DIRECTION] == "manual") { return meta_range_t(AMP_MIN_GAIN, AMP_MAX_GAIN, AMP_GAIN_STEP); - }else{ + } 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 // also set there. subtree->create<sensor_value_t>(tx_fe_path / "sensors" / "lo_locked") - .set(sensor_value_t("all_los", false, "locked", "unlocked")) - .add_coerced_subscriber([](const sensor_value_t &){ - throw uhd::runtime_error( - "Attempting to write to sensor!"); + .set(sensor_value_t("all_los", false, "locked", "unlocked")) + .add_coerced_subscriber([](const sensor_value_t&) { + throw uhd::runtime_error("Attempting to write to sensor!"); }) - .set_publisher([this](){ + .set_publisher([this]() { return sensor_value_t( - "all_los", - this->get_lo_lock_status(TX_DIRECTION), - "locked", "unlocked" - ); - }) - ; + "all_los", this->get_lo_lock_status(TX_DIRECTION), "locked", "unlocked"); + }); // RX LO lock sensor (see not on TX LO lock sensor) subtree->create<sensor_value_t>(rx_fe_path / "sensors" / "lo_locked") - .set(sensor_value_t("all_los", false, "locked", "unlocked")) - .add_coerced_subscriber([](const sensor_value_t &){ - throw uhd::runtime_error( - "Attempting to write to sensor!"); + .set(sensor_value_t("all_los", false, "locked", "unlocked")) + .add_coerced_subscriber([](const sensor_value_t&) { + throw uhd::runtime_error("Attempting to write to sensor!"); }) - .set_publisher([this](){ + .set_publisher([this]() { return sensor_value_t( - "all_los", - this->get_lo_lock_status(RX_DIRECTION), - "locked", "unlocked" - ); - }) - ; - //LO Specific - //RX LO - subtree->create<meta_range_t>(rx_fe_path / "los"/MAGNESIUM_LO1/"freq/range") - .set_publisher([this,chan_idx](){ + "all_los", this->get_lo_lock_status(RX_DIRECTION), "locked", "unlocked"); + }); + // LO Specific + // RX LO + subtree->create<meta_range_t>(rx_fe_path / "los" / MAGNESIUM_LO1 / "freq/range") + .set_publisher([this, chan_idx]() { return this->get_rx_lo_freq_range(MAGNESIUM_LO1, chan_idx); - }) - ; - subtree->create<std::vector<std::string>>(rx_fe_path / "los"/MAGNESIUM_LO1/"source/options") - .set_publisher([this,chan_idx](){ + }); + subtree + ->create<std::vector<std::string>>( + rx_fe_path / "los" / MAGNESIUM_LO1 / "source/options") + .set_publisher([this, chan_idx]() { return this->get_rx_lo_sources(MAGNESIUM_LO1, chan_idx); + }); + subtree->create<std::string>(rx_fe_path / "los" / MAGNESIUM_LO1 / "source/value") + .add_coerced_subscriber([this, chan_idx](std::string src) { + this->set_rx_lo_source(src, MAGNESIUM_LO1, chan_idx); }) - ; - subtree->create<std::string>(rx_fe_path / "los"/MAGNESIUM_LO1/"source/value") - .add_coerced_subscriber([this,chan_idx](std::string src){ - this->set_rx_lo_source(src, MAGNESIUM_LO1,chan_idx); - }) - .set_publisher([this,chan_idx](){ + .set_publisher([this, chan_idx]() { return this->get_rx_lo_source(MAGNESIUM_LO1, chan_idx); - }) - ; - subtree->create<double>(rx_fe_path / "los"/MAGNESIUM_LO1/"freq/value") - .set_publisher([this,chan_idx](){ - return this->get_rx_lo_freq(MAGNESIUM_LO1, chan_idx); - }) - .set_coercer([this,chan_idx](const double freq){ + }); + subtree->create<double>(rx_fe_path / "los" / MAGNESIUM_LO1 / "freq/value") + .set_publisher( + [this, chan_idx]() { return this->get_rx_lo_freq(MAGNESIUM_LO1, chan_idx); }) + .set_coercer([this, chan_idx](const double freq) { return this->set_rx_lo_freq(freq, MAGNESIUM_LO1, chan_idx); - }) - ; + }); - subtree->create<meta_range_t>(rx_fe_path / "los"/MAGNESIUM_LO2/"freq/range") - .set_publisher([this,chan_idx](){ + subtree->create<meta_range_t>(rx_fe_path / "los" / MAGNESIUM_LO2 / "freq/range") + .set_publisher([this, chan_idx]() { return this->get_rx_lo_freq_range(MAGNESIUM_LO2, chan_idx); - }) - ; - subtree->create<std::vector<std::string>>(rx_fe_path / "los"/MAGNESIUM_LO2/"source/options") - .set_publisher([this,chan_idx](){ + }); + subtree + ->create<std::vector<std::string>>( + rx_fe_path / "los" / MAGNESIUM_LO2 / "source/options") + .set_publisher([this, chan_idx]() { return this->get_rx_lo_sources(MAGNESIUM_LO2, chan_idx); - }) - ; + }); - subtree->create<std::string>(rx_fe_path / "los"/MAGNESIUM_LO2/"source/value") - .add_coerced_subscriber([this,chan_idx](std::string src){ + subtree->create<std::string>(rx_fe_path / "los" / MAGNESIUM_LO2 / "source/value") + .add_coerced_subscriber([this, chan_idx](std::string src) { this->set_rx_lo_source(src, MAGNESIUM_LO2, chan_idx); }) - .set_publisher([this,chan_idx](){ + .set_publisher([this, chan_idx]() { return this->get_rx_lo_source(MAGNESIUM_LO2, chan_idx); - }) - ; - subtree->create<double>(rx_fe_path / "los"/MAGNESIUM_LO2/"freq/value") - .set_publisher([this,chan_idx](){ - return this->get_rx_lo_freq(MAGNESIUM_LO2, chan_idx); - }) - .set_coercer([this,chan_idx](double freq){ + }); + subtree->create<double>(rx_fe_path / "los" / MAGNESIUM_LO2 / "freq/value") + .set_publisher( + [this, chan_idx]() { return this->get_rx_lo_freq(MAGNESIUM_LO2, chan_idx); }) + .set_coercer([this, chan_idx](double freq) { return this->set_rx_lo_freq(freq, MAGNESIUM_LO2, chan_idx); }); - //TX LO - subtree->create<meta_range_t>(tx_fe_path / "los"/MAGNESIUM_LO1/"freq/range") - .set_publisher([this,chan_idx](){ + // TX LO + subtree->create<meta_range_t>(tx_fe_path / "los" / MAGNESIUM_LO1 / "freq/range") + .set_publisher([this, chan_idx]() { return this->get_rx_lo_freq_range(MAGNESIUM_LO1, chan_idx); - }) - ; - subtree->create<std::vector<std::string>>(tx_fe_path / "los"/MAGNESIUM_LO1/"source/options") - .set_publisher([this,chan_idx](){ + }); + subtree + ->create<std::vector<std::string>>( + tx_fe_path / "los" / MAGNESIUM_LO1 / "source/options") + .set_publisher([this, chan_idx]() { return this->get_tx_lo_sources(MAGNESIUM_LO1, chan_idx); - }) - ; - subtree->create<std::string>(tx_fe_path / "los"/MAGNESIUM_LO1/"source/value") - .add_coerced_subscriber([this,chan_idx](std::string src){ + }); + subtree->create<std::string>(tx_fe_path / "los" / MAGNESIUM_LO1 / "source/value") + .add_coerced_subscriber([this, chan_idx](std::string src) { this->set_tx_lo_source(src, MAGNESIUM_LO1, chan_idx); }) - .set_publisher([this,chan_idx](){ + .set_publisher([this, chan_idx]() { return this->get_tx_lo_source(MAGNESIUM_LO1, chan_idx); - }) - ; - subtree->create<double>(tx_fe_path / "los"/MAGNESIUM_LO1/"freq/value ") - .set_publisher([this,chan_idx](){ - return this->get_tx_lo_freq(MAGNESIUM_LO1, chan_idx); - }) - .set_coercer([this,chan_idx](double freq){ + }); + subtree->create<double>(tx_fe_path / "los" / MAGNESIUM_LO1 / "freq/value ") + .set_publisher( + [this, chan_idx]() { return this->get_tx_lo_freq(MAGNESIUM_LO1, chan_idx); }) + .set_coercer([this, chan_idx](double freq) { return this->set_tx_lo_freq(freq, MAGNESIUM_LO1, chan_idx); - }) - ; + }); - subtree->create<meta_range_t>(tx_fe_path / "los"/MAGNESIUM_LO2/"freq/range") - .set_publisher([this,chan_idx](){ - return this->get_tx_lo_freq_range(MAGNESIUM_LO2,chan_idx); - }) - ; - subtree->create<std::vector<std::string>>(tx_fe_path / "los"/MAGNESIUM_LO2/"source/options") - .set_publisher([this,chan_idx](){ + subtree->create<meta_range_t>(tx_fe_path / "los" / MAGNESIUM_LO2 / "freq/range") + .set_publisher([this, chan_idx]() { + return this->get_tx_lo_freq_range(MAGNESIUM_LO2, chan_idx); + }); + subtree + ->create<std::vector<std::string>>( + tx_fe_path / "los" / MAGNESIUM_LO2 / "source/options") + .set_publisher([this, chan_idx]() { return this->get_tx_lo_sources(MAGNESIUM_LO2, chan_idx); - }) - ; + }); - subtree->create<std::string>(tx_fe_path / "los"/MAGNESIUM_LO2/"source/value") - .add_coerced_subscriber([this,chan_idx](std::string src){ + subtree->create<std::string>(tx_fe_path / "los" / MAGNESIUM_LO2 / "source/value") + .add_coerced_subscriber([this, chan_idx](std::string src) { this->set_tx_lo_source(src, MAGNESIUM_LO2, chan_idx); }) - .set_publisher([this,chan_idx](){ + .set_publisher([this, chan_idx]() { return this->get_tx_lo_source(MAGNESIUM_LO2, chan_idx); - }) - ; - subtree->create<double>(tx_fe_path / "los"/MAGNESIUM_LO2/"freq/value") - .set_publisher([this,chan_idx](){ - return this->get_tx_lo_freq(MAGNESIUM_LO2, chan_idx); - }) - .set_coercer([this,chan_idx](double freq){ + }); + subtree->create<double>(tx_fe_path / "los" / MAGNESIUM_LO2 / "freq/value") + .set_publisher( + [this, chan_idx]() { return this->get_tx_lo_freq(MAGNESIUM_LO2, chan_idx); }) + .set_coercer([this, chan_idx](double freq) { return this->set_tx_lo_freq(freq, MAGNESIUM_LO2, chan_idx); }); } @@ -721,13 +560,11 @@ void magnesium_radio_ctrl_impl::_init_prop_tree() { const fs_path fe_base = fs_path("dboards") / _radio_slot; for (size_t chan_idx = 0; chan_idx < MAGNESIUM_NUM_CHANS; chan_idx++) { - this->_init_frontend_subtree( - _tree->subtree(fe_base), chan_idx); + this->_init_frontend_subtree(_tree->subtree(fe_base), chan_idx); } // EEPROM paths subject to change FIXME - _tree->create<eeprom_map_t>(_root_path / "eeprom") - .set(eeprom_map_t()); + _tree->create<eeprom_map_t>(_root_path / "eeprom").set(eeprom_map_t()); // TODO change codec names _tree->create<int>("rx_codecs" / _radio_slot / "gains"); @@ -736,94 +573,108 @@ void magnesium_radio_ctrl_impl::_init_prop_tree() _tree->create<std::string>("tx_codecs" / _radio_slot / "name").set("AD9371 Dual DAC"); // TODO remove this dirty hack - if (not _tree->exists("tick_rate")) - { - _tree->create<double>("tick_rate") - .set_publisher([this](){ return this->get_rate(); }) - ; + if (not _tree->exists("tick_rate")) { + _tree->create<double>("tick_rate").set_publisher([this]() { + return this->get_rate(); + }); } // *****FP_GPIO************************ - for(const auto& attr: usrp::gpio_atr::gpio_attr_map) { - if (not _tree->exists(fs_path("gpio") / "FP0" / attr.second)){ - switch (attr.first){ + for (const auto& attr : usrp::gpio_atr::gpio_attr_map) { + if (not _tree->exists(fs_path("gpio") / "FP0" / attr.second)) { + switch (attr.first) { case usrp::gpio_atr::GPIO_SRC: - //FIXME: move this creation of this branch of ptree out side of radio impl; - // since there's no data dependency between radio and SRC setting for FP0 - _tree->create<std::vector<std::string>>(fs_path("gpio") / "FP0" / attr.second) - .set(std::vector<std::string>( - 32, - usrp::gpio_atr::default_attr_value_map.at(attr.first))) - .add_coerced_subscriber([this, attr]( - const std::vector<std::string> str_val){ - uint32_t radio_src_value = 0; - uint32_t master_value = 0; - for(size_t i = 0 ; i<str_val.size(); i++){ - if(str_val[i] == "PS"){ - master_value += 1<<i;; - }else{ - auto port_num = extract_port_number(str_val[i],_tree); - radio_src_value =(1<<(2*i))*port_num + radio_src_value; + // FIXME: move this creation of this branch of ptree out side of + // radio impl; + // since there's no data dependency between radio and SRC setting for + // FP0 + _tree + ->create<std::vector<std::string>>( + fs_path("gpio") / "FP0" / attr.second) + .set(std::vector<std::string>( + 32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) + .add_coerced_subscriber( + [this, attr](const std::vector<std::string> str_val) { + uint32_t radio_src_value = 0; + uint32_t master_value = 0; + for (size_t i = 0; i < str_val.size(); i++) { + if (str_val[i] == "PS") { + master_value += 1 << i; + ; + } else { + auto port_num = + extract_port_number(str_val[i], _tree); + radio_src_value = + (1 << (2 * i)) * port_num + radio_src_value; + } } - } - _rpcc->notify_with_token("set_fp_gpio_master", master_value); - _rpcc->notify_with_token("set_fp_gpio_radio_src", radio_src_value); - }); - break; + _rpcc->notify_with_token( + "set_fp_gpio_master", master_value); + _rpcc->notify_with_token( + "set_fp_gpio_radio_src", radio_src_value); + }); + break; case usrp::gpio_atr::GPIO_CTRL: case usrp::gpio_atr::GPIO_DDR: - _tree->create<std::vector<std::string>>(fs_path("gpio") / "FP0" / attr.second) - .set(std::vector<std::string>( - 32, - usrp::gpio_atr::default_attr_value_map.at(attr.first))) - .add_coerced_subscriber([this, attr]( - const std::vector<std::string> str_val){ - uint32_t val = 0; - for(size_t i = 0 ; i < str_val.size() ; i++){ - val += usrp::gpio_atr::gpio_attr_value_pair.at(attr.second).at(str_val[i])<<i; - } - _fp_gpio->set_gpio_attr(attr.first, val); - }); + _tree + ->create<std::vector<std::string>>( + fs_path("gpio") / "FP0" / attr.second) + .set(std::vector<std::string>( + 32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) + .add_coerced_subscriber( + [this, attr](const std::vector<std::string> str_val) { + uint32_t val = 0; + for (size_t i = 0; i < str_val.size(); i++) { + val += usrp::gpio_atr::gpio_attr_value_pair + .at(attr.second) + .at(str_val[i]) + << i; + } + _fp_gpio->set_gpio_attr(attr.first, val); + }); break; - case usrp::gpio_atr::GPIO_READBACK:{ + case usrp::gpio_atr::GPIO_READBACK: { _tree->create<uint32_t>(fs_path("gpio") / "FP0" / attr.second) - .set_publisher([this](){ - return _fp_gpio->read_gpio(); - } - ); - } - break; + .set_publisher([this]() { return _fp_gpio->read_gpio(); }); + } break; default: _tree->create<uint32_t>(fs_path("gpio") / "FP0" / attr.second) - .set(0) - .add_coerced_subscriber([this, attr](const uint32_t val){ - _fp_gpio->set_gpio_attr(attr.first, val); - }); + .set(0) + .add_coerced_subscriber([this, attr](const uint32_t val) { + _fp_gpio->set_gpio_attr(attr.first, val); + }); } - }else{ - switch (attr.first){ + } else { + switch (attr.first) { case usrp::gpio_atr::GPIO_SRC: - break; + break; case usrp::gpio_atr::GPIO_CTRL: case usrp::gpio_atr::GPIO_DDR: - _tree->access<std::vector<std::string>>(fs_path("gpio") / "FP0" / attr.second) - .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) - .add_coerced_subscriber([this, attr](const std::vector<std::string> str_val){ - uint32_t val = 0; - for(size_t i = 0 ; i < str_val.size() ; i++){ - val += usrp::gpio_atr::gpio_attr_value_pair.at(attr.second).at(str_val[i])<<i; - } - _fp_gpio->set_gpio_attr(attr.first, val); - }); + _tree + ->access<std::vector<std::string>>( + fs_path("gpio") / "FP0" / attr.second) + .set(std::vector<std::string>( + 32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) + .add_coerced_subscriber( + [this, attr](const std::vector<std::string> str_val) { + uint32_t val = 0; + for (size_t i = 0; i < str_val.size(); i++) { + val += usrp::gpio_atr::gpio_attr_value_pair + .at(attr.second) + .at(str_val[i]) + << i; + } + _fp_gpio->set_gpio_attr(attr.first, val); + }); break; case usrp::gpio_atr::GPIO_READBACK: break; default: _tree->access<uint32_t>(fs_path("gpio") / "FP0" / attr.second) - .set(0) - .add_coerced_subscriber([this, attr](const uint32_t val){ - _fp_gpio->set_gpio_attr(attr.first, val); - }); + .set(0) + .add_coerced_subscriber([this, attr](const uint32_t val) { + _fp_gpio->set_gpio_attr(attr.first, val); + }); } } } @@ -831,34 +682,27 @@ void magnesium_radio_ctrl_impl::_init_prop_tree() void magnesium_radio_ctrl_impl::_init_mpm_sensors( - const direction_t dir, - const size_t chan_idx -) { + const direction_t dir, const size_t chan_idx) +{ const std::string trx = (dir == RX_DIRECTION) ? "RX" : "TX"; - const fs_path fe_path = - fs_path("dboards") / _radio_slot / - (dir == RX_DIRECTION ? "rx_frontends" : "tx_frontends") / chan_idx; - auto sensor_list = - _rpcc->request_with_token<std::vector<std::string>>( - this->_rpc_prefix + "get_sensors", trx); + const fs_path fe_path = fs_path("dboards") / _radio_slot + / (dir == RX_DIRECTION ? "rx_frontends" : "tx_frontends") + / chan_idx; + auto sensor_list = _rpcc->request_with_token<std::vector<std::string>>( + this->_rpc_prefix + "get_sensors", trx); UHD_LOG_TRACE(unique_id(), - "Chan " << chan_idx << ": Found " - << sensor_list.size() << " " << trx << " sensors."); - for (const auto &sensor_name : sensor_list) { - UHD_LOG_TRACE(unique_id(), - "Adding " << trx << " sensor " << sensor_name); + "Chan " << chan_idx << ": Found " << sensor_list.size() << " " << trx + << " sensors."); + for (const auto& sensor_name : sensor_list) { + UHD_LOG_TRACE(unique_id(), "Adding " << trx << " sensor " << sensor_name); _tree->create<sensor_value_t>(fe_path / "sensors" / sensor_name) - .add_coerced_subscriber([](const sensor_value_t &){ - throw uhd::runtime_error( - "Attempting to write to sensor!"); + .add_coerced_subscriber([](const sensor_value_t&) { + throw uhd::runtime_error("Attempting to write to sensor!"); }) - .set_publisher([this, trx, sensor_name, chan_idx](){ + .set_publisher([this, trx, sensor_name, chan_idx]() { return sensor_value_t( this->_rpcc->request_with_token<sensor_value_t::sensor_map_t>( - this->_rpc_prefix + "get_sensor", - trx, sensor_name, chan_idx) - ); - }) - ; + this->_rpc_prefix + "get_sensor", trx, sensor_name, chan_idx)); + }); } } diff --git a/host/lib/usrp/dboard/neon/neon_ad9361_iface.cpp b/host/lib/usrp/dboard/neon/neon_ad9361_iface.cpp index e19f890ca..a9cf28fc2 100644 --- a/host/lib/usrp/dboard/neon/neon_ad9361_iface.cpp +++ b/host/lib/usrp/dboard/neon/neon_ad9361_iface.cpp @@ -14,38 +14,33 @@ using namespace uhd; class neon_ad9361_iface : public ad9361_ctrl { public: - neon_ad9361_iface( - rpc_client::sptr rpcc - ) : _rpcc(rpcc) - , _rpc_prefix("db_0_") - , _log_prefix("AD9361") + neon_ad9361_iface(rpc_client::sptr rpcc) + : _rpcc(rpcc), _rpc_prefix("db_0_"), _log_prefix("AD9361") { - UHD_LOG_TRACE(_log_prefix, - "Initialized controls with RPC prefix " << _rpc_prefix); + UHD_LOG_TRACE( + _log_prefix, "Initialized controls with RPC prefix " << _rpc_prefix); } - double set_bw_filter(const std::string &which, const double bw) + double set_bw_filter(const std::string& which, const double bw) { return _rpcc->request_with_token<double>( this->_rpc_prefix + "set_bw_filter", which, bw); } - double set_gain(const std::string &which, const double value) + double set_gain(const std::string& which, const double value) { return _rpcc->request_with_token<double>( this->_rpc_prefix + "set_gain", which, value); } - void set_agc(const std::string &which, bool enable) + void set_agc(const std::string& which, bool enable) { - _rpcc->request_with_token<void>( - this->_rpc_prefix + "set_agc", which, enable); + _rpcc->request_with_token<void>(this->_rpc_prefix + "set_agc", which, enable); } - void set_agc_mode(const std::string &which, const std::string &mode) + void set_agc_mode(const std::string& which, const std::string& mode) { - _rpcc->request_with_token<void>( - this->_rpc_prefix + "set_agc_mode", which, mode); + _rpcc->request_with_token<void>(this->_rpc_prefix + "set_agc_mode", which, mode); } double set_clock_rate(const double rate) @@ -60,43 +55,41 @@ public: this->_rpc_prefix + "set_active_chains", tx1, tx2, rx1, rx2); } - double tune(const std::string &which, const double value) + double tune(const std::string& which, const double value) { return _rpcc->request_with_token<double>( this->_rpc_prefix + "tune", which, value); } - void set_dc_offset_auto(const std::string &which, const bool on) + void set_dc_offset_auto(const std::string& which, const bool on) { _rpcc->request_with_token<void>( this->_rpc_prefix + "set_dc_offset_auto", which, on); } - void set_timing_mode(const std::string &timing_mode) + void set_timing_mode(const std::string& timing_mode) { _rpcc->request_with_token<void>( this->_rpc_prefix + "set_timing_mode", timing_mode); } - void set_iq_balance_auto(const std::string &which, const bool on) + void set_iq_balance_auto(const std::string& which, const bool on) { _rpcc->request_with_token<void>( this->_rpc_prefix + "set_iq_balance_auto", which, on); } - double get_freq(const std::string &which) + double get_freq(const std::string& which) { - return _rpcc->request_with_token<double>( - this->_rpc_prefix + "get_freq", which); + return _rpcc->request_with_token<double>(this->_rpc_prefix + "get_freq", which); } void data_port_loopback(const bool on) { - _rpcc->request_with_token<void>( - this->_rpc_prefix + "data_port_loopback", on); + _rpcc->request_with_token<void>(this->_rpc_prefix + "data_port_loopback", on); } - sensor_value_t get_rssi(const std::string &which) + sensor_value_t get_rssi(const std::string& which) { return sensor_value_t(_rpcc->request_with_token<sensor_value_t::sensor_map_t>( this->_rpc_prefix + "get_rssi", which)); @@ -108,23 +101,25 @@ public: this->_rpc_prefix + "get_temperature")); } - std::vector<std::string> get_filter_names(const std::string &which) + std::vector<std::string> get_filter_names(const std::string& which) { return _rpcc->request_with_token<std::vector<std::string>>( this->_rpc_prefix + "get_filter_names", which); } - filter_info_base::sptr get_filter(const std::string &/*which*/, - const std::string &/*filter_name*/) + filter_info_base::sptr get_filter( + const std::string& /*which*/, const std::string& /*filter_name*/) { - throw uhd::runtime_error("ad9361_ctrl::get_filter is not supported over an RPC connection"); + throw uhd::runtime_error( + "ad9361_ctrl::get_filter is not supported over an RPC connection"); } - void set_filter(const std::string &/*which*/, - const std::string &/*filter_name*/, - const filter_info_base::sptr /*filter*/) + void set_filter(const std::string& /*which*/, + const std::string& /*filter_name*/, + const filter_info_base::sptr /*filter*/) { - throw uhd::runtime_error("ad9361_ctrl::set_filter is not supported over an RPC connection"); + throw uhd::runtime_error( + "ad9361_ctrl::set_filter is not supported over an RPC connection"); } void output_digital_test_tone(bool enb) @@ -150,13 +145,11 @@ ad9361_ctrl::sptr make_rpc(rpc_client::sptr rpcc) return ad9361_ctrl::sptr(new neon_ad9361_iface(rpcc)); } -/*! Helper function to convert direction and channel to the 'which' required by most Catalina - driver functions */ +/*! Helper function to convert direction and channel to the 'which' required by most + Catalina driver functions */ std::string get_which_ad9361_chain(const direction_t dir, const size_t chan) { UHD_ASSERT_THROW(dir == RX_DIRECTION or dir == TX_DIRECTION); UHD_ASSERT_THROW(chan == 0 or chan == 1); - return str(boost::format("%s%d") - % (dir == RX_DIRECTION ? "RX" : "TX") - % (chan + 1)); + return str(boost::format("%s%d") % (dir == RX_DIRECTION ? "RX" : "TX") % (chan + 1)); } diff --git a/host/lib/usrp/dboard/neon/neon_bands.cpp b/host/lib/usrp/dboard/neon/neon_bands.cpp index 25aa0a181..303d2801d 100644 --- a/host/lib/usrp/dboard/neon/neon_bands.cpp +++ b/host/lib/usrp/dboard/neon/neon_bands.cpp @@ -4,8 +4,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include "neon_radio_ctrl_impl.hpp" #include "neon_constants.hpp" +#include "neon_radio_ctrl_impl.hpp" #include <uhd/utils/math.hpp> /* @@ -51,54 +51,55 @@ using namespace uhd::rfnoc; using namespace uhd::math::fp_compare; namespace { - /* Note on the RX filter bank: - * - * The RX path has 7 bands, which we call LB_B2, B3, .. HB same as - * the schematic. - * - * The following constants define lower cutoff frequencies for each band. - * LB_B2 does not have a lower cutoff frequency, it is implied by - * AD9361_MIN_FREQ. NEON_RX_BAND1_MIN_FREQ is the cutover frequency - * for switching from LB_B2 to LB_B3, and so on. - * - * Bands 1-6 have both high- and low-pass filters (effectively band - * passes). Frequencies need to be chosen to allow as much of the full - * bandwidth through unattenuated. - */ - constexpr double NEON_RX_LB_BAND3_MIN_FREQ = 450e6; - constexpr double NEON_RX_LB_BAND4_MIN_FREQ = 700e6; - constexpr double NEON_RX_LB_BAND5_MIN_FREQ = 1200e6; - constexpr double NEON_RX_LB_BAND6_MIN_FREQ = 1800e6; - constexpr double NEON_RX_LB_BAND7_MIN_FREQ = 2350e6; - constexpr double NEON_RX_HB_MIN_FREQ = 2600e6; +/* Note on the RX filter bank: + * + * The RX path has 7 bands, which we call LB_B2, B3, .. HB same as + * the schematic. + * + * The following constants define lower cutoff frequencies for each band. + * LB_B2 does not have a lower cutoff frequency, it is implied by + * AD9361_MIN_FREQ. NEON_RX_BAND1_MIN_FREQ is the cutover frequency + * for switching from LB_B2 to LB_B3, and so on. + * + * Bands 1-6 have both high- and low-pass filters (effectively band + * passes). Frequencies need to be chosen to allow as much of the full + * bandwidth through unattenuated. + */ +constexpr double NEON_RX_LB_BAND3_MIN_FREQ = 450e6; +constexpr double NEON_RX_LB_BAND4_MIN_FREQ = 700e6; +constexpr double NEON_RX_LB_BAND5_MIN_FREQ = 1200e6; +constexpr double NEON_RX_LB_BAND6_MIN_FREQ = 1800e6; +constexpr double NEON_RX_LB_BAND7_MIN_FREQ = 2350e6; +constexpr double NEON_RX_HB_MIN_FREQ = 2600e6; - /* Note on the TX filter bank: - * - * The TX path has 9 bands, which we name according to the schematic. - * - * The following constants define lower cutoff frequencies for each band. - * LB_80 does not have a lower cutoff frequency, it is implied by - * AD9361_MIN_FREQ. NEON_TX_LB_160_MIN_FREQ is the cutover frequency - * for switching from LB_80 to LB_160, and so on. - * - * On current Neon revisions, all filters on the TX filter bank are - * low pass filters (no high pass filters). - * Frequencies need to be chosen to allow as much of the full bandwidth - * through unattenuated (so don't go all the way up to the cutoff frequency - * of that filter). - */ - constexpr double NEON_TX_LB_160_MIN_FREQ = 117.7e6; - constexpr double NEON_TX_LB_225_MIN_FREQ = 178.2e6; - constexpr double NEON_TX_LB_400_MIN_FREQ = 284.3e6; - constexpr double NEON_TX_LB_575_MIN_FREQ = 453.7e6; - constexpr double NEON_TX_LB_1000_MIN_FREQ = 723.8e6; - constexpr double NEON_TX_LB_1700_MIN_FREQ = 1154.9e6; - constexpr double NEON_TX_LB_2750_MIN_FREQ = 1842.6e6; - constexpr double NEON_TX_HB_MIN_FREQ = 2940.0e6; -} +/* Note on the TX filter bank: + * + * The TX path has 9 bands, which we name according to the schematic. + * + * The following constants define lower cutoff frequencies for each band. + * LB_80 does not have a lower cutoff frequency, it is implied by + * AD9361_MIN_FREQ. NEON_TX_LB_160_MIN_FREQ is the cutover frequency + * for switching from LB_80 to LB_160, and so on. + * + * On current Neon revisions, all filters on the TX filter bank are + * low pass filters (no high pass filters). + * Frequencies need to be chosen to allow as much of the full bandwidth + * through unattenuated (so don't go all the way up to the cutoff frequency + * of that filter). + */ +constexpr double NEON_TX_LB_160_MIN_FREQ = 117.7e6; +constexpr double NEON_TX_LB_225_MIN_FREQ = 178.2e6; +constexpr double NEON_TX_LB_400_MIN_FREQ = 284.3e6; +constexpr double NEON_TX_LB_575_MIN_FREQ = 453.7e6; +constexpr double NEON_TX_LB_1000_MIN_FREQ = 723.8e6; +constexpr double NEON_TX_LB_1700_MIN_FREQ = 1154.9e6; +constexpr double NEON_TX_LB_2750_MIN_FREQ = 1842.6e6; +constexpr double NEON_TX_HB_MIN_FREQ = 2940.0e6; +} // namespace -neon_radio_ctrl_impl::rx_band -neon_radio_ctrl_impl::_map_freq_to_rx_band(const double freq) { +neon_radio_ctrl_impl::rx_band neon_radio_ctrl_impl::_map_freq_to_rx_band( + const double freq) +{ neon_radio_ctrl_impl::rx_band band; if (fp_compare_epsilon<double>(freq) < AD9361_RX_MIN_FREQ) { @@ -124,8 +125,9 @@ neon_radio_ctrl_impl::_map_freq_to_rx_band(const double freq) { return band; } -neon_radio_ctrl_impl::tx_band -neon_radio_ctrl_impl::_map_freq_to_tx_band(const double freq) { +neon_radio_ctrl_impl::tx_band neon_radio_ctrl_impl::_map_freq_to_tx_band( + const double freq) +{ neon_radio_ctrl_impl::tx_band band; if (fp_compare_epsilon<double>(freq) < AD9361_TX_MIN_FREQ) { @@ -154,4 +156,3 @@ neon_radio_ctrl_impl::_map_freq_to_tx_band(const double freq) { return band; } - diff --git a/host/lib/usrp/dboard/neon/neon_constants.hpp b/host/lib/usrp/dboard/neon/neon_constants.hpp index 58e5244fc..42cfb6579 100644 --- a/host/lib/usrp/dboard/neon/neon_constants.hpp +++ b/host/lib/usrp/dboard/neon/neon_constants.hpp @@ -7,16 +7,16 @@ #ifndef INCLUDED_LIBUHD_NEON_CONSTANTS_HPP #define INCLUDED_LIBUHD_NEON_CONSTANTS_HPP -#include <vector> -#include <string> #include <cstddef> +#include <string> +#include <vector> -static constexpr size_t FPGPIO_MASTER_RADIO = 0; -static constexpr size_t TOTAL_RADIO_PORTS = 2; -static constexpr double AD9361_RX_MIN_BANDWIDTH = 20.0e6; // HZ +static constexpr size_t FPGPIO_MASTER_RADIO = 0; +static constexpr size_t TOTAL_RADIO_PORTS = 2; +static constexpr double AD9361_RX_MIN_BANDWIDTH = 20.0e6; // HZ static constexpr double AD9361_RX_MAX_BANDWIDTH = 40.0e6; // HZ -static constexpr double AD9361_TX_MIN_BANDWIDTH = 20.0e6; // HZ +static constexpr double AD9361_TX_MIN_BANDWIDTH = 20.0e6; // HZ static constexpr double AD9361_TX_MAX_BANDWIDTH = 40.0e6; // HZ static constexpr double AD9361_TX_MIN_FREQ = 47.0e6; // Hz @@ -27,27 +27,25 @@ static constexpr double AD9361_RX_MAX_FREQ = 6.0e9; // Hz static constexpr double NEON_RADIO_RATE = 16e6; // Hz -static constexpr double AD9361_MIN_RX_GAIN = 0.0; // dB -static constexpr double AD9361_MAX_RX_GAIN = 76; // dB +static constexpr double AD9361_MIN_RX_GAIN = 0.0; // dB +static constexpr double AD9361_MAX_RX_GAIN = 76; // dB static constexpr double AD9361_RX_GAIN_STEP = 1.0; // dB -static constexpr double AD9361_MIN_TX_GAIN = 0.0; // dB -static constexpr double AD9361_MAX_TX_GAIN = 89.75; // dB +static constexpr double AD9361_MIN_TX_GAIN = 0.0; // dB +static constexpr double AD9361_MAX_TX_GAIN = 89.75; // dB static constexpr double AD9361_TX_GAIN_STEP = 0.25; // dB -static constexpr bool NEON_DEFAULT_AUTO_DC_OFFSET = true; +static constexpr bool NEON_DEFAULT_AUTO_DC_OFFSET = true; static constexpr bool NEON_DEFAULT_AUTO_IQ_BALANCE = true; -static constexpr bool NEON_DEFAULT_AGC_ENABLE = false; +static constexpr bool NEON_DEFAULT_AGC_ENABLE = false; -static constexpr double NEON_DEFAULT_GAIN = 0.0; -static constexpr double NEON_DEFAULT_FREQ = 2.4e9; // Hz -static constexpr double NEON_DEFAULT_BANDWIDTH = 40e6; // Hz -static constexpr char NEON_DEFAULT_RX_ANTENNA[] = "RX2"; -static constexpr char NEON_DEFAULT_TX_ANTENNA[] = "TX/RX"; +static constexpr double NEON_DEFAULT_GAIN = 0.0; +static constexpr double NEON_DEFAULT_FREQ = 2.4e9; // Hz +static constexpr double NEON_DEFAULT_BANDWIDTH = 40e6; // Hz +static constexpr char NEON_DEFAULT_RX_ANTENNA[] = "RX2"; +static constexpr char NEON_DEFAULT_TX_ANTENNA[] = "TX/RX"; -static const std::vector<std::string> NEON_RX_ANTENNAS = { - "RX2", "TX/RX" -}; +static const std::vector<std::string> NEON_RX_ANTENNAS = {"RX2", "TX/RX"}; static constexpr size_t NEON_NUM_CHANS = 2; diff --git a/host/lib/usrp/dboard/neon/neon_radio_ctrl_impl.cpp b/host/lib/usrp/dboard/neon/neon_radio_ctrl_impl.cpp index 71e467848..d8fabcee0 100644 --- a/host/lib/usrp/dboard/neon/neon_radio_ctrl_impl.cpp +++ b/host/lib/usrp/dboard/neon/neon_radio_ctrl_impl.cpp @@ -7,20 +7,20 @@ #include "neon_radio_ctrl_impl.hpp" #include "neon_constants.hpp" #include "neon_regs.hpp" -#include <uhd/utils/log.hpp> +#include <uhd/exception.hpp> #include <uhd/rfnoc/node_ctrl_base.hpp> #include <uhd/transport/chdr.hpp> -#include <uhd/utils/algorithm.hpp> -#include <uhd/utils/math.hpp> #include <uhd/types/direction.hpp> #include <uhd/types/eeprom.hpp> -#include <uhd/exception.hpp> +#include <uhd/utils/algorithm.hpp> +#include <uhd/utils/log.hpp> +#include <uhd/utils/math.hpp> #include <boost/algorithm/string.hpp> -#include <boost/make_shared.hpp> #include <boost/format.hpp> -#include <sstream> +#include <boost/make_shared.hpp> #include <cmath> #include <cstdlib> +#include <sstream> using namespace uhd; using namespace uhd::usrp; @@ -34,7 +34,7 @@ UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(neon_radio_ctrl) { UHD_LOG_TRACE(unique_id(), "Entering neon_radio_ctrl_impl ctor..."); const char radio_slot_name[1] = {'A'}; - _radio_slot = radio_slot_name[get_block_id().get_block_count()]; + _radio_slot = radio_slot_name[get_block_id().get_block_count()]; UHD_LOG_TRACE(unique_id(), "Radio slot: " << _radio_slot); _rpc_prefix = "db_0_"; @@ -58,38 +58,39 @@ bool neon_radio_ctrl_impl::check_radio_config() // mapping of frontend to radio perif index static const size_t FE0 = 0; static const size_t FE1 = 1; - const size_t num_rx = _is_streamer_active(RX_DIRECTION, FE0) + _is_streamer_active(RX_DIRECTION, FE1); - const size_t num_tx = _is_streamer_active(TX_DIRECTION, FE0) + _is_streamer_active(TX_DIRECTION, FE1); + const size_t num_rx = + _is_streamer_active(RX_DIRECTION, FE0) + _is_streamer_active(RX_DIRECTION, FE1); + const size_t num_tx = + _is_streamer_active(TX_DIRECTION, FE0) + _is_streamer_active(TX_DIRECTION, FE1); - //setup the active chains in the codec + // setup the active chains in the codec if ((num_rx + num_tx) == 0) { // Ensure at least one RX chain is enabled so AD9361 outputs a sample clock this->set_streaming_mode(false, false, true, false); } else { - this->set_streaming_mode( - _is_streamer_active(TX_DIRECTION, FE0), - _is_streamer_active(TX_DIRECTION, FE1), - _is_streamer_active(RX_DIRECTION, FE0), - _is_streamer_active(RX_DIRECTION, FE1) - ); + this->set_streaming_mode(_is_streamer_active(TX_DIRECTION, FE0), + _is_streamer_active(TX_DIRECTION, FE1), + _is_streamer_active(RX_DIRECTION, FE0), + _is_streamer_active(RX_DIRECTION, FE1)); } return true; } -void neon_radio_ctrl_impl::set_streaming_mode(const bool tx1, const bool tx2, const bool rx1, const bool rx2) +void neon_radio_ctrl_impl::set_streaming_mode( + const bool tx1, const bool tx2, const bool rx1, const bool rx2) { UHD_LOG_TRACE(unique_id(), "Setting up streaming ...") const size_t num_rx = rx1 + rx2; const size_t num_tx = tx1 + tx2; - //setup the active chains in the codec + // setup the active chains in the codec _ad9361->set_active_chains(tx1, tx2, rx1, rx2); const std::string TIMING_MODE_2R2T = "2R2T"; const std::string TIMING_MODE_1R1T = "1R1T"; - const std::string MIMO = "MIMO"; // 2R2T - const std::string SISO_TX1 = "SISO_TX1"; // 1R1T - const std::string SISO_TX0 = "SISO_TX0"; // 1R1T + const std::string MIMO = "MIMO"; // 2R2T + const std::string SISO_TX1 = "SISO_TX1"; // 1R1T + const std::string SISO_TX0 = "SISO_TX0"; // 1R1T // setup 1R1T/2R2T mode in catalina and fpga // The Catalina interface in the fpga needs to know which TX channel to use for // the data on the LVDS lines. @@ -107,11 +108,11 @@ void neon_radio_ctrl_impl::set_streaming_mode(const bool tx1, const bool tx2, co } } -void neon_radio_ctrl_impl::set_channel_mode(const std::string &channel_mode) +void neon_radio_ctrl_impl::set_channel_mode(const std::string& channel_mode) { - //MIMO for 2R2T mode for 2 channels - //SISO_TX1 for 1R1T mode for 1 channel - TX1 - //SISO_TX0 for 1R1T mode for 1 channel - TX0 + // MIMO for 2R2T mode for 2 channels + // SISO_TX1 for 1R1T mode for 1 channel - TX1 + // SISO_TX0 for 1R1T mode for 1 channel - TX0 _rpcc->request_with_token<void>("set_channel_mode", channel_mode); } @@ -127,9 +128,8 @@ void neon_radio_ctrl_impl::set_channel_mode(const std::string &channel_mode) Note: This currently only tests 2R2T mode */ void neon_radio_ctrl_impl::loopback_self_test( - std::function<void(uint32_t)> poker_functor, - std::function<uint64_t()> peeker_functor -) { + std::function<void(uint32_t)> poker_functor, std::function<uint64_t()> peeker_functor) +{ // Save current rate before running this test const double current_rate = this->get_rate(); // Set 2R2T mode, stream on all channels @@ -139,7 +139,7 @@ void neon_radio_ctrl_impl::loopback_self_test( // Put AD936x in loopback mode _ad9361->data_port_loopback(true); UHD_LOG_INFO(unique_id(), "Performing CODEC loopback test... "); - size_t hash = size_t(time(NULL)); + size_t hash = size_t(time(NULL)); constexpr size_t loopback_count = 100; // Allow some time for AD936x to enter loopback mode. @@ -150,27 +150,26 @@ void neon_radio_ctrl_impl::loopback_self_test( // Sleeping 1ms is far more than enough. std::this_thread::sleep_for(std::chrono::milliseconds(1)); - for (size_t i = 0; i < loopback_count; i++) - { + for (size_t i = 0; i < loopback_count; i++) { // Create test word boost::hash_combine(hash, i); const uint32_t word32 = uint32_t(hash) & 0xfff0fff0; - //const uint32_t word32 = 0xCA00C100; + // const uint32_t word32 = 0xCA00C100; // Write test word to codec_idle idle register (on TX side) poker_functor(word32); // Read back values - TX is lower 32-bits and RX is upper 32-bits const uint64_t rb_word64 = peeker_functor(); - const uint32_t rb_tx = uint32_t(rb_word64 >> 32); - const uint32_t rb_rx = uint32_t(rb_word64 & 0xffffffff); + const uint32_t rb_tx = uint32_t(rb_word64 >> 32); + const uint32_t rb_rx = uint32_t(rb_word64 & 0xffffffff); // Compare TX and RX values to test word bool test_fail = word32 != rb_tx or word32 != rb_rx; - if(test_fail) - { - UHD_LOG_WARNING(unique_id(), "CODEC loopback test failed! " - << boost::format("Expected: 0x%08X Received (TX/RX): 0x%08X/0x%08X") - % word32 % rb_tx % rb_rx); + if (test_fail) { + UHD_LOG_WARNING(unique_id(), + "CODEC loopback test failed! " + << boost::format("Expected: 0x%08X Received (TX/RX): 0x%08X/0x%08X") + % word32 % rb_tx % rb_rx); throw uhd::runtime_error("CODEC loopback test failed."); } } @@ -189,63 +188,50 @@ void neon_radio_ctrl_impl::loopback_self_test( double neon_radio_ctrl_impl::set_rate(const double rate) { std::lock_guard<std::mutex> l(_set_lock); - UHD_LOG_DEBUG(unique_id(), "Asking for clock rate " << rate/1e6 << " MHz\n"); + UHD_LOG_DEBUG(unique_id(), "Asking for clock rate " << rate / 1e6 << " MHz\n"); double actual_tick_rate = _ad9361->set_clock_rate(rate); - UHD_LOG_DEBUG(unique_id(), "Actual clock rate " << actual_tick_rate/1e6 << " MHz\n"); + UHD_LOG_DEBUG( + unique_id(), "Actual clock rate " << actual_tick_rate / 1e6 << " MHz\n"); radio_ctrl_impl::set_rate(rate); return rate; } -void neon_radio_ctrl_impl::set_tx_antenna( - const std::string &ant, - const size_t chan -) { +void neon_radio_ctrl_impl::set_tx_antenna(const std::string& ant, const size_t chan) +{ if (ant != get_tx_antenna(chan)) { - throw uhd::value_error(str( - boost::format("[%s] Requesting invalid TX antenna value: %s") - % unique_id() - % ant - )); + throw uhd::value_error( + str(boost::format("[%s] Requesting invalid TX antenna value: %s") + % unique_id() % ant)); } radio_ctrl_impl::set_tx_antenna(ant, chan); // We can't actually set the TX antenna, so let's stop here. } -void neon_radio_ctrl_impl::set_rx_antenna( - const std::string &ant, - const size_t chan -) { +void neon_radio_ctrl_impl::set_rx_antenna(const std::string& ant, const size_t chan) +{ UHD_ASSERT_THROW(chan <= NEON_NUM_CHANS); - if (std::find(NEON_RX_ANTENNAS.begin(), - NEON_RX_ANTENNAS.end(), - ant) == NEON_RX_ANTENNAS.end()) { - throw uhd::value_error(str( - boost::format("[%s] Requesting invalid RX antenna value: %s") - % unique_id() - % ant - )); + if (std::find(NEON_RX_ANTENNAS.begin(), NEON_RX_ANTENNAS.end(), ant) + == NEON_RX_ANTENNAS.end()) { + throw uhd::value_error( + str(boost::format("[%s] Requesting invalid RX antenna value: %s") + % unique_id() % ant)); } - UHD_LOG_TRACE(unique_id(), - "Setting RX antenna to " << ant << " for chan " << chan); + UHD_LOG_TRACE(unique_id(), "Setting RX antenna to " << ant << " for chan " << chan); radio_ctrl_impl::set_rx_antenna(ant, chan); _set_atr_bits(chan); } -double neon_radio_ctrl_impl::set_tx_frequency( - const double freq, - const size_t chan -) { - UHD_LOG_TRACE(unique_id(), - "set_tx_frequency(f=" << freq << ", chan=" << chan << ")"); +double neon_radio_ctrl_impl::set_tx_frequency(const double freq, const size_t chan) +{ + UHD_LOG_TRACE(unique_id(), "set_tx_frequency(f=" << freq << ", chan=" << chan << ")"); std::lock_guard<std::mutex> l(_set_lock); double clipped_freq = uhd::clip(freq, AD9361_TX_MIN_FREQ, AD9361_TX_MAX_FREQ); - double coerced_freq = _ad9361->tune( - get_which_ad9361_chain(TX_DIRECTION, chan), - clipped_freq); + double coerced_freq = + _ad9361->tune(get_which_ad9361_chain(TX_DIRECTION, chan), clipped_freq); radio_ctrl_impl::set_tx_frequency(coerced_freq, chan); // Front-end switching _set_atr_bits(chan); @@ -253,19 +239,15 @@ double neon_radio_ctrl_impl::set_tx_frequency( return coerced_freq; } -double neon_radio_ctrl_impl::set_rx_frequency( - const double freq, - const size_t chan -) { - UHD_LOG_TRACE(unique_id(), - "set_rx_frequency(f=" << freq << ", chan=" << chan << ")"); +double neon_radio_ctrl_impl::set_rx_frequency(const double freq, const size_t chan) +{ + UHD_LOG_TRACE(unique_id(), "set_rx_frequency(f=" << freq << ", chan=" << chan << ")"); std::lock_guard<std::mutex> l(_set_lock); double clipped_freq = uhd::clip(freq, AD9361_RX_MIN_FREQ, AD9361_RX_MAX_FREQ); - double coerced_freq = _ad9361->tune( - get_which_ad9361_chain(RX_DIRECTION, chan), - clipped_freq); + double coerced_freq = + _ad9361->tune(get_which_ad9361_chain(RX_DIRECTION, chan), clipped_freq); radio_ctrl_impl::set_rx_frequency(coerced_freq, chan); // Front-end switching _set_atr_bits(chan); @@ -273,63 +255,48 @@ double neon_radio_ctrl_impl::set_rx_frequency( return coerced_freq; } -double neon_radio_ctrl_impl::set_rx_bandwidth( - const double bandwidth, - const size_t chan -) { +double neon_radio_ctrl_impl::set_rx_bandwidth(const double bandwidth, const size_t chan) +{ std::lock_guard<std::mutex> l(_set_lock); - double clipped_bw = _ad9361->set_bw_filter( - get_which_ad9361_chain(RX_DIRECTION, chan), - bandwidth); + double clipped_bw = + _ad9361->set_bw_filter(get_which_ad9361_chain(RX_DIRECTION, chan), bandwidth); return radio_ctrl_impl::set_rx_bandwidth(clipped_bw, chan); } -double neon_radio_ctrl_impl::set_tx_bandwidth( - const double bandwidth, - const size_t chan -) { +double neon_radio_ctrl_impl::set_tx_bandwidth(const double bandwidth, const size_t chan) +{ std::lock_guard<std::mutex> l(_set_lock); - double clipped_bw = _ad9361->set_bw_filter( - get_which_ad9361_chain(TX_DIRECTION, chan), - bandwidth); + double clipped_bw = + _ad9361->set_bw_filter(get_which_ad9361_chain(TX_DIRECTION, chan), bandwidth); return radio_ctrl_impl::set_tx_bandwidth(clipped_bw, chan); } -double neon_radio_ctrl_impl::set_tx_gain( - const double gain, - const size_t chan -) { +double neon_radio_ctrl_impl::set_tx_gain(const double gain, const size_t chan) +{ std::lock_guard<std::mutex> l(_set_lock); - UHD_LOG_TRACE(unique_id(), - "set_tx_gain(gain=" << gain << ", chan=" << chan << ")"); + UHD_LOG_TRACE(unique_id(), "set_tx_gain(gain=" << gain << ", chan=" << chan << ")"); double clip_gain = uhd::clip(gain, AD9361_MIN_TX_GAIN, AD9361_MAX_TX_GAIN); - _ad9361->set_gain( - get_which_ad9361_chain(TX_DIRECTION, chan), - clip_gain); + _ad9361->set_gain(get_which_ad9361_chain(TX_DIRECTION, chan), clip_gain); radio_ctrl_impl::set_tx_gain(clip_gain, chan); return clip_gain; } -double neon_radio_ctrl_impl::set_rx_gain( - const double gain, - const size_t chan -) { +double neon_radio_ctrl_impl::set_rx_gain(const double gain, const size_t chan) +{ std::lock_guard<std::mutex> l(_set_lock); - UHD_LOG_TRACE(unique_id(), - "set_rx_gain(gain=" << gain << ", chan=" << chan << ")"); + UHD_LOG_TRACE(unique_id(), "set_rx_gain(gain=" << gain << ", chan=" << chan << ")"); double clip_gain = uhd::clip(gain, AD9361_MIN_RX_GAIN, AD9361_MAX_RX_GAIN); - _ad9361->set_gain( - get_which_ad9361_chain(RX_DIRECTION, chan), - clip_gain); + _ad9361->set_gain(get_which_ad9361_chain(RX_DIRECTION, chan), clip_gain); radio_ctrl_impl::set_rx_gain(clip_gain, chan); return clip_gain; } size_t neon_radio_ctrl_impl::get_chan_from_dboard_fe( - const std::string &fe, const direction_t /* dir */ -) { + const std::string& fe, const direction_t /* dir */ +) +{ const size_t chan = boost::lexical_cast<size_t>(fe); - if (chan > _get_num_radios()-1) { + if (chan > _get_num_radios() - 1) { UHD_LOG_WARNING(unique_id(), boost::format("Invalid channel determined from dboard frontend %s.") % fe); } @@ -337,122 +304,107 @@ size_t neon_radio_ctrl_impl::get_chan_from_dboard_fe( } std::string neon_radio_ctrl_impl::get_dboard_fe_from_chan( - const size_t chan, - const direction_t /* dir */ -) { + const size_t chan, const direction_t /* dir */ +) +{ return std::to_string(chan); } void neon_radio_ctrl_impl::set_rpc_client( - uhd::rpc_client::sptr rpcc, - const uhd::device_addr_t &block_args -) { - _rpcc = rpcc; + uhd::rpc_client::sptr rpcc, const uhd::device_addr_t& block_args) +{ + _rpcc = rpcc; _block_args = block_args; UHD_LOG_TRACE(unique_id(), "Instantiating AD9361 control object..."); _ad9361 = make_rpc(_rpcc); UHD_LOG_TRACE(unique_id(), "Setting Catalina Defaults... "); - //Initialize catalina + // Initialize catalina this->_init_codec(); if (block_args.has_key("identify")) { const std::string identify_val = block_args.get("identify"); - int identify_duration = std::atoi(identify_val.c_str()); + int identify_duration = std::atoi(identify_val.c_str()); if (identify_duration == 0) { identify_duration = 5; } UHD_LOG_INFO(unique_id(), "Running LED identification process for " << identify_duration - << " seconds."); + << " seconds."); _identify_with_leds(identify_duration); } // Note: MCR gets set during the init() call (prior to this), which takes // in arguments from the device args. So if block_args contains a // master_clock_rate key, then it should better be whatever the device is // configured to do. - _master_clock_rate = _rpcc->request_with_token<double>( - _rpc_prefix + "get_master_clock_rate"); + _master_clock_rate = + _rpcc->request_with_token<double>(_rpc_prefix + "get_master_clock_rate"); if (block_args.cast<double>("master_clock_rate", _master_clock_rate) - != _master_clock_rate) { + != _master_clock_rate) { throw uhd::runtime_error(str( boost::format("Master clock rate mismatch. Device returns %f MHz, " "but should have been %f MHz.") % (_master_clock_rate / 1e6) - % (block_args.cast<double>( - "master_clock_rate", _master_clock_rate) / 1e6) - )); - + % (block_args.cast<double>("master_clock_rate", _master_clock_rate) / 1e6))); } - UHD_LOG_DEBUG(unique_id(), - "Master Clock Rate is: " << (_master_clock_rate / 1e6) << " MHz."); + UHD_LOG_DEBUG( + unique_id(), "Master Clock Rate is: " << (_master_clock_rate / 1e6) << " MHz."); this->set_rate(_master_clock_rate); // Loopback test for (size_t chan = 0; chan < _get_num_radios(); chan++) { loopback_self_test( - [this, chan](const uint32_t value){ - this->sr_write(regs::CODEC_IDLE, value, chan); - }, - [this, chan](){ + [this, chan]( + const uint32_t value) { this->sr_write(regs::CODEC_IDLE, value, chan); }, + [this, chan]() { return this->user_reg_read64(regs::RB_CODEC_READBACK, chan); - } - ); + }); } const size_t db_idx = get_block_id().get_block_count(); _tree->access<eeprom_map_t>(_root_path / "eeprom") - .add_coerced_subscriber([this, db_idx](const eeprom_map_t& db_eeprom){ + .add_coerced_subscriber([this, db_idx](const eeprom_map_t& db_eeprom) { this->_rpcc->notify_with_token("set_db_eeprom", db_idx, db_eeprom); }) - .set_publisher([this, db_idx](){ - return this->_rpcc->request_with_token<eeprom_map_t>( - "get_db_eeprom", db_idx - ); - }) - ; + .set_publisher([this, db_idx]() { + return this->_rpcc->request_with_token<eeprom_map_t>("get_db_eeprom", db_idx); + }); // Init sensors - for (const auto &dir : std::vector<direction_t>{RX_DIRECTION, TX_DIRECTION}) { + for (const auto& dir : std::vector<direction_t>{RX_DIRECTION, TX_DIRECTION}) { for (size_t chan_idx = 0; chan_idx < NEON_NUM_CHANS; chan_idx++) { _init_mpm_sensors(dir, chan_idx); } } } -bool neon_radio_ctrl_impl::get_lo_lock_status( - const direction_t dir -) { - if (not (bool(_rpcc))) { - UHD_LOG_DEBUG(unique_id(), - "Reported no LO lock due to lack of RPC connection."); +bool neon_radio_ctrl_impl::get_lo_lock_status(const direction_t dir) +{ + if (not(bool(_rpcc))) { + UHD_LOG_DEBUG(unique_id(), "Reported no LO lock due to lack of RPC connection."); return false; } const std::string trx = (dir == RX_DIRECTION) ? "rx" : "tx"; - bool lo_lock = _rpcc->request_with_token<bool>( - _rpc_prefix + "get_ad9361_lo_lock", trx); + bool lo_lock = + _rpcc->request_with_token<bool>(_rpc_prefix + "get_ad9361_lo_lock", trx); UHD_LOG_TRACE(unique_id(), "AD9361 " << trx << " LO reports lock: " << (lo_lock ? "Yes" : "No")); return lo_lock; } -void neon_radio_ctrl_impl::_set_atr_bits( - const size_t chan -) { - const auto rx_freq = radio_ctrl_impl::get_rx_frequency(chan); - const auto tx_freq = radio_ctrl_impl::get_tx_frequency(chan); - const auto rx_ant = radio_ctrl_impl::get_rx_antenna(chan); - const uint32_t rx_regs = _get_rx_switches(chan, rx_freq, rx_ant); - const uint32_t tx_regs = _get_tx_switches(chan, tx_freq); - const uint32_t idle_regs = TX_AMP_OFF << TX_AMP_SHIFT | - TRX1_SW_TX_HB << TRX_SW_SHIFT | - TX_SW2_LB_80 << TX_SW2_SHIFT | - TX_SW1_LB_80 << TX_SW1_SHIFT | - RX_SW3_OFF << RX_SW3_SHIFT | - RX_SW2_OFF << RX_SW2_SHIFT | - RX_SW1_OFF << RX_SW1_SHIFT; +void neon_radio_ctrl_impl::_set_atr_bits(const size_t chan) +{ + const auto rx_freq = radio_ctrl_impl::get_rx_frequency(chan); + const auto tx_freq = radio_ctrl_impl::get_tx_frequency(chan); + const auto rx_ant = radio_ctrl_impl::get_rx_antenna(chan); + const uint32_t rx_regs = _get_rx_switches(chan, rx_freq, rx_ant); + const uint32_t tx_regs = _get_tx_switches(chan, tx_freq); + const uint32_t idle_regs = TX_AMP_OFF << TX_AMP_SHIFT | TRX1_SW_TX_HB << TRX_SW_SHIFT + | TX_SW2_LB_80 << TX_SW2_SHIFT + | TX_SW1_LB_80 << TX_SW1_SHIFT | RX_SW3_OFF << RX_SW3_SHIFT + | RX_SW2_OFF << RX_SW2_SHIFT | RX_SW1_OFF << RX_SW1_SHIFT; _db_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_IDLE, idle_regs); _db_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_RX_ONLY, rx_regs); @@ -462,21 +414,21 @@ void neon_radio_ctrl_impl::_set_atr_bits( // The LED signal names are reversed, but are consistent with the schematic const int idle_led = 0; const bool is_txrx = rx_ant == "TX/RX"; - const int rx_led = 1 << TRX_LED_GRN_SHIFT; - const int tx_led = 1 << TX_LED_RED_SHIFT; + const int rx_led = 1 << TRX_LED_GRN_SHIFT; + const int tx_led = 1 << TX_LED_RED_SHIFT; const int txrx_led = 1 << RX_LED_GRN_SHIFT; _leds_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_IDLE, idle_led); - _leds_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_RX_ONLY, is_txrx ? txrx_led : rx_led); + _leds_gpio[chan]->set_atr_reg( + usrp::gpio_atr::ATR_REG_RX_ONLY, is_txrx ? txrx_led : rx_led); _leds_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_TX_ONLY, tx_led); _leds_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_FULL_DUPLEX, rx_led | tx_led); } -void neon_radio_ctrl_impl::_identify_with_leds( - const int identify_duration -) { - auto end_time = std::chrono::steady_clock::now() - + std::chrono::seconds(identify_duration); +void neon_radio_ctrl_impl::_identify_with_leds(const int identify_duration) +{ + auto end_time = + std::chrono::steady_clock::now() + std::chrono::seconds(identify_duration); bool led_state = true; while (std::chrono::steady_clock::now() < end_time) { // Add update_leds @@ -485,141 +437,126 @@ void neon_radio_ctrl_impl::_identify_with_leds( } } -uint32_t neon_radio_ctrl_impl::_get_tx_switches( - const size_t chan, - const double freq -) { - - UHD_LOG_TRACE(unique_id(), - "Update all TX freq related switches. f=" << freq << " Hz, " - ); +uint32_t neon_radio_ctrl_impl::_get_tx_switches(const size_t chan, const double freq) +{ + UHD_LOG_TRACE( + unique_id(), "Update all TX freq related switches. f=" << freq << " Hz, "); auto tx_sw1 = TX_SW1_LB_160; auto tx_sw2 = TX_SW2_LB_160; - auto trx_sw = (chan == 0) ? TRX1_SW_TX_LB: TRX2_SW_TX_LB; + auto trx_sw = (chan == 0) ? TRX1_SW_TX_LB : TRX2_SW_TX_LB; auto tx_amp = TX_AMP_LF_ON; const auto band = _map_freq_to_tx_band(freq); - switch(band) { - case tx_band::LB_80: - tx_sw1 = TX_SW1_LB_80; - tx_sw2 = TX_SW2_LB_80; - break; - case tx_band::LB_160: - tx_sw1 = TX_SW1_LB_160; - tx_sw2 = TX_SW2_LB_160; - break; - case tx_band::LB_225: - tx_sw1 = TX_SW1_LB_225; - tx_sw2 = TX_SW2_LB_225; - break; - case tx_band::LB_400: - tx_sw1 = TX_SW1_LB_400; - tx_sw2 = TX_SW2_LB_400; - break; - case tx_band::LB_575: - tx_sw1 = TX_SW1_LB_575; - tx_sw2 = TX_SW2_LB_575; - break; - case tx_band::LB_1000: - tx_sw1 = TX_SW1_LB_1000; - tx_sw2 = TX_SW2_LB_1000; - break; - case tx_band::LB_1700: - tx_sw1 = TX_SW1_LB_1700; - tx_sw2 = TX_SW2_LB_1700; - break; - case tx_band::LB_2750: - tx_sw1 = TX_SW1_LB_2750; - tx_sw2 = TX_SW2_LB_2750; - break; - case tx_band::HB: - trx_sw = (chan == 0) ? TRX1_SW_TX_HB: TRX2_SW_TX_HB; - tx_amp = TX_AMP_HF_ON; - break; - case tx_band::INVALID_BAND: - UHD_LOG_ERROR(unique_id(), - "Cannot map TX frequency to band: " << freq); - UHD_THROW_INVALID_CODE_PATH(); - break; + switch (band) { + case tx_band::LB_80: + tx_sw1 = TX_SW1_LB_80; + tx_sw2 = TX_SW2_LB_80; + break; + case tx_band::LB_160: + tx_sw1 = TX_SW1_LB_160; + tx_sw2 = TX_SW2_LB_160; + break; + case tx_band::LB_225: + tx_sw1 = TX_SW1_LB_225; + tx_sw2 = TX_SW2_LB_225; + break; + case tx_band::LB_400: + tx_sw1 = TX_SW1_LB_400; + tx_sw2 = TX_SW2_LB_400; + break; + case tx_band::LB_575: + tx_sw1 = TX_SW1_LB_575; + tx_sw2 = TX_SW2_LB_575; + break; + case tx_band::LB_1000: + tx_sw1 = TX_SW1_LB_1000; + tx_sw2 = TX_SW2_LB_1000; + break; + case tx_band::LB_1700: + tx_sw1 = TX_SW1_LB_1700; + tx_sw2 = TX_SW2_LB_1700; + break; + case tx_band::LB_2750: + tx_sw1 = TX_SW1_LB_2750; + tx_sw2 = TX_SW2_LB_2750; + break; + case tx_band::HB: + trx_sw = (chan == 0) ? TRX1_SW_TX_HB : TRX2_SW_TX_HB; + tx_amp = TX_AMP_HF_ON; + break; + case tx_band::INVALID_BAND: + UHD_LOG_ERROR(unique_id(), "Cannot map TX frequency to band: " << freq); + UHD_THROW_INVALID_CODE_PATH(); + break; } - auto tx_regs = tx_amp << TX_AMP_SHIFT | - trx_sw << TRX_SW_SHIFT | - tx_sw2 << TX_SW2_SHIFT | - tx_sw1 << TX_SW1_SHIFT; + auto tx_regs = tx_amp << TX_AMP_SHIFT | trx_sw << TRX_SW_SHIFT + | tx_sw2 << TX_SW2_SHIFT | tx_sw1 << TX_SW1_SHIFT; return tx_regs; } uint32_t neon_radio_ctrl_impl::_get_rx_switches( - const size_t chan, - const double freq, - const std::string &ant -){ - UHD_LOG_TRACE(unique_id(), - "Update all RX freq related switches. f=" << freq << " Hz, " - ); + const size_t chan, const double freq, const std::string& ant) +{ + UHD_LOG_TRACE( + unique_id(), "Update all RX freq related switches. f=" << freq << " Hz, "); // Default to OFF auto rx_sw1 = RX_SW1_OFF; auto rx_sw2 = RX_SW2_OFF; auto rx_sw3 = RX_SW3_OFF; - auto trx_sw = (chan == 0) ? TRX1_SW_RX: TRX2_SW_RX; + auto trx_sw = (chan == 0) ? TRX1_SW_RX : TRX2_SW_RX; if (ant == "TX/RX") { rx_sw3 = RX_SW3_HBRX_LBTRX; - trx_sw = (chan == 0) ? TRX1_SW_RX: TRX2_SW_RX; - } - else if (ant == "RX2") { + trx_sw = (chan == 0) ? TRX1_SW_RX : TRX2_SW_RX; + } else if (ant == "RX2") { rx_sw3 = RX_SW3_HBTRX_LBRX; // Set TRX switch to TX when receiving on RX2 trx_sw = TRX1_SW_TX_HB; } const auto band = _map_freq_to_rx_band(freq); - switch(band) { - case rx_band::LB_B2: - rx_sw1 = RX_SW1_LB_B2; - rx_sw2 = RX_SW2_LB_B2; - break; - case rx_band::LB_B3: - rx_sw1 = RX_SW1_LB_B3; - rx_sw2 = RX_SW2_LB_B3; - break; - case rx_band::LB_B4: - rx_sw1 = RX_SW1_LB_B4; - rx_sw2 = RX_SW2_LB_B4; - break; - case rx_band::LB_B5: - rx_sw1 = RX_SW1_LB_B5; - rx_sw2 = RX_SW2_LB_B5; - break; - case rx_band::LB_B6: - rx_sw1 = RX_SW1_LB_B6; - rx_sw2 = RX_SW2_LB_B6; - break; - case rx_band::LB_B7: - rx_sw1 = RX_SW1_LB_B7; - rx_sw2 = RX_SW2_LB_B7; - break; - case rx_band::HB: - rx_sw1 = RX_SW1_OFF; - rx_sw2 = RX_SW2_OFF; - if (ant == "TX/RX") { - rx_sw3 = RX_SW3_HBTRX_LBRX; - } - else if (ant == "RX2") { - rx_sw3 = RX_SW3_HBRX_LBTRX; - } - break; - case rx_band::INVALID_BAND: - UHD_LOG_ERROR(unique_id(), - "Cannot map RX frequency to band: " << freq); - UHD_THROW_INVALID_CODE_PATH(); - break; + switch (band) { + case rx_band::LB_B2: + rx_sw1 = RX_SW1_LB_B2; + rx_sw2 = RX_SW2_LB_B2; + break; + case rx_band::LB_B3: + rx_sw1 = RX_SW1_LB_B3; + rx_sw2 = RX_SW2_LB_B3; + break; + case rx_band::LB_B4: + rx_sw1 = RX_SW1_LB_B4; + rx_sw2 = RX_SW2_LB_B4; + break; + case rx_band::LB_B5: + rx_sw1 = RX_SW1_LB_B5; + rx_sw2 = RX_SW2_LB_B5; + break; + case rx_band::LB_B6: + rx_sw1 = RX_SW1_LB_B6; + rx_sw2 = RX_SW2_LB_B6; + break; + case rx_band::LB_B7: + rx_sw1 = RX_SW1_LB_B7; + rx_sw2 = RX_SW2_LB_B7; + break; + case rx_band::HB: + rx_sw1 = RX_SW1_OFF; + rx_sw2 = RX_SW2_OFF; + if (ant == "TX/RX") { + rx_sw3 = RX_SW3_HBTRX_LBRX; + } else if (ant == "RX2") { + rx_sw3 = RX_SW3_HBRX_LBTRX; + } + break; + case rx_band::INVALID_BAND: + UHD_LOG_ERROR(unique_id(), "Cannot map RX frequency to band: " << freq); + UHD_THROW_INVALID_CODE_PATH(); + break; } - auto rx_regs = trx_sw << TRX_SW_SHIFT | - rx_sw3 << RX_SW3_SHIFT | - rx_sw2 << RX_SW2_SHIFT | - rx_sw1 << RX_SW1_SHIFT; + auto rx_regs = trx_sw << TRX_SW_SHIFT | rx_sw3 << RX_SW3_SHIFT + | rx_sw2 << RX_SW2_SHIFT | rx_sw1 << RX_SW1_SHIFT; return rx_regs; } diff --git a/host/lib/usrp/dboard/neon/neon_radio_ctrl_impl.hpp b/host/lib/usrp/dboard/neon/neon_radio_ctrl_impl.hpp index ac7fd70e9..88d1eed73 100644 --- a/host/lib/usrp/dboard/neon/neon_radio_ctrl_impl.hpp +++ b/host/lib/usrp/dboard/neon/neon_radio_ctrl_impl.hpp @@ -11,13 +11,12 @@ #include <uhd/types/serial.hpp> #include <uhd/usrp/dboard_manager.hpp> #include <uhd/usrp/gpio_defs.hpp> -#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> -#include <uhdlib/rfnoc/rpc_block_ctrl.hpp> #include <uhdlib/rfnoc/radio_ctrl_impl.hpp> +#include <uhdlib/rfnoc/rpc_block_ctrl.hpp> +#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> #include <mutex> -namespace uhd { - namespace rfnoc { +namespace uhd { namespace rfnoc { /*! \brief Provide access to an Magnesium radio. */ @@ -27,16 +26,7 @@ public: typedef boost::shared_ptr<neon_radio_ctrl_impl> sptr; //! Frequency bands for RX. Bands are a function of the analog filter banks - enum class rx_band { - INVALID_BAND, - LB_B2, - LB_B3, - LB_B4, - LB_B5, - LB_B6, - LB_B7, - HB - }; + enum class rx_band { INVALID_BAND, LB_B2, LB_B3, LB_B4, LB_B5, LB_B6, LB_B7, HB }; //! Frequency bands for TX. Bands are a function of the analog filter banks enum class tx_band { @@ -56,37 +46,28 @@ public: * ATR/ Switches Types *************************************************************************/ //! ATR state - enum atr_state_t { - IDLE, - RX_ONLY, - TX_ONLY, - FULL_DUPLEX - }; + enum atr_state_t { IDLE, RX_ONLY, TX_ONLY, FULL_DUPLEX }; //! Channel select: - enum chan_sel_t { - CHAN1, - CHAN2, - BOTH - }; + enum chan_sel_t { CHAN1, CHAN2, BOTH }; enum tx_sw1_t { - TX_SW1_LB_80 = 3, - TX_SW1_LB_160 = 7, - TX_SW1_LB_225 = 1, - TX_SW1_LB_400 = 5, - TX_SW1_LB_575 = 2, + TX_SW1_LB_80 = 3, + TX_SW1_LB_160 = 7, + TX_SW1_LB_225 = 1, + TX_SW1_LB_400 = 5, + TX_SW1_LB_575 = 2, TX_SW1_LB_1000 = 6, TX_SW1_LB_1700 = 0, TX_SW1_LB_2750 = 4 }; enum tx_sw2_t { - TX_SW2_LB_80 = 7, - TX_SW2_LB_160 = 3, - TX_SW2_LB_225 = 5, - TX_SW2_LB_400 = 1, - TX_SW2_LB_575 = 6, + TX_SW2_LB_80 = 7, + TX_SW2_LB_160 = 3, + TX_SW2_LB_225 = 5, + TX_SW2_LB_400 = 1, + TX_SW2_LB_575 = 6, TX_SW2_LB_1000 = 2, TX_SW2_LB_1700 = 4, TX_SW2_LB_2750 = 0 @@ -95,10 +76,10 @@ public: enum trx_sw_t { TRX1_SW_TX_HB = 2, TRX1_SW_TX_LB = 1, - TRX1_SW_RX = 4, + TRX1_SW_RX = 4, TRX2_SW_TX_HB = 2, TRX2_SW_TX_LB = 4, - TRX2_SW_RX = 1 + TRX2_SW_RX = 1 }; enum rx_sw1_t { @@ -108,7 +89,7 @@ public: RX_SW1_LB_B5 = 3, RX_SW1_LB_B6 = 0, RX_SW1_LB_B7 = 1, - RX_SW1_OFF = 7 + RX_SW1_OFF = 7 }; @@ -119,20 +100,16 @@ public: RX_SW2_LB_B5 = 2, RX_SW2_LB_B6 = 1, RX_SW2_LB_B7 = 0, - RX_SW2_OFF = 7 + RX_SW2_OFF = 7 }; enum rx_sw3_t { RX_SW3_HBRX_LBTRX = 1, RX_SW3_HBTRX_LBRX = 2, - RX_SW3_OFF = 0 //or 3 + RX_SW3_OFF = 0 // or 3 }; - enum tx_amp_t { - TX_AMP_HF_ON = 2, - TX_AMP_LF_ON = 1, - TX_AMP_OFF = 3 - }; + enum tx_amp_t { TX_AMP_HF_ON = 2, TX_AMP_LF_ON = 1, TX_AMP_OFF = 3 }; /************************************************************************ * Structors @@ -149,10 +126,11 @@ public: virtual bool check_radio_config(); //! Set which channel mode is used - void set_channel_mode(const std::string &channel_mode); + void set_channel_mode(const std::string& channel_mode); //! Set streaming mode - active chains, channel_mode, timing_mode - void set_streaming_mode(const bool tx1, const bool tx2, const bool rx1, const bool rx2); + void set_streaming_mode( + const bool tx1, const bool tx2, const bool rx1, const bool rx2); /*! Run a loopback self test. * @@ -163,19 +141,18 @@ public: * * \param iface An interface to the associated radio control core * \param iface The radio control core's address to write the loopback value - * \param iface The radio control core's readback address to read back the returned value + * \param iface The radio control core's readback address to read back the returned + * value * * \throws a uhd::runtime_error if the loopback value didn't match. */ - void loopback_self_test( - std::function<void(uint32_t)> poker_functor, - std::function<uint64_t()> peeker_functor - ); + void loopback_self_test(std::function<void(uint32_t)> poker_functor, + std::function<uint64_t()> peeker_functor); double set_rate(const double rate); - void set_tx_antenna(const std::string &ant, const size_t chan); - void set_rx_antenna(const std::string &ant, const size_t chan); + void set_tx_antenna(const std::string& ant, const size_t chan); + void set_rx_antenna(const std::string& ant, const size_t chan); double set_tx_frequency(const double freq, const size_t chan); double set_rx_frequency(const double freq, const size_t chan); @@ -186,13 +163,10 @@ public: double set_tx_gain(const double gain, const size_t chan); double set_rx_gain(const double gain, const size_t chan); - size_t get_chan_from_dboard_fe(const std::string &fe, const direction_t dir); + 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); - void set_rpc_client( - uhd::rpc_client::sptr rpcc, - const uhd::device_addr_t &block_args - ); + void set_rpc_client(uhd::rpc_client::sptr rpcc, const uhd::device_addr_t& block_args); private: /************************************************************************** @@ -205,10 +179,7 @@ private: void _init_defaults(); //! Init a subtree for the RF frontends - void _init_frontend_subtree( - uhd::property_tree::sptr subtree, - const size_t chan_idx - ); + void _init_frontend_subtree(uhd::property_tree::sptr subtree, const size_t chan_idx); //! Initialize Catalina defaults void _init_codec(); @@ -216,10 +187,7 @@ private: //! Initialize property tree void _init_prop_tree(); - void _init_mpm_sensors( - const direction_t dir, - const size_t chan_idx - ); + void _init_mpm_sensors(const direction_t dir, const size_t chan_idx); //! Map a frequency in Hz to an rx_band value. Will return // rx_band::INVALID_BAND if the frequency is out of range. @@ -233,33 +201,21 @@ private: *************************************************************************/ //! Return LO lock status. Factors in current band (low/high) and // direction (TX/RX) - bool get_lo_lock_status( - const direction_t dir - ); + bool get_lo_lock_status(const direction_t dir); /************************************************************************** * Misc Controls *************************************************************************/ //! Blink the front-panel LEDs for \p identify_duration, // and resume normal operation. - void _identify_with_leds( - const int identify_duration - ); + void _identify_with_leds(const int identify_duration); uint32_t _get_rx_switches( - const size_t chan, - const double freq, - const std::string &ant - ); + const size_t chan, const double freq, const std::string& ant); - uint32_t _get_tx_switches( - const size_t chan, - const double freq - ); + uint32_t _get_tx_switches(const size_t chan, const double freq); - void _set_atr_bits( - const size_t chan - ); + void _set_atr_bits(const size_t chan); /************************************************************************** * Private attributes @@ -283,7 +239,7 @@ private: uhd::spi_iface::sptr _spi; //! Reference to the AD9361 controls - //neon_ad9361_iface::uptr _ad9361; + // neon_ad9361_iface::uptr _ad9361; ad9361_ctrl::sptr _ad9361; //! ATR controls. These control the AD9361 gain @@ -305,4 +261,3 @@ private: }} /* namespace uhd::rfnoc */ #endif /* INCLUDED_LIBUHD_RFNOC_NEON_RADIO_CTRL_IMPL_HPP */ - diff --git a/host/lib/usrp/dboard/neon/neon_radio_ctrl_init.cpp b/host/lib/usrp/dboard/neon/neon_radio_ctrl_init.cpp index c71fd0169..783f0c7b2 100644 --- a/host/lib/usrp/dboard/neon/neon_radio_ctrl_init.cpp +++ b/host/lib/usrp/dboard/neon/neon_radio_ctrl_init.cpp @@ -4,17 +4,17 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include "neon_radio_ctrl_impl.hpp" #include "neon_constants.hpp" -#include <uhd/utils/log.hpp> +#include "neon_radio_ctrl_impl.hpp" +#include <uhd/transport/chdr.hpp> #include <uhd/types/eeprom.hpp> #include <uhd/types/sensors.hpp> -#include <uhd/transport/chdr.hpp> +#include <uhd/utils/log.hpp> #include <boost/algorithm/string.hpp> -#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/case_conv.hpp> -#include <vector> +#include <boost/algorithm/string/split.hpp> #include <string> +#include <vector> using namespace uhd; using namespace uhd::rfnoc; @@ -25,32 +25,35 @@ using namespace uhd::rfnoc; // This function convert the format of attribute "Radio_N_M" // to a single value port number = N*number_of_port_per_radio + M -uint32_t _extract_port_number(std::string radio_src_string, uhd::property_tree::sptr ptree){ +uint32_t _extract_port_number( + std::string radio_src_string, uhd::property_tree::sptr ptree) +{ std::string s_val = "0"; std::vector<std::string> radio_strings; - boost::algorithm::split( - radio_strings, + boost::algorithm::split(radio_strings, radio_src_string, boost::is_any_of("_/"), boost::token_compress_on); boost::to_lower(radio_strings[0]); - if (radio_strings.size()<3) { - throw uhd::runtime_error(str(boost::format("%s is an invalid GPIO source string.") % radio_src_string)); + if (radio_strings.size() < 3) { + throw uhd::runtime_error(str( + boost::format("%s is an invalid GPIO source string.") % radio_src_string)); } size_t radio_num = std::stoi(radio_strings[1]); - size_t port_num = std::stoi(radio_strings[2]); + size_t port_num = std::stoi(radio_strings[2]); if (radio_strings[0] != "radio") { - throw uhd::runtime_error("Front panel GPIO bank can only accept a radio block as its driver."); + throw uhd::runtime_error( + "Front panel GPIO bank can only accept a radio block as its driver."); } - std::string radio_port_out = "Radio_"+ radio_strings[1] + "/ports/out"; - std::string radio_port_path = radio_port_out + "/"+ radio_strings[2]; - auto found = ptree->exists(fs_path("xbar")/ radio_port_path); - if (not found){ - throw uhd::runtime_error(str(boost::format( - "Could not find radio port %s.\n") % radio_port_path)); + std::string radio_port_out = "Radio_" + radio_strings[1] + "/ports/out"; + std::string radio_port_path = radio_port_out + "/" + radio_strings[2]; + auto found = ptree->exists(fs_path("xbar") / radio_port_path); + if (not found) { + throw uhd::runtime_error( + str(boost::format("Could not find radio port %s.\n") % radio_port_path)); } - size_t port_size = ptree->list(fs_path("xbar")/ radio_port_out).size(); - return radio_num*port_size + port_num; + size_t port_size = ptree->list(fs_path("xbar") / radio_port_out).size(); + return radio_num * port_size + port_num; } void neon_radio_ctrl_impl::_init_defaults() @@ -60,8 +63,7 @@ void neon_radio_ctrl_impl::_init_defaults() const size_t num_tx_chans = get_input_ports().size(); UHD_LOG_TRACE(unique_id(), - "Num TX chans: " << num_tx_chans - << " Num RX chans: " << num_rx_chans); + "Num TX chans: " << num_tx_chans << " Num RX chans: " << num_rx_chans); for (size_t chan = 0; chan < num_rx_chans; chan++) { radio_ctrl_impl::set_rx_frequency(NEON_DEFAULT_FREQ, chan); @@ -83,8 +85,7 @@ void neon_radio_ctrl_impl::_init_defaults() const size_t default_spp = (_tree->access<size_t>("mtu/recv").get() - max_bytes_header) / (2 * sizeof(int16_t)); - UHD_LOG_DEBUG(unique_id(), - "Setting default spp to " << default_spp); + UHD_LOG_DEBUG(unique_id(), "Setting default spp to " << default_spp); _tree->access<int>(get_arg_path("spp") / "value").set(default_spp); } @@ -92,255 +93,181 @@ void neon_radio_ctrl_impl::_init_peripherals() { UHD_LOG_TRACE(unique_id(), "Initializing peripherals..."); - _db_gpio.clear(); // Following the as-if rule, this can get optimized out + _db_gpio.clear(); // Following the as-if rule, this can get optimized out for (size_t radio_idx = 0; radio_idx < _get_num_radios(); radio_idx++) { - UHD_LOG_TRACE(unique_id(), - "Initializing GPIOs for channel " << radio_idx); - _db_gpio.emplace_back( - usrp::gpio_atr::gpio_atr_3000::make_write_only( - _get_ctrl(radio_idx), - regs::sr_addr(regs::GPIO) - ) - ); - _db_gpio[radio_idx]->set_atr_mode(usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL); + UHD_LOG_TRACE(unique_id(), "Initializing GPIOs for channel " << radio_idx); + _db_gpio.emplace_back(usrp::gpio_atr::gpio_atr_3000::make_write_only( + _get_ctrl(radio_idx), regs::sr_addr(regs::GPIO))); + _db_gpio[radio_idx]->set_atr_mode( + usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL); } - _leds_gpio.clear(); // Following the as-if rule, this can get optimized out + _leds_gpio.clear(); // Following the as-if rule, this can get optimized out for (size_t radio_idx = 0; radio_idx < _get_num_radios(); radio_idx++) { - UHD_LOG_TRACE(unique_id(), - "Initializing GPIOs for channel " << radio_idx); - _leds_gpio.emplace_back( - usrp::gpio_atr::gpio_atr_3000::make_write_only( - _get_ctrl(radio_idx), - regs::sr_addr(regs::LEDS) - ) - ); + UHD_LOG_TRACE(unique_id(), "Initializing GPIOs for channel " << radio_idx); + _leds_gpio.emplace_back(usrp::gpio_atr::gpio_atr_3000::make_write_only( + _get_ctrl(radio_idx), regs::sr_addr(regs::LEDS))); - _leds_gpio[radio_idx]->set_atr_mode(usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL); + _leds_gpio[radio_idx]->set_atr_mode( + usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL); } UHD_LOG_TRACE(unique_id(), "Initializing front-panel GPIO control...") _fp_gpio = usrp::gpio_atr::gpio_atr_3000::make( - _get_ctrl(0), - regs::sr_addr(regs::FP_GPIO), - regs::rb_addr(regs::RB_FP_GPIO) - ); + _get_ctrl(0), regs::sr_addr(regs::FP_GPIO), regs::rb_addr(regs::RB_FP_GPIO)); } void neon_radio_ctrl_impl::_init_frontend_subtree( - uhd::property_tree::sptr subtree, - const size_t chan_idx -) { + uhd::property_tree::sptr subtree, const size_t chan_idx) +{ const fs_path tx_fe_path = fs_path("tx_frontends") / chan_idx; const fs_path rx_fe_path = fs_path("rx_frontends") / chan_idx; UHD_LOG_TRACE(unique_id(), - "Adding non-RFNoC block properties for channel " << chan_idx << - " to prop tree path " << tx_fe_path << " and " << rx_fe_path); + "Adding non-RFNoC block properties for channel " + << chan_idx << " to prop tree path " << tx_fe_path << " and " << rx_fe_path); // TX Standard attributes - subtree->create<std::string>(tx_fe_path / "name") - .set(str(boost::format("Neon"))) - ; - subtree->create<std::string>(tx_fe_path / "connection") - .set("IQ") - ; + subtree->create<std::string>(tx_fe_path / "name").set(str(boost::format("Neon"))); + subtree->create<std::string>(tx_fe_path / "connection").set("IQ"); // RX Standard attributes - subtree->create<std::string>(rx_fe_path / "name") - .set(str(boost::format("Neon"))) - ; - subtree->create<std::string>(rx_fe_path / "connection") - .set("IQ") - ; + subtree->create<std::string>(rx_fe_path / "name").set(str(boost::format("Neon"))); + subtree->create<std::string>(rx_fe_path / "connection").set("IQ"); // TX Antenna subtree->create<std::string>(tx_fe_path / "antenna" / "value") - .add_coerced_subscriber([this, chan_idx](const std::string &ant){ + .add_coerced_subscriber([this, chan_idx](const std::string& ant) { this->set_tx_antenna(ant, chan_idx); }) - .set_publisher([this, chan_idx](){ - return this->get_tx_antenna(chan_idx); - }) - ; + .set_publisher([this, chan_idx]() { return this->get_tx_antenna(chan_idx); }); subtree->create<std::vector<std::string>>(tx_fe_path / "antenna" / "options") .set({NEON_DEFAULT_TX_ANTENNA}) - .add_coerced_subscriber([](const std::vector<std::string> &){ - throw uhd::runtime_error( - "Attempting to update antenna options!"); - }) - ; + .add_coerced_subscriber([](const std::vector<std::string>&) { + throw uhd::runtime_error("Attempting to update antenna options!"); + }); // RX Antenna subtree->create<std::string>(rx_fe_path / "antenna" / "value") - .add_coerced_subscriber([this, chan_idx](const std::string &ant){ + .add_coerced_subscriber([this, chan_idx](const std::string& ant) { this->set_rx_antenna(ant, chan_idx); }) - .set_publisher([this, chan_idx](){ - return this->get_rx_antenna(chan_idx); - }) - ; + .set_publisher([this, chan_idx]() { return this->get_rx_antenna(chan_idx); }); subtree->create<std::vector<std::string>>(rx_fe_path / "antenna" / "options") .set(NEON_RX_ANTENNAS) - .add_coerced_subscriber([](const std::vector<std::string> &){ - throw uhd::runtime_error( - "Attempting to update antenna options!"); - }) - ; + .add_coerced_subscriber([](const std::vector<std::string>&) { + throw uhd::runtime_error("Attempting to update antenna options!"); + }); // TX frequency subtree->create<double>(tx_fe_path / "freq" / "value") - .set_coercer([this, chan_idx](const double freq){ + .set_coercer([this, chan_idx](const double freq) { return this->set_tx_frequency(freq, chan_idx); }) - .set_publisher([this, chan_idx](){ - return this->get_tx_frequency(chan_idx); - }) - ; + .set_publisher([this, chan_idx]() { return this->get_tx_frequency(chan_idx); }); subtree->create<meta_range_t>(tx_fe_path / "freq" / "range") .set(meta_range_t(AD9361_TX_MIN_FREQ, AD9361_TX_MAX_FREQ, 1.0)) - .add_coerced_subscriber([](const meta_range_t &){ - throw uhd::runtime_error( - "Attempting to update freq range!"); - }) - ; + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update freq range!"); + }); // RX frequency subtree->create<double>(rx_fe_path / "freq" / "value") - .set_coercer([this, chan_idx](const double freq){ + .set_coercer([this, chan_idx](const double freq) { return this->set_rx_frequency(freq, chan_idx); }) - .set_publisher([this, chan_idx](){ - return this->get_rx_frequency(chan_idx); - }) - ; + .set_publisher([this, chan_idx]() { return this->get_rx_frequency(chan_idx); }); subtree->create<meta_range_t>(rx_fe_path / "freq" / "range") .set(meta_range_t(AD9361_RX_MIN_FREQ, AD9361_RX_MAX_FREQ, 1.0)) - .add_coerced_subscriber([](const meta_range_t &){ - throw uhd::runtime_error( - "Attempting to update freq range!"); - }) - ; + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update freq range!"); + }); // TX bandwidth subtree->create<double>(tx_fe_path / "bandwidth" / "value") .set(AD9361_TX_MAX_BANDWIDTH) - .set_coercer([this, chan_idx](const double bw){ + .set_coercer([this, chan_idx](const double bw) { return this->set_tx_bandwidth(bw, chan_idx); }) - .set_publisher([this, chan_idx](){ - return this->get_tx_bandwidth(chan_idx); - }) - ; + .set_publisher([this, chan_idx]() { return this->get_tx_bandwidth(chan_idx); }); subtree->create<meta_range_t>(tx_fe_path / "bandwidth" / "range") .set(meta_range_t(AD9361_TX_MIN_BANDWIDTH, AD9361_TX_MAX_BANDWIDTH)) - .add_coerced_subscriber([](const meta_range_t &){ - throw uhd::runtime_error( - "Attempting to update bandwidth range!"); - }) - ; + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update bandwidth range!"); + }); // RX bandwidth subtree->create<double>(rx_fe_path / "bandwidth" / "value") .set(AD9361_RX_MAX_BANDWIDTH) - .set_coercer([this, chan_idx](const double bw){ + .set_coercer([this, chan_idx](const double bw) { return this->set_rx_bandwidth(bw, chan_idx); - }) - ; + }); subtree->create<meta_range_t>(rx_fe_path / "bandwidth" / "range") .set(meta_range_t(AD9361_RX_MIN_BANDWIDTH, AD9361_RX_MAX_BANDWIDTH)) - .add_coerced_subscriber([](const meta_range_t &){ - throw uhd::runtime_error( - "Attempting to update bandwidth range!"); - }) - ; + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update bandwidth range!"); + }); // TX gains const std::vector<std::string> tx_gain_names = ad9361_ctrl::get_gain_names("TX1"); for (auto tx_gain_name : tx_gain_names) { subtree->create<double>(tx_fe_path / "gains" / tx_gain_name / "value") - .set_coercer([this, chan_idx](const double gain){ + .set_coercer([this, chan_idx](const double gain) { return this->set_tx_gain(gain, chan_idx); }) - .set_publisher([this, chan_idx](){ - return radio_ctrl_impl::get_tx_gain(chan_idx); - }) - ; + .set_publisher( + [this, chan_idx]() { return radio_ctrl_impl::get_tx_gain(chan_idx); }); subtree->create<meta_range_t>(tx_fe_path / "gains" / tx_gain_name / "range") - .add_coerced_subscriber([](const meta_range_t &){ - throw uhd::runtime_error( - "Attempting to update gain range!"); + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update gain range!"); }) - .set_publisher([this](){ - return meta_range_t( - AD9361_MIN_TX_GAIN, - AD9361_MAX_TX_GAIN, - AD9361_TX_GAIN_STEP - ); - }) - ; + .set_publisher([this]() { + return meta_range_t( + AD9361_MIN_TX_GAIN, AD9361_MAX_TX_GAIN, AD9361_TX_GAIN_STEP); + }); } // RX gains const std::vector<std::string> rx_gain_names = ad9361_ctrl::get_gain_names("RX1"); for (auto rx_gain_name : rx_gain_names) { subtree->create<double>(rx_fe_path / "gains" / rx_gain_name / "value") - .set_coercer([this, chan_idx](const double gain){ + .set_coercer([this, chan_idx](const double gain) { return this->set_rx_gain(gain, chan_idx); }) - .set_publisher([this, chan_idx](){ - return radio_ctrl_impl::get_rx_gain(chan_idx); - }) - ; + .set_publisher( + [this, chan_idx]() { return radio_ctrl_impl::get_rx_gain(chan_idx); }); subtree->create<meta_range_t>(rx_fe_path / "gains" / rx_gain_name / "range") - .add_coerced_subscriber([](const meta_range_t &){ - throw uhd::runtime_error( - "Attempting to update gain range!"); + .add_coerced_subscriber([](const meta_range_t&) { + throw uhd::runtime_error("Attempting to update gain range!"); }) - .set_publisher([this](){ + .set_publisher([this]() { return meta_range_t( - AD9361_MIN_RX_GAIN, - AD9361_MAX_RX_GAIN, - AD9361_RX_GAIN_STEP - ); - }) - ; + AD9361_MIN_RX_GAIN, AD9361_MAX_RX_GAIN, AD9361_RX_GAIN_STEP); + }); } // TX LO lock sensor ////////////////////////////////////////////////////// // Note: The AD9361 LO lock sensors are generated programmatically in // set_rpc_client(). The actual lo_locked publisher is also set there. subtree->create<sensor_value_t>(tx_fe_path / "sensors" / "lo_locked") - .set(sensor_value_t("all_los", false, "locked", "unlocked")) - .add_coerced_subscriber([](const sensor_value_t &){ - throw uhd::runtime_error( - "Attempting to write to sensor!"); + .set(sensor_value_t("all_los", false, "locked", "unlocked")) + .add_coerced_subscriber([](const sensor_value_t&) { + throw uhd::runtime_error("Attempting to write to sensor!"); }) - .set_publisher([this](){ + .set_publisher([this]() { return sensor_value_t( - "all_los", - this->get_lo_lock_status(TX_DIRECTION), - "locked", "unlocked" - ); - }) - ; + "all_los", this->get_lo_lock_status(TX_DIRECTION), "locked", "unlocked"); + }); // RX LO lock sensor (see not on TX LO lock sensor) subtree->create<sensor_value_t>(rx_fe_path / "sensors" / "lo_locked") - .set(sensor_value_t("all_los", false, "locked", "unlocked")) - .add_coerced_subscriber([](const sensor_value_t &){ - throw uhd::runtime_error( - "Attempting to write to sensor!"); + .set(sensor_value_t("all_los", false, "locked", "unlocked")) + .add_coerced_subscriber([](const sensor_value_t&) { + throw uhd::runtime_error("Attempting to write to sensor!"); }) - .set_publisher([this](){ + .set_publisher([this]() { return sensor_value_t( - "all_los", - this->get_lo_lock_status(RX_DIRECTION), - "locked", "unlocked" - ); - }) - ; + "all_los", this->get_lo_lock_status(RX_DIRECTION), "locked", "unlocked"); + }); } void neon_radio_ctrl_impl::_init_prop_tree() { const fs_path fe_base = fs_path("dboards") / _radio_slot; for (size_t chan_idx = 0; chan_idx < NEON_NUM_CHANS; chan_idx++) { - this->_init_frontend_subtree( - _tree->subtree(fe_base), chan_idx); + this->_init_frontend_subtree(_tree->subtree(fe_base), chan_idx); } - _tree->create<eeprom_map_t>(_root_path / "eeprom") - .set(eeprom_map_t()); + _tree->create<eeprom_map_t>(_root_path / "eeprom").set(eeprom_map_t()); _tree->create<int>("rx_codecs" / _radio_slot / "gains"); _tree->create<int>("tx_codecs" / _radio_slot / "gains"); @@ -349,98 +276,108 @@ void neon_radio_ctrl_impl::_init_prop_tree() if (not _tree->exists("tick_rate")) { _tree->create<double>("tick_rate") - .set_coercer([this](double tick_rate){ - return this->set_rate(tick_rate); - }) - .set_publisher([this](){ - return this->get_rate(); - }) - ; + .set_coercer([this](double tick_rate) { return this->set_rate(tick_rate); }) + .set_publisher([this]() { return this->get_rate(); }); } else { UHD_LOG_WARNING(unique_id(), "Cannot set tick_rate again"); } // *****FP_GPIO************************ - for(const auto& attr: usrp::gpio_atr::gpio_attr_map) { - if (not _tree->exists(fs_path("gpio") / "FP0" / attr.second)){ - switch (attr.first){ + for (const auto& attr : usrp::gpio_atr::gpio_attr_map) { + if (not _tree->exists(fs_path("gpio") / "FP0" / attr.second)) { + switch (attr.first) { case usrp::gpio_atr::GPIO_SRC: - //FIXME: move this creation of this branch of ptree out side of radio impl; - // since there's no data dependency between radio and SRC setting for FP0 - _tree->create<std::vector<std::string>>(fs_path("gpio") / "FP0" / attr.second) - .set(std::vector<std::string>( - 32, - usrp::gpio_atr::default_attr_value_map.at(attr.first))) - .add_coerced_subscriber([this, attr]( - const std::vector<std::string> str_val){ - uint32_t radio_src_value = 0; - uint32_t master_value = 0; - for(size_t i = 0 ; i<str_val.size(); i++){ - if(str_val[i] == "PS"){ - master_value += 1<<i;; - }else{ - auto port_num = _extract_port_number(str_val[i],_tree); - radio_src_value =(1<<(2*i))*port_num + radio_src_value; + // FIXME: move this creation of this branch of ptree out side of + // radio impl; + // since there's no data dependency between radio and SRC setting for + // FP0 + _tree + ->create<std::vector<std::string>>( + fs_path("gpio") / "FP0" / attr.second) + .set(std::vector<std::string>( + 32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) + .add_coerced_subscriber( + [this, attr](const std::vector<std::string> str_val) { + uint32_t radio_src_value = 0; + uint32_t master_value = 0; + for (size_t i = 0; i < str_val.size(); i++) { + if (str_val[i] == "PS") { + master_value += 1 << i; + ; + } else { + auto port_num = + _extract_port_number(str_val[i], _tree); + radio_src_value = + (1 << (2 * i)) * port_num + radio_src_value; + } } - } - _rpcc->notify_with_token("set_fp_gpio_master", master_value); - _rpcc->notify_with_token("set_fp_gpio_radio_src", radio_src_value); - }); - break; + _rpcc->notify_with_token( + "set_fp_gpio_master", master_value); + _rpcc->notify_with_token( + "set_fp_gpio_radio_src", radio_src_value); + }); + break; case usrp::gpio_atr::GPIO_CTRL: case usrp::gpio_atr::GPIO_DDR: - _tree->create<std::vector<std::string>>(fs_path("gpio") / "FP0" / attr.second) - .set(std::vector<std::string>( - 32, - usrp::gpio_atr::default_attr_value_map.at(attr.first))) - .add_coerced_subscriber([this, attr]( - const std::vector<std::string> str_val){ - uint32_t val = 0; - for(size_t i = 0 ; i < str_val.size() ; i++){ - val += usrp::gpio_atr::gpio_attr_value_pair.at(attr.second).at(str_val[i])<<i; - } - _fp_gpio->set_gpio_attr(attr.first, val); - }); + _tree + ->create<std::vector<std::string>>( + fs_path("gpio") / "FP0" / attr.second) + .set(std::vector<std::string>( + 32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) + .add_coerced_subscriber( + [this, attr](const std::vector<std::string> str_val) { + uint32_t val = 0; + for (size_t i = 0; i < str_val.size(); i++) { + val += usrp::gpio_atr::gpio_attr_value_pair + .at(attr.second) + .at(str_val[i]) + << i; + } + _fp_gpio->set_gpio_attr(attr.first, val); + }); break; - case usrp::gpio_atr::GPIO_READBACK:{ + case usrp::gpio_atr::GPIO_READBACK: { _tree->create<uint32_t>(fs_path("gpio") / "FP0" / attr.second) - .set_publisher([this](){ - return _fp_gpio->read_gpio(); - } - ); - } - break; + .set_publisher([this]() { return _fp_gpio->read_gpio(); }); + } break; default: _tree->create<uint32_t>(fs_path("gpio") / "FP0" / attr.second) - .set(0) - .add_coerced_subscriber([this, attr](const uint32_t val){ - _fp_gpio->set_gpio_attr(attr.first, val); - }); + .set(0) + .add_coerced_subscriber([this, attr](const uint32_t val) { + _fp_gpio->set_gpio_attr(attr.first, val); + }); } - }else{ - switch (attr.first){ + } else { + switch (attr.first) { case usrp::gpio_atr::GPIO_SRC: - break; + break; case usrp::gpio_atr::GPIO_CTRL: case usrp::gpio_atr::GPIO_DDR: - _tree->access<std::vector<std::string>>(fs_path("gpio") / "FP0" / attr.second) - .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) - .add_coerced_subscriber([this, attr](const std::vector<std::string> str_val){ - uint32_t val = 0; - for(size_t i = 0 ; i < str_val.size() ; i++){ - val += usrp::gpio_atr::gpio_attr_value_pair.at(attr.second).at(str_val[i])<<i; - } - _fp_gpio->set_gpio_attr(attr.first, val); - }); + _tree + ->access<std::vector<std::string>>( + fs_path("gpio") / "FP0" / attr.second) + .set(std::vector<std::string>( + 32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) + .add_coerced_subscriber( + [this, attr](const std::vector<std::string> str_val) { + uint32_t val = 0; + for (size_t i = 0; i < str_val.size(); i++) { + val += usrp::gpio_atr::gpio_attr_value_pair + .at(attr.second) + .at(str_val[i]) + << i; + } + _fp_gpio->set_gpio_attr(attr.first, val); + }); break; case usrp::gpio_atr::GPIO_READBACK: break; default: _tree->access<uint32_t>(fs_path("gpio") / "FP0" / attr.second) - .set(0) - .add_coerced_subscriber([this, attr](const uint32_t val){ - _fp_gpio->set_gpio_attr(attr.first, val); - }); + .set(0) + .add_coerced_subscriber([this, attr](const uint32_t val) { + _fp_gpio->set_gpio_attr(attr.first, val); + }); } } } @@ -464,35 +401,27 @@ void neon_radio_ctrl_impl::_init_codec() } } -void neon_radio_ctrl_impl::_init_mpm_sensors( - const direction_t dir, - const size_t chan_idx -) { +void neon_radio_ctrl_impl::_init_mpm_sensors(const direction_t dir, const size_t chan_idx) +{ const std::string trx = (dir == RX_DIRECTION) ? "RX" : "TX"; - const fs_path fe_path = - fs_path("dboards") / _radio_slot / - (dir == RX_DIRECTION ? "rx_frontends" : "tx_frontends") / chan_idx; - auto sensor_list = - _rpcc->request_with_token<std::vector<std::string>>( - this->_rpc_prefix + "get_sensors", trx); + const fs_path fe_path = fs_path("dboards") / _radio_slot + / (dir == RX_DIRECTION ? "rx_frontends" : "tx_frontends") + / chan_idx; + auto sensor_list = _rpcc->request_with_token<std::vector<std::string>>( + this->_rpc_prefix + "get_sensors", trx); UHD_LOG_TRACE(unique_id(), - "Chan " << chan_idx << ": Found " - << sensor_list.size() << " " << trx << " sensors."); - for (const auto &sensor_name : sensor_list) { - UHD_LOG_TRACE(unique_id(), - "Adding " << trx << " sensor " << sensor_name); + "Chan " << chan_idx << ": Found " << sensor_list.size() << " " << trx + << " sensors."); + for (const auto& sensor_name : sensor_list) { + UHD_LOG_TRACE(unique_id(), "Adding " << trx << " sensor " << sensor_name); _tree->create<sensor_value_t>(fe_path / "sensors" / sensor_name) - .add_coerced_subscriber([](const sensor_value_t &){ - throw uhd::runtime_error( - "Attempting to write to sensor!"); + .add_coerced_subscriber([](const sensor_value_t&) { + throw uhd::runtime_error("Attempting to write to sensor!"); }) - .set_publisher([this, trx, sensor_name, chan_idx](){ + .set_publisher([this, trx, sensor_name, chan_idx]() { return sensor_value_t( this->_rpcc->request_with_token<sensor_value_t::sensor_map_t>( - this->_rpc_prefix + "get_sensor", - trx, sensor_name, chan_idx) - ); - }) - ; + this->_rpc_prefix + "get_sensor", trx, sensor_name, chan_idx)); + }); } } diff --git a/host/lib/usrp/dboard/neon/neon_regs.hpp b/host/lib/usrp/dboard/neon/neon_regs.hpp index 39ceca01c..d1ff940c6 100644 --- a/host/lib/usrp/dboard/neon/neon_regs.hpp +++ b/host/lib/usrp/dboard/neon/neon_regs.hpp @@ -10,17 +10,16 @@ #include <uhd/config.hpp> #include <cstdint> -static const uint32_t TX_AMP_SHIFT = 17; -static const uint32_t TRX_SW_SHIFT = 14; -static const uint32_t RX_SW1_SHIFT = 0; -static const uint32_t RX_SW2_SHIFT = 3; -static const uint32_t RX_SW3_SHIFT = 6; -static const uint32_t TX_SW1_SHIFT = 8; -static const uint32_t TX_SW2_SHIFT = 11; +static const uint32_t TX_AMP_SHIFT = 17; +static const uint32_t TRX_SW_SHIFT = 14; +static const uint32_t RX_SW1_SHIFT = 0; +static const uint32_t RX_SW2_SHIFT = 3; +static const uint32_t RX_SW3_SHIFT = 6; +static const uint32_t TX_SW1_SHIFT = 8; +static const uint32_t TX_SW2_SHIFT = 11; -static const uint32_t TRX_LED_GRN_SHIFT = 0; +static const uint32_t TRX_LED_GRN_SHIFT = 0; static const uint32_t TX_LED_RED_SHIFT = 1; static const uint32_t RX_LED_GRN_SHIFT = 2; #endif /* INCLUDED_NEON_REGS_HPP */ - diff --git a/host/lib/usrp/device3/device3_flow_ctrl.hpp b/host/lib/usrp/device3/device3_flow_ctrl.hpp index 50081543a..535d7fbac 100644 --- a/host/lib/usrp/device3/device3_flow_ctrl.hpp +++ b/host/lib/usrp/device3/device3_flow_ctrl.hpp @@ -8,10 +8,10 @@ #define INCLUDED_DEVICE3_FLOW_CTRL_HPP #include "device3_impl.hpp" -#include <uhd/utils/log.hpp> -#include <uhd/types/sid.hpp> -#include <uhd/transport/zero_copy.hpp> #include <uhd/transport/vrt_if_packet.hpp> +#include <uhd/transport/zero_copy.hpp> +#include <uhd/types/sid.hpp> +#include <uhd/utils/log.hpp> #include <boost/shared_ptr.hpp> namespace uhd { namespace usrp { @@ -19,12 +19,14 @@ namespace uhd { namespace usrp { //! Stores the state of RX flow control struct rx_fc_cache_t { - rx_fc_cache_t(): - interval(0), - last_byte_count(0), - total_bytes_consumed(0), - total_packets_consumed(0), - seq_num(0) {} + rx_fc_cache_t() + : interval(0) + , last_byte_count(0) + , total_bytes_consumed(0) + , total_packets_consumed(0) + , seq_num(0) + { + } //! Flow control interval in bytes size_t interval; @@ -40,117 +42,112 @@ struct rx_fc_cache_t uhd::transport::zero_copy_if::sptr xport; std::function<uint32_t(uint32_t)> to_host; std::function<uint32_t(uint32_t)> from_host; - std::function<void(const uint32_t *packet_buff, uhd::transport::vrt::if_packet_info_t &)> unpack; - std::function<void(uint32_t *packet_buff, uhd::transport::vrt::if_packet_info_t &)> pack; + std::function<void( + const uint32_t* packet_buff, uhd::transport::vrt::if_packet_info_t&)> + unpack; + std::function<void(uint32_t* packet_buff, uhd::transport::vrt::if_packet_info_t&)> + pack; }; /*! Send out RX flow control packets. -* -* This function handles updating the counters for the consumed -* bytes and packets, determines if a flow control message is -* is necessary, and sends one if it is. Passing a nullptr for -* the buff parameter will skip the counter update. -* -* \param fc_cache RX flow control state information -* \param buff Receive buffer. Setting to nullptr will -* skip the counter update. -*/ + * + * This function handles updating the counters for the consumed + * bytes and packets, determines if a flow control message is + * is necessary, and sends one if it is. Passing a nullptr for + * the buff parameter will skip the counter update. + * + * \param fc_cache RX flow control state information + * \param buff Receive buffer. Setting to nullptr will + * skip the counter update. + */ inline bool rx_flow_ctrl( - boost::shared_ptr<rx_fc_cache_t> fc_cache, - uhd::transport::managed_buffer::sptr buff -) { + boost::shared_ptr<rx_fc_cache_t> fc_cache, uhd::transport::managed_buffer::sptr buff) +{ // If the caller supplied a buffer - if (buff) - { + if (buff) { // Unpack the header uhd::transport::vrt::if_packet_info_t packet_info; - packet_info.num_packet_words32 = buff->size()/sizeof(uint32_t); - const uint32_t *pkt = buff->cast<const uint32_t *>(); + packet_info.num_packet_words32 = buff->size() / sizeof(uint32_t); + const uint32_t* pkt = buff->cast<const uint32_t*>(); try { fc_cache->unpack(pkt, packet_info); - } - catch(const std::exception &ex) - { + } catch (const std::exception& ex) { // Log and ignore - UHD_LOGGER_ERROR("RX FLOW CTRL") << "Error unpacking packet: " << ex.what() << std::endl; + UHD_LOGGER_ERROR("RX FLOW CTRL") + << "Error unpacking packet: " << ex.what() << std::endl; return true; } // Update counters assuming the buffer is a consumed packet - if (not packet_info.error) - { + if (not packet_info.error) { fc_cache->total_bytes_consumed += buff->size(); fc_cache->total_packets_consumed++; } } // Just return if there is no need to send a flow control packet - if (fc_cache->total_bytes_consumed - fc_cache->last_byte_count < fc_cache->interval) - { + if (fc_cache->total_bytes_consumed - fc_cache->last_byte_count < fc_cache->interval) { return true; } // Time to send a flow control packet // Get a send buffer - uhd::transport::managed_send_buffer::sptr fc_buff = fc_cache->xport->get_send_buff(0.0); + uhd::transport::managed_send_buffer::sptr fc_buff = + fc_cache->xport->get_send_buff(0.0); if (not fc_buff) { throw uhd::runtime_error("rx_flowctrl timed out getting a send buffer"); } - uint32_t *pkt = fc_buff->cast<uint32_t *>(); + uint32_t* pkt = fc_buff->cast<uint32_t*>(); - //load packet info + // load packet info uhd::transport::vrt::if_packet_info_t packet_info; packet_info.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_FC; packet_info.num_payload_words32 = uhd::usrp::DEVICE3_FC_PACKET_LEN_IN_WORDS32; - packet_info.num_payload_bytes = packet_info.num_payload_words32*sizeof(uint32_t); - packet_info.packet_count = fc_cache->seq_num++; - packet_info.sob = false; - packet_info.eob = false; - packet_info.error = false; - packet_info.fc_ack = false; - packet_info.sid = fc_cache->sid.get(); - packet_info.has_sid = true; - packet_info.has_cid = false; - packet_info.has_tsi = false; - packet_info.has_tsf = false; - packet_info.has_tlr = false; + packet_info.num_payload_bytes = packet_info.num_payload_words32 * sizeof(uint32_t); + packet_info.packet_count = fc_cache->seq_num++; + packet_info.sob = false; + packet_info.eob = false; + packet_info.error = false; + packet_info.fc_ack = false; + packet_info.sid = fc_cache->sid.get(); + packet_info.has_sid = true; + packet_info.has_cid = false; + packet_info.has_tsi = false; + packet_info.has_tsf = false; + packet_info.has_tlr = false; // Load Header: fc_cache->pack(pkt, packet_info); // Load Payload: Packet count, and byte count - pkt[packet_info.num_header_words32+uhd::usrp::DEVICE3_FC_PACKET_COUNT_OFFSET] = + pkt[packet_info.num_header_words32 + uhd::usrp::DEVICE3_FC_PACKET_COUNT_OFFSET] = fc_cache->from_host(fc_cache->total_packets_consumed); - pkt[packet_info.num_header_words32+uhd::usrp::DEVICE3_FC_BYTE_COUNT_OFFSET] = + pkt[packet_info.num_header_words32 + uhd::usrp::DEVICE3_FC_BYTE_COUNT_OFFSET] = fc_cache->from_host(fc_cache->total_bytes_consumed); - //send the buffer over the interface - fc_buff->commit(sizeof(uint32_t)*(packet_info.num_packet_words32)); + // send the buffer over the interface + fc_buff->commit(sizeof(uint32_t) * (packet_info.num_packet_words32)); - //update byte count + // update byte count fc_cache->last_byte_count = fc_cache->total_bytes_consumed; return true; } /*! Handle RX flow control ACK packets. -* -*/ + * + */ inline void handle_rx_flowctrl_ack( - boost::shared_ptr<rx_fc_cache_t> fc_cache, - const uint32_t *payload -) { - const uint32_t pkt_count = fc_cache->to_host(payload[0]); + boost::shared_ptr<rx_fc_cache_t> fc_cache, const uint32_t* payload) +{ + const uint32_t pkt_count = fc_cache->to_host(payload[0]); const uint32_t byte_count = fc_cache->to_host(payload[1]); - if (fc_cache->total_bytes_consumed != byte_count) - { + if (fc_cache->total_bytes_consumed != byte_count) { UHD_LOGGER_DEBUG("device3") << "oh noes: byte_count==" << byte_count - << " total_bytes_consumed==" << fc_cache->total_bytes_consumed - << std::hex << " sid==" << fc_cache->sid << std::dec - << std::endl - ; + << " total_bytes_consumed==" << fc_cache->total_bytes_consumed << std::hex + << " sid==" << fc_cache->sid << std::dec << std::endl; } - fc_cache->total_bytes_consumed = byte_count; + fc_cache->total_bytes_consumed = byte_count; fc_cache->total_packets_consumed = pkt_count; // guess we need a pkt offset too? // This will send a flow control packet if there is a significant discrepancy @@ -160,14 +157,16 @@ inline void handle_rx_flowctrl_ack( //! Stores the state of TX flow control struct tx_fc_cache_t { - tx_fc_cache_t(uint32_t capacity): - last_byte_ack(0), - last_seq_ack(0), - byte_count(0), - pkt_count(0), - window_size(capacity), - fc_ack_seqnum(0), - fc_received(false) {} + tx_fc_cache_t(uint32_t capacity) + : last_byte_ack(0) + , last_seq_ack(0) + , byte_count(0) + , pkt_count(0) + , window_size(capacity) + , fc_ack_seqnum(0) + , fc_received(false) + { + } uint32_t last_byte_ack; uint32_t last_seq_ack; @@ -178,26 +177,28 @@ struct tx_fc_cache_t bool fc_received; std::function<uint32_t(uint32_t)> to_host; std::function<uint32_t(uint32_t)> from_host; - std::function<void(const uint32_t *packet_buff, uhd::transport::vrt::if_packet_info_t &)> unpack; - std::function<void(uint32_t *packet_buff, uhd::transport::vrt::if_packet_info_t &)> pack; + std::function<void( + const uint32_t* packet_buff, uhd::transport::vrt::if_packet_info_t&)> + unpack; + std::function<void(uint32_t* packet_buff, uhd::transport::vrt::if_packet_info_t&)> + pack; }; -inline bool tx_flow_ctrl( - boost::shared_ptr<tx_fc_cache_t> fc_cache, +inline bool tx_flow_ctrl(boost::shared_ptr<tx_fc_cache_t> fc_cache, uhd::transport::zero_copy_if::sptr xport, - uhd::transport::managed_buffer::sptr buff -) { - while (true) - { + uhd::transport::managed_buffer::sptr buff) +{ + while (true) { // If there is space - if (fc_cache->window_size - (fc_cache->byte_count - fc_cache->last_byte_ack) >= buff->size()) - { + if (fc_cache->window_size - (fc_cache->byte_count - fc_cache->last_byte_ack) + >= buff->size()) { // All is good - packet will be sent fc_cache->byte_count += buff->size(); // Round up to nearest word - if (fc_cache->byte_count % uhd::usrp::DEVICE3_LINE_SIZE) - { - fc_cache->byte_count += uhd::usrp::DEVICE3_LINE_SIZE - (fc_cache->byte_count % uhd::usrp::DEVICE3_LINE_SIZE); + if (fc_cache->byte_count % uhd::usrp::DEVICE3_LINE_SIZE) { + fc_cache->byte_count += + uhd::usrp::DEVICE3_LINE_SIZE + - (fc_cache->byte_count % uhd::usrp::DEVICE3_LINE_SIZE); } fc_cache->pkt_count++; return true; @@ -205,33 +206,33 @@ inline bool tx_flow_ctrl( // Look for a flow control message to update the space available in the buffer. uhd::transport::managed_recv_buffer::sptr buff = xport->get_recv_buff(0.1); - if (buff) - { + if (buff) { uhd::transport::vrt::if_packet_info_t if_packet_info; - if_packet_info.num_packet_words32 = buff->size()/sizeof(uint32_t); - const uint32_t *packet_buff = buff->cast<const uint32_t *>(); + if_packet_info.num_packet_words32 = buff->size() / sizeof(uint32_t); + const uint32_t* packet_buff = buff->cast<const uint32_t*>(); try { fc_cache->unpack(packet_buff, if_packet_info); - } - catch(const std::exception &ex) - { - UHD_LOGGER_ERROR("TX FLOW CTRL") << "Error unpacking flow control packet: " << ex.what() << std::endl; + } catch (const std::exception& ex) { + UHD_LOGGER_ERROR("TX FLOW CTRL") + << "Error unpacking flow control packet: " << ex.what() << std::endl; continue; } - if (if_packet_info.packet_type != uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_FC) - { - UHD_LOGGER_ERROR("TX FLOW CTRL") << "Unexpected packet received by flow control handler: " << if_packet_info.packet_type << std::endl; + if (if_packet_info.packet_type + != uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_FC) { + UHD_LOGGER_ERROR("TX FLOW CTRL") + << "Unexpected packet received by flow control handler: " + << if_packet_info.packet_type << std::endl; continue; } - const uint32_t *payload = &packet_buff[if_packet_info.num_header_words32]; - const uint32_t pkt_count = fc_cache->to_host(payload[0]); + const uint32_t* payload = &packet_buff[if_packet_info.num_header_words32]; + const uint32_t pkt_count = fc_cache->to_host(payload[0]); const uint32_t byte_count = fc_cache->to_host(payload[1]); // update the amount of space fc_cache->last_byte_ack = byte_count; - fc_cache->last_seq_ack = pkt_count; + fc_cache->last_seq_ack = pkt_count; fc_cache->fc_received = true; } @@ -239,13 +240,11 @@ inline bool tx_flow_ctrl( return false; } -inline void tx_flow_ctrl_ack( - boost::shared_ptr<tx_fc_cache_t> fc_cache, +inline void tx_flow_ctrl_ack(boost::shared_ptr<tx_fc_cache_t> fc_cache, uhd::transport::zero_copy_if::sptr send_xport, - uhd::sid_t send_sid -) { - if (not fc_cache->fc_received) - { + uhd::sid_t send_sid) +{ + if (not fc_cache->fc_received) { return; } @@ -256,42 +255,42 @@ inline void tx_flow_ctrl_ack( UHD_LOGGER_ERROR("tx_flow_ctrl_ack") << "timed out getting a send buffer"; return; } - uint32_t *pkt = fc_buff->cast<uint32_t *>(); + uint32_t* pkt = fc_buff->cast<uint32_t*>(); // Load packet info uhd::transport::vrt::if_packet_info_t packet_info; packet_info.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_ACK; packet_info.num_payload_words32 = uhd::usrp::DEVICE3_FC_PACKET_LEN_IN_WORDS32; - packet_info.num_payload_bytes = packet_info.num_payload_words32*sizeof(uint32_t); - packet_info.packet_count = fc_cache->fc_ack_seqnum++; - packet_info.sob = false; - packet_info.eob = true; - packet_info.error = false; - packet_info.fc_ack = false; - packet_info.sid = send_sid.get(); - packet_info.has_sid = true; - packet_info.has_cid = false; - packet_info.has_tsi = false; - packet_info.has_tsf = false; - packet_info.has_tlr = false; + packet_info.num_payload_bytes = packet_info.num_payload_words32 * sizeof(uint32_t); + packet_info.packet_count = fc_cache->fc_ack_seqnum++; + packet_info.sob = false; + packet_info.eob = true; + packet_info.error = false; + packet_info.fc_ack = false; + packet_info.sid = send_sid.get(); + packet_info.has_sid = true; + packet_info.has_cid = false; + packet_info.has_tsi = false; + packet_info.has_tsf = false; + packet_info.has_tlr = false; // Load Header: fc_cache->pack(pkt, packet_info); // Update counters to include this packet - size_t fc_ack_pkt_size = sizeof(uint32_t)*(packet_info.num_packet_words32); + size_t fc_ack_pkt_size = sizeof(uint32_t) * (packet_info.num_packet_words32); fc_cache->byte_count += fc_ack_pkt_size; // Round up to nearest word - if (fc_cache->byte_count % uhd::usrp::DEVICE3_LINE_SIZE) - { - fc_cache->byte_count += uhd::usrp::DEVICE3_LINE_SIZE - (fc_cache->byte_count % uhd::usrp::DEVICE3_LINE_SIZE); + if (fc_cache->byte_count % uhd::usrp::DEVICE3_LINE_SIZE) { + fc_cache->byte_count += uhd::usrp::DEVICE3_LINE_SIZE + - (fc_cache->byte_count % uhd::usrp::DEVICE3_LINE_SIZE); } fc_cache->pkt_count++; // Load Payload: Packet count, and byte count - pkt[packet_info.num_header_words32+uhd::usrp::DEVICE3_FC_PACKET_COUNT_OFFSET] = + pkt[packet_info.num_header_words32 + uhd::usrp::DEVICE3_FC_PACKET_COUNT_OFFSET] = fc_cache->from_host(fc_cache->pkt_count); - pkt[packet_info.num_header_words32+uhd::usrp::DEVICE3_FC_BYTE_COUNT_OFFSET] = + pkt[packet_info.num_header_words32 + uhd::usrp::DEVICE3_FC_BYTE_COUNT_OFFSET] = fc_cache->from_host(fc_cache->byte_count); // Send the buffer over the interface @@ -301,6 +300,6 @@ inline void tx_flow_ctrl_ack( fc_cache->fc_received = false; } -}}; +}}; // namespace uhd::usrp #endif /* INCLUDED_DEVICE3_FLOW_CTRL_HPP */ diff --git a/host/lib/usrp/device3/device3_impl.cpp b/host/lib/usrp/device3/device3_impl.cpp index 5705d6a84..d636b3338 100644 --- a/host/lib/usrp/device3/device3_impl.cpp +++ b/host/lib/usrp/device3/device3_impl.cpp @@ -6,10 +6,10 @@ // #include "device3_impl.hpp" -#include <uhd/utils/log.hpp> #include <uhd/rfnoc/block_ctrl_base.hpp> -#include <uhdlib/rfnoc/graph_impl.hpp> +#include <uhd/utils/log.hpp> #include <uhdlib/rfnoc/ctrl_iface.hpp> +#include <uhdlib/rfnoc/graph_impl.hpp> #include <boost/make_shared.hpp> #include <algorithm> @@ -18,21 +18,20 @@ using namespace uhd::usrp; device3_impl::device3_impl() { _type = uhd::device::USRP; - _async_md.reset(new async_md_type(1000/*messages deep*/)); + _async_md.reset(new async_md_type(1000 /*messages deep*/)); _tree = uhd::property_tree::make(); }; //! Returns true if the integer value stored in lhs is smaller than that in rhs -bool _compare_string_indexes(const std::string &lhs, const std::string &rhs) +bool _compare_string_indexes(const std::string& lhs, const std::string& rhs) { return boost::lexical_cast<size_t>(lhs) < boost::lexical_cast<size_t>(rhs); } -void device3_impl::merge_channel_defs( - const std::vector<uhd::rfnoc::block_id_t> &chan_ids, - const std::vector<uhd::device_addr_t> &chan_args, - const uhd::direction_t dir -) { +void device3_impl::merge_channel_defs(const std::vector<uhd::rfnoc::block_id_t>& chan_ids, + const std::vector<uhd::device_addr_t>& chan_args, + const uhd::direction_t dir) +{ UHD_ASSERT_THROW(chan_ids.size() == chan_args.size()); if (dir == uhd::DX_DIRECTION) { merge_channel_defs(chan_ids, chan_args, RX_DIRECTION); @@ -40,7 +39,8 @@ void device3_impl::merge_channel_defs( return; } - uhd::fs_path chans_root = uhd::fs_path("/channels/") / (dir == RX_DIRECTION ? "rx" : "tx"); + uhd::fs_path chans_root = + uhd::fs_path("/channels/") / (dir == RX_DIRECTION ? "rx" : "tx"); // Store the new positions of the channels: std::vector<size_t> chan_idxs; @@ -54,18 +54,23 @@ void device3_impl::merge_channel_defs( // 2. Cycle through existing channels to find out where to merge // the new channels. Rules are: // - The order of chan_ids must be preserved - // - All block indices that are in chan_ids may be overwritten in the channel definition + // - All block indices that are in chan_ids may be overwritten in the channel + // definition // - If the channels in chan_ids are not yet in the property tree channel list, // they are appended. - for(const std::string &chan_idx: curr_channels) { + for (const std::string& chan_idx : curr_channels) { if (_tree->exists(chans_root / chan_idx)) { - rfnoc::block_id_t chan_block_id = _tree->access<rfnoc::block_id_t>(chans_root / chan_idx).get(); - if (std::find(chan_ids.begin(), chan_ids.end(), chan_block_id) != chan_ids.end()) { + rfnoc::block_id_t chan_block_id = + _tree->access<rfnoc::block_id_t>(chans_root / chan_idx).get(); + if (std::find(chan_ids.begin(), chan_ids.end(), chan_block_id) + != chan_ids.end()) { chan_idxs.push_back(boost::lexical_cast<size_t>(chan_idx)); } } } - size_t last_chan_idx = curr_channels.empty() ? 0 : (boost::lexical_cast<size_t>(curr_channels.back()) + 1); + size_t last_chan_idx = curr_channels.empty() + ? 0 + : (boost::lexical_cast<size_t>(curr_channels.back()) + 1); while (chan_idxs.size() < chan_ids.size()) { chan_idxs.push_back(last_chan_idx); last_chan_idx++; @@ -80,27 +85,28 @@ void device3_impl::merge_channel_defs( if (not _tree->exists(chans_root / chan_idxs[i] / "args")) { _tree->create<uhd::device_addr_t>(chans_root / chan_idxs[i] / "args"); } - _tree->access<uhd::device_addr_t>(chans_root / chan_idxs[i] / "args").set(chan_args[i]); + _tree->access<uhd::device_addr_t>(chans_root / chan_idxs[i] / "args") + .set(chan_args[i]); } } /*********************************************************************** * RFNoC-Specific **********************************************************************/ -void device3_impl::enumerate_rfnoc_blocks( - size_t device_index, - size_t n_blocks, - size_t base_port, - const uhd::sid_t &base_sid, - uhd::device_addr_t transport_args -) { +void device3_impl::enumerate_rfnoc_blocks(size_t device_index, + size_t n_blocks, + size_t base_port, + const uhd::sid_t& base_sid, + uhd::device_addr_t transport_args) +{ // entries that are already connected to this block uhd::sid_t ctrl_sid = base_sid; - uhd::property_tree::sptr subtree = _tree->subtree(uhd::fs_path("/mboards") / device_index); + uhd::property_tree::sptr subtree = + _tree->subtree(uhd::fs_path("/mboards") / device_index); // 1) Clean property tree entries // TODO put this back once radios are actual rfnoc blocks!!!!!! - //if (subtree->exists("xbar")) { - //subtree->remove("xbar"); + // if (subtree->exists("xbar")) { + // subtree->remove("xbar"); //} // 2) Destroy existing block controllers // TODO: Clear out all the old block control classes @@ -109,40 +115,27 @@ void device3_impl::enumerate_rfnoc_blocks( // First, make a transport for port number zero, because we always need that: ctrl_sid.set_dst_xbarport(base_port + i); ctrl_sid.set_dst_blockport(0); - both_xports_t xport = this->make_transport( - ctrl_sid, - CTRL, - transport_args - ); + both_xports_t xport = this->make_transport(ctrl_sid, CTRL, transport_args); UHD_LOG_TRACE("DEVICE3", str(boost::format("Setting up NoC-Shell Control for port #0 (SID: %s)...") - % xport.send_sid.to_pp_string_hex()) - ); - uhd::rfnoc::ctrl_iface::sptr ctrl = uhd::rfnoc::ctrl_iface::make( - xport, - str(boost::format("CE_%02d_Port_%02X") - % i - % ctrl_sid.get_dst_endpoint()) - ); - uint64_t noc_id = ctrl->send_cmd_pkt( - uhd::rfnoc::SR_READBACK, - uhd::rfnoc::SR_READBACK_REG_ID, - true - ); - UHD_LOG_DEBUG("DEVICE3", str( - boost::format("Port 0x%02X: Found NoC-Block with ID %016X.") - % int(ctrl_sid.get_dst_endpoint()) - % noc_id - )); + % xport.send_sid.to_pp_string_hex())); + uhd::rfnoc::ctrl_iface::sptr ctrl = uhd::rfnoc::ctrl_iface::make(xport, + str(boost::format("CE_%02d_Port_%02X") % i % ctrl_sid.get_dst_endpoint())); + uint64_t noc_id = ctrl->send_cmd_pkt( + uhd::rfnoc::SR_READBACK, uhd::rfnoc::SR_READBACK_REG_ID, true); + UHD_LOG_DEBUG("DEVICE3", + str(boost::format("Port 0x%02X: Found NoC-Block with ID %016X.") + % int(ctrl_sid.get_dst_endpoint()) % noc_id)); uhd::rfnoc::make_args_t make_args; - uhd::rfnoc::blockdef::sptr block_def = uhd::rfnoc::blockdef::make_from_noc_id(noc_id); + uhd::rfnoc::blockdef::sptr block_def = + uhd::rfnoc::blockdef::make_from_noc_id(noc_id); if (not block_def) { UHD_LOG_WARNING("DEVICE3", "No block definition found, using default block configuration " - "for block with NOC ID: " + str(boost::format("0x%08X") % noc_id) - ); - block_def = uhd::rfnoc::blockdef::make_from_noc_id( - uhd::rfnoc::DEFAULT_NOC_ID); + "for block with NOC ID: " + + str(boost::format("0x%08X") % noc_id)); + block_def = + uhd::rfnoc::blockdef::make_from_noc_id(uhd::rfnoc::DEFAULT_NOC_ID); } UHD_ASSERT_THROW(block_def); make_args.ctrl_ifaces[0] = ctrl; @@ -151,71 +144,59 @@ void device3_impl::enumerate_rfnoc_blocks( continue; } ctrl_sid.set_dst_blockport(port_number); - both_xports_t xport1 = this->make_transport( - ctrl_sid, - CTRL, - transport_args - ); - UHD_LOG_TRACE("DEVICE3", str( - boost::format("Setting up NoC-Shell Control for port #%d " + both_xports_t xport1 = this->make_transport(ctrl_sid, CTRL, transport_args); + UHD_LOG_TRACE("DEVICE3", + str(boost::format("Setting up NoC-Shell Control for port #%d " "(SID: %s)...") - % port_number - % xport1.send_sid.to_pp_string_hex() - )); - uhd::rfnoc::ctrl_iface::sptr ctrl1 = uhd::rfnoc::ctrl_iface::make( - xport1, - str(boost::format("CE_%02d_Port_%02X") % i % ctrl_sid.get_dst_endpoint()) - ); + % port_number % xport1.send_sid.to_pp_string_hex())); + uhd::rfnoc::ctrl_iface::sptr ctrl1 = uhd::rfnoc::ctrl_iface::make(xport1, + str(boost::format("CE_%02d_Port_%02X") % i + % ctrl_sid.get_dst_endpoint())); make_args.ctrl_ifaces[port_number] = ctrl1; } UHD_LOG_TRACE("DEVICE3", - "All control transports successfully created for block with ID " << - str(boost::format("0x%08X") % noc_id) - ); + "All control transports successfully created for block with ID " + << str(boost::format("0x%08X") % noc_id)); make_args.base_address = xport.send_sid.get_dst(); make_args.device_index = device_index; - make_args.tree = subtree; - { //Critical section for block_ctrl vector access + make_args.tree = subtree; + { // Critical section for block_ctrl vector access boost::lock_guard<boost::mutex> lock(_block_ctrl_mutex); - _rfnoc_block_ctrl.push_back(uhd::rfnoc::block_ctrl_base::make(make_args, noc_id)); + _rfnoc_block_ctrl.push_back( + uhd::rfnoc::block_ctrl_base::make(make_args, noc_id)); } } } -uhd::rfnoc::graph::sptr device3_impl::create_graph(const std::string &name) +uhd::rfnoc::graph::sptr device3_impl::create_graph(const std::string& name) { // Create an async message handler - UHD_LOGGER_TRACE("DEVICE3") << "Creating async message handler for graph `" << name << "'..."; - // FIXME: right now this only can only handle source sid of 0 and xbar local addr of 2. - // This is ok for now because that most of our device has xbard local addr hardcode to 2. + UHD_LOGGER_TRACE("DEVICE3") + << "Creating async message handler for graph `" << name << "'..."; + // FIXME: right now this only can only handle source sid of 0 and xbar local addr + // of 2. This is ok for now because that most of our device has xbard local addr + // hardcode to 2. sid_t async_sid(0); async_sid.set_dst_addr(2); - both_xports_t async_xports = make_transport( - async_sid, - ASYNC_MSG, - //FIXME: only get rx_hints from mb index of 0 - get_rx_hints(0) - ); + both_xports_t async_xports = make_transport(async_sid, + ASYNC_MSG, + // FIXME: only get rx_hints from mb index of 0 + get_rx_hints(0)); UHD_LOGGER_TRACE("DEVICE3") << " Async transport ready." << std::endl; uhd::rfnoc::async_msg_handler::sptr async_msg_handler = - uhd::rfnoc::async_msg_handler::make( - async_xports.recv, - async_xports.send, - async_xports.send_sid, - async_xports.endianness - ); - UHD_LOGGER_TRACE("DEVICE3") << "Async message has address " << async_xports.send_sid << std::endl; + uhd::rfnoc::async_msg_handler::make(async_xports.recv, + async_xports.send, + async_xports.send_sid, + async_xports.endianness); + UHD_LOGGER_TRACE("DEVICE3") + << "Async message has address " << async_xports.send_sid << std::endl; // Create the graph UHD_LOGGER_TRACE("DEVICE3") << "Creating graph `" << name << "'..." << std::endl; uhd::rfnoc::graph::sptr graph = boost::make_shared<uhd::rfnoc::graph_impl>( - name, - shared_from_this(), - async_msg_handler - ); + name, shared_from_this(), async_msg_handler); return graph; } - diff --git a/host/lib/usrp/device3/device3_impl.hpp b/host/lib/usrp/device3/device3_impl.hpp index e82597b9b..3bf6f6111 100644 --- a/host/lib/usrp/device3/device3_impl.hpp +++ b/host/lib/usrp/device3/device3_impl.hpp @@ -11,20 +11,20 @@ #ifndef INCLUDED_DEVICE3_IMPL_HPP #define INCLUDED_DEVICE3_IMPL_HPP +#include "../../transport/super_recv_packet_handler.hpp" +#include "../../transport/super_send_packet_handler.hpp" +#include <uhd/device3.hpp> #include <uhd/transport/bounded_buffer.hpp> -#include <uhd/transport/vrt_if_packet.hpp> #include <uhd/transport/chdr.hpp> +#include <uhd/transport/vrt_if_packet.hpp> #include <uhd/transport/zero_copy.hpp> -#include <uhd/types/sid.hpp> -#include <uhd/types/metadata.hpp> -#include <uhd/types/endianness.hpp> #include <uhd/types/direction.hpp> +#include <uhd/types/endianness.hpp> +#include <uhd/types/metadata.hpp> +#include <uhd/types/sid.hpp> #include <uhd/utils/tasks.hpp> -#include <uhd/device3.hpp> -#include "../../transport/super_send_packet_handler.hpp" -#include "../../transport/super_recv_packet_handler.hpp" -#include <uhdlib/rfnoc/tx_stream_terminator.hpp> #include <uhdlib/rfnoc/rx_stream_terminator.hpp> +#include <uhdlib/rfnoc/tx_stream_terminator.hpp> #include <uhdlib/rfnoc/xports.hpp> namespace uhd { namespace usrp { @@ -32,31 +32,33 @@ namespace uhd { namespace usrp { /*********************************************************************** * Default settings (any device3 may override these) **********************************************************************/ -static const size_t DEVICE3_RX_FC_REQUEST_FREQ = 32; //per flow-control window -static const size_t DEVICE3_TX_FC_RESPONSE_FREQ = 8; -static const size_t DEVICE3_FC_PACKET_LEN_IN_WORDS32 = 2; -static const size_t DEVICE3_FC_PACKET_COUNT_OFFSET = 0; -static const size_t DEVICE3_FC_BYTE_COUNT_OFFSET = 1; -static const size_t DEVICE3_LINE_SIZE = 8; - -static const size_t DEVICE3_TX_MAX_HDR_LEN = uhd::transport::vrt::chdr::max_if_hdr_words64 * sizeof(uint64_t); // Bytes -static const size_t DEVICE3_RX_MAX_HDR_LEN = uhd::transport::vrt::chdr::max_if_hdr_words64 * sizeof(uint64_t); // Bytes - -// This class manages the lifetime of the TX async message handler task, transports, and terminator +static const size_t DEVICE3_RX_FC_REQUEST_FREQ = 32; // per flow-control window +static const size_t DEVICE3_TX_FC_RESPONSE_FREQ = 8; +static const size_t DEVICE3_FC_PACKET_LEN_IN_WORDS32 = 2; +static const size_t DEVICE3_FC_PACKET_COUNT_OFFSET = 0; +static const size_t DEVICE3_FC_BYTE_COUNT_OFFSET = 1; +static const size_t DEVICE3_LINE_SIZE = 8; + +static const size_t DEVICE3_TX_MAX_HDR_LEN = + uhd::transport::vrt::chdr::max_if_hdr_words64 * sizeof(uint64_t); // Bytes +static const size_t DEVICE3_RX_MAX_HDR_LEN = + uhd::transport::vrt::chdr::max_if_hdr_words64 * sizeof(uint64_t); // Bytes + +// This class manages the lifetime of the TX async message handler task, transports, and +// terminator class device3_send_packet_streamer : public uhd::transport::sph::send_packet_streamer { public: - device3_send_packet_streamer( - const size_t max_num_samps, - const uhd::rfnoc::tx_stream_terminator::sptr terminator, - const both_xports_t data_xport, - const both_xports_t async_msg_xport - ) : - uhd::transport::sph::send_packet_streamer(max_num_samps), - _terminator(terminator), - _data_xport(data_xport), - _async_msg_xport(async_msg_xport) - {} + device3_send_packet_streamer(const size_t max_num_samps, + const uhd::rfnoc::tx_stream_terminator::sptr terminator, + const both_xports_t data_xport, + const both_xports_t async_msg_xport) + : uhd::transport::sph::send_packet_streamer(max_num_samps) + , _terminator(terminator) + , _data_xport(data_xport) + , _async_msg_xport(async_msg_xport) + { + } ~device3_send_packet_streamer() { @@ -81,18 +83,19 @@ private: std::vector<task::sptr> _tx_async_msg_tasks; }; -// This class manages the lifetime of the RX transports and terminator and provides access to both +// This class manages the lifetime of the RX transports and terminator and provides access +// to both class device3_recv_packet_streamer : public uhd::transport::sph::recv_packet_streamer { public: - device3_recv_packet_streamer( - const size_t max_num_samps, - const uhd::rfnoc::rx_stream_terminator::sptr terminator, - const both_xports_t xport - ) : - uhd::transport::sph::recv_packet_streamer(max_num_samps), - _terminator(terminator), - _xport(xport) {} + device3_recv_packet_streamer(const size_t max_num_samps, + const uhd::rfnoc::rx_stream_terminator::sptr terminator, + const both_xports_t xport) + : uhd::transport::sph::recv_packet_streamer(max_num_samps) + , _terminator(terminator) + , _xport(xport) + { + } ~device3_recv_packet_streamer() {} @@ -111,7 +114,8 @@ private: both_xports_t _xport; }; -class device3_impl : public uhd::device3, public boost::enable_shared_from_this<device3_impl> +class device3_impl : public uhd::device3, + public boost::enable_shared_from_this<device3_impl> { public: /*********************************************************************** @@ -120,14 +124,9 @@ public: typedef uhd::transport::bounded_buffer<uhd::async_metadata_t> async_md_type; //! The purpose of a transport - enum xport_type_t { - CTRL = 0, - ASYNC_MSG, - TX_DATA, - RX_DATA - }; + enum xport_type_t { CTRL = 0, ASYNC_MSG, TX_DATA, RX_DATA }; - enum xport_t {AXI, ETH, PCIE}; + enum xport_t { AXI, ETH, PCIE }; //! Stores all streaming-related options struct stream_options_t @@ -145,20 +144,21 @@ public: , rx_max_len_hdr(DEVICE3_RX_MAX_HDR_LEN) , rx_fc_request_freq(DEVICE3_RX_FC_REQUEST_FREQ) , tx_fc_response_freq(DEVICE3_TX_FC_RESPONSE_FREQ) - {} + { + } }; /*********************************************************************** * I/O Interface **********************************************************************/ - uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &); - uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &); - bool recv_async_msg(uhd::async_metadata_t &async_metadata, double timeout); + uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t&); + uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t&); + bool recv_async_msg(uhd::async_metadata_t& async_metadata, double timeout); /*********************************************************************** * Other public APIs **********************************************************************/ - rfnoc::graph::sptr create_graph(const std::string &name=""); + rfnoc::graph::sptr create_graph(const std::string& name = ""); protected: /*********************************************************************** @@ -172,10 +172,10 @@ protected: **********************************************************************/ // The 'rate' argument is so we can use these as subscribers to rate changes public: // TODO make these protected again - void update_rx_streamers(double rate=-1.0); - void update_tx_streamers(double rate=-1.0); -protected: + void update_rx_streamers(double rate = -1.0); + void update_tx_streamers(double rate = -1.0); +protected: /*********************************************************************** * Transport-related **********************************************************************/ @@ -187,17 +187,21 @@ protected: * The source address in this value is not considered, only the * destination address. * \param xport_type Specify which kind of transport this is. - * \param args Additional arguments for the transport generation. See \ref page_transport - * for valid arguments. + * \param args Additional arguments for the transport generation. See \ref + * page_transport for valid arguments. */ - virtual uhd::both_xports_t make_transport( - const uhd::sid_t &address, + virtual uhd::both_xports_t make_transport(const uhd::sid_t& address, const xport_type_t xport_type, - const uhd::device_addr_t& args - ) = 0; + const uhd::device_addr_t& args) = 0; - virtual uhd::device_addr_t get_tx_hints(size_t) { return uhd::device_addr_t(); } - virtual uhd::device_addr_t get_rx_hints(size_t) { return uhd::device_addr_t(); } + virtual uhd::device_addr_t get_tx_hints(size_t) + { + return uhd::device_addr_t(); + } + virtual uhd::device_addr_t get_rx_hints(size_t) + { + return uhd::device_addr_t(); + } //! Is called after a streamer is generated virtual void post_streamer_hooks(uhd::direction_t) {} @@ -216,29 +220,25 @@ protected: * \param chan_args New channel args. Must have same length as chan_ids. * */ - void merge_channel_defs( - const std::vector<rfnoc::block_id_t> &chan_ids, - const std::vector<uhd::device_addr_t> &chan_args, - const uhd::direction_t dir - ); + void merge_channel_defs(const std::vector<rfnoc::block_id_t>& chan_ids, + const std::vector<uhd::device_addr_t>& chan_args, + const uhd::direction_t dir); /*********************************************************************** * RFNoC-Specific **********************************************************************/ - void enumerate_rfnoc_blocks( - size_t device_index, - size_t n_blocks, - size_t base_port, - const uhd::sid_t &base_sid, - uhd::device_addr_t transport_args - ); + void enumerate_rfnoc_blocks(size_t device_index, + size_t n_blocks, + size_t base_port, + const uhd::sid_t& base_sid, + uhd::device_addr_t transport_args); /*********************************************************************** * Members **********************************************************************/ // TODO: Maybe move these to private - uhd::dict<std::string, boost::weak_ptr<uhd::rx_streamer> > _rx_streamers; - uhd::dict<std::string, boost::weak_ptr<uhd::tx_streamer> > _tx_streamers; + uhd::dict<std::string, boost::weak_ptr<uhd::rx_streamer>> _rx_streamers; + uhd::dict<std::string, boost::weak_ptr<uhd::tx_streamer>> _tx_streamers; private: /*********************************************************************** diff --git a/host/lib/usrp/device3/device3_io_impl.cpp b/host/lib/usrp/device3/device3_io_impl.cpp index 7afa2ace0..c0f91368d 100644 --- a/host/lib/usrp/device3/device3_io_impl.cpp +++ b/host/lib/usrp/device3/device3_io_impl.cpp @@ -7,16 +7,16 @@ // Provides streaming-related functions which are used by device3 objects. -#include "device3_impl.hpp" #include "device3_flow_ctrl.hpp" +#include "device3_impl.hpp" #include <uhd/rfnoc/constants.hpp> -#include <uhd/rfnoc/source_block_ctrl_base.hpp> +#include <uhd/rfnoc/radio_ctrl.hpp> +#include <uhd/rfnoc/rate_node_ctrl.hpp> #include <uhd/rfnoc/sink_block_ctrl_base.hpp> +#include <uhd/rfnoc/source_block_ctrl_base.hpp> +#include <uhd/transport/zero_copy_flow_ctrl.hpp> #include <uhd/utils/byteswap.hpp> #include <uhd/utils/log.hpp> -#include <uhd/rfnoc/rate_node_ctrl.hpp> -#include <uhd/rfnoc/radio_ctrl.hpp> -#include <uhd/transport/zero_copy_flow_ctrl.hpp> #include <uhdlib/rfnoc/rx_stream_terminator.hpp> #include <uhdlib/rfnoc/tx_stream_terminator.hpp> #include <uhdlib/usrp/common/async_packet_handler.hpp> @@ -32,7 +32,7 @@ using namespace uhd::transport; /*********************************************************************** * Helper functions for get_?x_stream() **********************************************************************/ -static uhd::stream_args_t sanitize_stream_args(const uhd::stream_args_t &args_) +static uhd::stream_args_t sanitize_stream_args(const uhd::stream_args_t& args_) { uhd::stream_args_t args = args_; if (args.channels.empty()) { @@ -42,31 +42,33 @@ static uhd::stream_args_t sanitize_stream_args(const uhd::stream_args_t &args_) return args; } -static void check_stream_sig_compatible(const rfnoc::stream_sig_t &stream_sig, stream_args_t &args, const std::string &tx_rx) +static void check_stream_sig_compatible( + const rfnoc::stream_sig_t& stream_sig, stream_args_t& args, const std::string& tx_rx) { if (args.otw_format.empty()) { if (stream_sig.item_type.empty()) { - throw uhd::runtime_error(str( - boost::format("[%s Streamer] No otw_format defined!") % tx_rx - )); + throw uhd::runtime_error( + str(boost::format("[%s Streamer] No otw_format defined!") % tx_rx)); } else { args.otw_format = stream_sig.item_type; } - } else if (not stream_sig.item_type.empty() and stream_sig.item_type != args.otw_format) { - throw uhd::runtime_error(str( - boost::format("[%s Streamer] Conflicting OTW types defined: args.otw_format = '%s' <=> stream_sig.item_type = '%s'") - % tx_rx % args.otw_format % stream_sig.item_type - )); + } else if (not stream_sig.item_type.empty() + and stream_sig.item_type != args.otw_format) { + throw uhd::runtime_error( + str(boost::format("[%s Streamer] Conflicting OTW types defined: " + "args.otw_format = '%s' <=> stream_sig.item_type = '%s'") + % tx_rx % args.otw_format % stream_sig.item_type)); } const size_t bpi = convert::get_bytes_per_item(args.otw_format); // bytes per item if (stream_sig.packet_size) { if (args.args.has_key("spp")) { size_t args_spp = args.args.cast<size_t>("spp", 0); if (args_spp * bpi != stream_sig.packet_size) { - throw uhd::runtime_error(str( - boost::format("[%s Streamer] Conflicting packet sizes defined: args yields %d bytes but stream_sig.packet_size is %d bytes") - % tx_rx % (args_spp * bpi) % stream_sig.packet_size - )); + throw uhd::runtime_error( + str(boost::format( + "[%s Streamer] Conflicting packet sizes defined: args yields " + "%d bytes but stream_sig.packet_size is %d bytes") + % tx_rx % (args_spp * bpi) % stream_sig.packet_size)); } } else { args.args["spp"] = str(boost::format("%d") % (stream_sig.packet_size / bpi)); @@ -82,19 +84,18 @@ static void check_stream_sig_compatible(const rfnoc::stream_sig_t &stream_sig, s * * \param args_ Stream args. * \param[out] chan_list The list of channels in the correct order. - * \param[out] chan_args Channel args for every channel. `chan_args.size() == chan_list.size()` + * \param[out] chan_args Channel args for every channel. `chan_args.size() == + * chan_list.size()` */ -void generate_channel_list( - const uhd::stream_args_t &args_, - std::vector<uhd::rfnoc::block_id_t> &chan_list, - std::vector<device_addr_t> &chan_args -) { +void generate_channel_list(const uhd::stream_args_t& args_, + std::vector<uhd::rfnoc::block_id_t>& chan_list, + std::vector<device_addr_t>& chan_args) +{ uhd::stream_args_t args = args_; std::vector<uhd::rfnoc::block_id_t> chan_list_(args.channels.size()); std::vector<device_addr_t> chan_args_(args.channels.size()); - for (size_t i = 0; i < args.channels.size(); i++) - { + for (size_t i = 0; i < args.channels.size(); i++) { // Extract block ID size_t chan_idx = args.channels[i]; std::string key = str(boost::format("block_id%d") % chan_idx); @@ -103,10 +104,10 @@ void generate_channel_list( } else if (args.args.has_key("block_id")) { chan_list_[i] = args.args["block_id"]; } else { - throw uhd::runtime_error(str( - boost::format("Cannot create streamers: No block_id specified for channel %d.") - % chan_idx - )); + throw uhd::runtime_error( + str(boost::format( + "Cannot create streamers: No block_id specified for channel %d.") + % chan_idx)); } // Split off known channel specific args @@ -125,7 +126,7 @@ void generate_channel_list( } // Add all remaining args to all channel args - for(device_addr_t &chan_arg: chan_args_) { + for (device_addr_t& chan_arg : chan_args_) { chan_arg = chan_arg.to_string() + "," + args.args.to_string(); } @@ -154,25 +155,20 @@ void generate_channel_list( * \returns The size of the flow control window in number of packets */ static size_t get_rx_flow_control_window( - size_t pkt_size, - size_t sw_buff_size, - const device_addr_t& rx_args -) { + size_t pkt_size, size_t sw_buff_size, const device_addr_t& rx_args) +{ double fullness_factor = rx_args.cast<double>( - "recv_buff_fullness", - uhd::rfnoc::DEFAULT_FC_RX_SW_BUFF_FULL_FACTOR - ); + "recv_buff_fullness", uhd::rfnoc::DEFAULT_FC_RX_SW_BUFF_FULL_FACTOR); if (fullness_factor < 0.01 || fullness_factor > 1) { - throw uhd::value_error("recv_buff_fullness must be in [0.01, 1] inclusive (1% to 100%)"); + throw uhd::value_error( + "recv_buff_fullness must be in [0.01, 1] inclusive (1% to 100%)"); } size_t window_in_bytes = (static_cast<size_t>(sw_buff_size * fullness_factor)); if (rx_args.has_key("max_recv_window")) { window_in_bytes = std::min( - window_in_bytes, - rx_args.cast<size_t>("max_recv_window", window_in_bytes) - ); + window_in_bytes, rx_args.cast<size_t>("max_recv_window", window_in_bytes)); } if (window_in_bytes < pkt_size) { throw uhd::value_error("recv_buff_size must be larger than the recv_frame_size."); @@ -200,32 +196,28 @@ struct async_tx_info_t * * This is run inside a uhd::task as long as this streamer lives. */ -static void handle_tx_async_msgs( - boost::shared_ptr<async_tx_info_t> async_info, - zero_copy_if::sptr xport, - uint32_t (*to_host)(uint32_t), - void (*unpack)(const uint32_t *packet_buff, vrt::if_packet_info_t &), - boost::function<double(void)> get_tick_rate -) { +static void handle_tx_async_msgs(boost::shared_ptr<async_tx_info_t> async_info, + zero_copy_if::sptr xport, + uint32_t (*to_host)(uint32_t), + void (*unpack)(const uint32_t* packet_buff, vrt::if_packet_info_t&), + boost::function<double(void)> get_tick_rate) +{ managed_recv_buffer::sptr buff = xport->get_recv_buff(); - if (not buff) - { + if (not buff) { return; } - //extract packet info + // extract packet info vrt::if_packet_info_t if_packet_info; - if_packet_info.num_packet_words32 = buff->size()/sizeof(uint32_t); - const uint32_t *packet_buff = buff->cast<const uint32_t *>(); + if_packet_info.num_packet_words32 = buff->size() / sizeof(uint32_t); + const uint32_t* packet_buff = buff->cast<const uint32_t*>(); - //unpacking can fail - try - { + // unpacking can fail + try { unpack(packet_buff, if_packet_info); - } - catch(const std::exception &ex) - { - UHD_LOGGER_ERROR("STREAMER") << "Error parsing async message packet: " << ex.what() ; + } catch (const std::exception& ex) { + UHD_LOGGER_ERROR("STREAMER") + << "Error parsing async message packet: " << ex.what(); return; } @@ -234,21 +226,20 @@ static void handle_tx_async_msgs( tick_rate = 1; } - //fill in the async metadata + // fill in the async metadata async_metadata_t metadata; - load_metadata_from_buff( - to_host, - metadata, - if_packet_info, - packet_buff, - tick_rate, - async_info->stream_channel - ); + load_metadata_from_buff(to_host, + metadata, + if_packet_info, + packet_buff, + tick_rate, + async_info->stream_channel); // Filter out any flow control messages and cache the rest - if (metadata.event_code == DEVICE3_ASYNC_EVENT_CODE_FLOW_CTRL) - { - UHD_LOGGER_ERROR("TX ASYNC MSG") << "Unexpected flow control message found in async message handling" << std::endl; + if (metadata.event_code == DEVICE3_ASYNC_EVENT_CODE_FLOW_CTRL) { + UHD_LOGGER_ERROR("TX ASYNC MSG") + << "Unexpected flow control message found in async message handling" + << std::endl; } else { async_info->async_queue->push_with_pop_on_full(metadata); metadata.channel = async_info->device_channel; @@ -257,9 +248,7 @@ static void handle_tx_async_msgs( } } -bool device3_impl::recv_async_msg( - async_metadata_t &async_metadata, double timeout -) +bool device3_impl::recv_async_msg(async_metadata_t& async_metadata, double timeout) { return _async_md->pop_with_timed_wait(async_metadata, timeout); } @@ -269,10 +258,11 @@ bool device3_impl::recv_async_msg( **********************************************************************/ void device3_impl::update_rx_streamers(double /* rate */) { - for(const std::string &block_id: _rx_streamers.keys()) { + for (const std::string& block_id : _rx_streamers.keys()) { UHD_RX_STREAMER_LOG() << "updating RX streamer to " << block_id; boost::shared_ptr<device3_recv_packet_streamer> my_streamer = - boost::dynamic_pointer_cast<device3_recv_packet_streamer>(_rx_streamers[block_id].lock()); + boost::dynamic_pointer_cast<device3_recv_packet_streamer>( + _rx_streamers[block_id].lock()); if (my_streamer) { double tick_rate = my_streamer->get_terminator()->get_tick_rate(); if (tick_rate == rfnoc::tick_node_ctrl::RATE_UNDEFINED) { @@ -285,9 +275,11 @@ void device3_impl::update_rx_streamers(double /* rate */) } double scaling = my_streamer->get_terminator()->get_output_scale_factor(); if (scaling == rfnoc::scalar_node_ctrl::SCALE_UNDEFINED) { - scaling = 1/32767.; + scaling = 1 / 32767.; } - UHD_RX_STREAMER_LOG() << " New tick_rate == " << tick_rate << " New samp_rate == " << samp_rate << " New scaling == " << scaling ; + UHD_RX_STREAMER_LOG() + << " New tick_rate == " << tick_rate + << " New samp_rate == " << samp_rate << " New scaling == " << scaling; my_streamer->set_tick_rate(tick_rate); my_streamer->set_samp_rate(samp_rate); @@ -296,7 +288,7 @@ void device3_impl::update_rx_streamers(double /* rate */) } } -rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t &args_) +rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t& args_) { boost::mutex::scoped_lock lock(_transport_setup_mutex); stream_args_t args = sanitize_stream_args(args_); @@ -312,88 +304,83 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t &args_) // The terminator's lifetime is coupled to the streamer. // There is only one terminator. If the streamer has multiple channels, // it will be connected to each upstream block. - rfnoc::rx_stream_terminator::sptr recv_terminator = rfnoc::rx_stream_terminator::make(); - for (size_t stream_i = 0; stream_i < chan_list.size(); stream_i++) - { + rfnoc::rx_stream_terminator::sptr recv_terminator = + rfnoc::rx_stream_terminator::make(); + for (size_t stream_i = 0; stream_i < chan_list.size(); stream_i++) { // First, configure blocks and create transport // Get block ID and mb index uhd::rfnoc::block_id_t block_id = chan_list[stream_i]; - UHD_RX_STREAMER_LOG() << "chan " << stream_i << " connecting to " << block_id ; + UHD_RX_STREAMER_LOG() << "chan " << stream_i << " connecting to " << block_id; // Update args so args.args is always valid for this particular channel: - args.args = chan_args[stream_i]; + args.args = chan_args[stream_i]; size_t mb_index = block_id.get_device_no(); - size_t suggested_block_port = args.args.cast<size_t>("block_port", rfnoc::ANY_PORT); + size_t suggested_block_port = + args.args.cast<size_t>("block_port", rfnoc::ANY_PORT); // Access to this channel's block control uhd::rfnoc::source_block_ctrl_base::sptr blk_ctrl = - boost::dynamic_pointer_cast<uhd::rfnoc::source_block_ctrl_base>(get_block_ctrl(block_id)); + boost::dynamic_pointer_cast<uhd::rfnoc::source_block_ctrl_base>( + get_block_ctrl(block_id)); // Connect the terminator with this channel's block. size_t block_port = blk_ctrl->connect_downstream( - recv_terminator, - suggested_block_port, - args.args - ); + recv_terminator, suggested_block_port, args.args); const size_t terminator_port = recv_terminator->connect_upstream(blk_ctrl); blk_ctrl->set_downstream_port(block_port, terminator_port); recv_terminator->set_upstream_port(terminator_port, block_port); // Check if the block connection is compatible (spp and item type) - check_stream_sig_compatible(blk_ctrl->get_output_signature(block_port), args, "RX"); + check_stream_sig_compatible( + blk_ctrl->get_output_signature(block_port), args, "RX"); // Setup the DSP transport hints device_addr_t rx_hints = get_rx_hints(mb_index); - //allocate sid and create transport + // allocate sid and create transport uhd::sid_t stream_address = blk_ctrl->get_address(block_port); - UHD_RX_STREAMER_LOG() << "creating rx stream " << rx_hints.to_string() ; + UHD_RX_STREAMER_LOG() << "creating rx stream " << rx_hints.to_string(); both_xports_t xport = make_transport(stream_address, RX_DATA, rx_hints); - UHD_RX_STREAMER_LOG() << std::hex << "data_sid = " << xport.send_sid << std::dec << " actual recv_buff_size = " << xport.recv_buff_size; + UHD_RX_STREAMER_LOG() << std::hex << "data_sid = " << xport.send_sid << std::dec + << " actual recv_buff_size = " << xport.recv_buff_size; // Configure the block // Flow control setup const size_t pkt_size = xport.recv->get_recv_frame_size(); // Leave one pkt_size space for overrun packets - TODO make this obsolete - const size_t fc_window = get_rx_flow_control_window(pkt_size, xport.recv_buff_size, rx_hints) - pkt_size; - const size_t fc_handle_window = std::max<size_t>(1, fc_window / stream_options.rx_fc_request_freq); - UHD_RX_STREAMER_LOG()<< "Flow Control Window = " << (fc_window) << ", Flow Control Handler Window = " << fc_handle_window; - blk_ctrl->configure_flow_control_out( - true, + const size_t fc_window = + get_rx_flow_control_window(pkt_size, xport.recv_buff_size, rx_hints) + - pkt_size; + const size_t fc_handle_window = + std::max<size_t>(1, fc_window / stream_options.rx_fc_request_freq); + UHD_RX_STREAMER_LOG() << "Flow Control Window = " << (fc_window) + << ", Flow Control Handler Window = " << fc_handle_window; + blk_ctrl->configure_flow_control_out(true, fc_window, - rx_hints.cast<size_t>("recv_pkt_limit", 0), // On rfnoc-devel, update e300_impl::get_rx_hints() to set this to 32 - block_port - ); + rx_hints.cast<size_t>("recv_pkt_limit", + 0), // On rfnoc-devel, update e300_impl::get_rx_hints() to set this to 32 + block_port); // Add flow control transport boost::shared_ptr<rx_fc_cache_t> fc_cache(new rx_fc_cache_t()); - fc_cache->sid = xport.send_sid; - fc_cache->xport = xport.send; + fc_cache->sid = xport.send_sid; + fc_cache->xport = xport.send; fc_cache->interval = fc_handle_window; - if (xport.endianness == ENDIANNESS_BIG) - { - fc_cache->to_host = uhd::ntohx<uint32_t>; + if (xport.endianness == ENDIANNESS_BIG) { + fc_cache->to_host = uhd::ntohx<uint32_t>; fc_cache->from_host = uhd::htonx<uint32_t>; - fc_cache->pack = vrt::chdr::if_hdr_pack_be; - fc_cache->unpack = vrt::chdr::if_hdr_unpack_be; - } - else - { - fc_cache->to_host = uhd::wtohx<uint32_t>; + fc_cache->pack = vrt::chdr::if_hdr_pack_be; + fc_cache->unpack = vrt::chdr::if_hdr_unpack_be; + } else { + fc_cache->to_host = uhd::wtohx<uint32_t>; fc_cache->from_host = uhd::htowx<uint32_t>; - fc_cache->pack = vrt::chdr::if_hdr_pack_le; - fc_cache->unpack = vrt::chdr::if_hdr_unpack_le; + fc_cache->pack = vrt::chdr::if_hdr_pack_le; + fc_cache->unpack = vrt::chdr::if_hdr_unpack_le; } - xport.recv = zero_copy_flow_ctrl::make - ( - xport.recv, - NULL, - [fc_cache](managed_buffer::sptr buff) { - return rx_flow_ctrl( - fc_cache, - buff); - } - ); + xport.recv = zero_copy_flow_ctrl::make( + xport.recv, NULL, [fc_cache](managed_buffer::sptr buff) { + return rx_flow_ctrl(fc_cache, buff); + }); // Configure the block // Note: We need to set_destination() after writing to SR_CLEAR_TX_FC. @@ -406,36 +393,41 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t &args_) blk_ctrl->set_destination(xport.send_sid.get_src(), block_port); // Configure routing for responses - blk_ctrl->sr_write(uhd::rfnoc::SR_RESP_OUT_DST_SID, xport.send_sid.get_src(), block_port); - UHD_RX_STREAMER_LOG() << "resp_out_dst_sid == " << xport.send_sid.get_src() ; + blk_ctrl->sr_write( + uhd::rfnoc::SR_RESP_OUT_DST_SID, xport.send_sid.get_src(), block_port); + UHD_RX_STREAMER_LOG() << "resp_out_dst_sid == " << xport.send_sid.get_src(); // Find all upstream radio nodes and set their response in SID to the host - std::vector<boost::shared_ptr<uhd::rfnoc::radio_ctrl> > upstream_radio_nodes = blk_ctrl->find_upstream_node<uhd::rfnoc::radio_ctrl>(); - UHD_RX_STREAMER_LOG() << "Number of upstream radio nodes: " << upstream_radio_nodes.size(); - for(const boost::shared_ptr<uhd::rfnoc::radio_ctrl> &node: upstream_radio_nodes) { - node->sr_write(uhd::rfnoc::SR_RESP_OUT_DST_SID, xport.send_sid.get_src(), block_port); + std::vector<boost::shared_ptr<uhd::rfnoc::radio_ctrl>> upstream_radio_nodes = + blk_ctrl->find_upstream_node<uhd::rfnoc::radio_ctrl>(); + UHD_RX_STREAMER_LOG() << "Number of upstream radio nodes: " + << upstream_radio_nodes.size(); + for (const boost::shared_ptr<uhd::rfnoc::radio_ctrl>& node : + upstream_radio_nodes) { + node->sr_write( + uhd::rfnoc::SR_RESP_OUT_DST_SID, xport.send_sid.get_src(), block_port); } // Second, configure the streamer - //make the new streamer given the samples per packet - if (not my_streamer) - { - // To calculate the max number of samples per packet, we assume the maximum header length - // to avoid fragmentation should the entire header be used. - const size_t bpp = pkt_size - stream_options.rx_max_len_hdr; // bytes per packet - const size_t bpi = convert::get_bytes_per_item(args.otw_format); // bytes per item - const size_t spp = std::min(args.args.cast<size_t>("spp", bpp/bpi), bpp/bpi); // samples per packet - UHD_RX_STREAMER_LOG() << "spp == " << spp ; + // make the new streamer given the samples per packet + if (not my_streamer) { + // To calculate the max number of samples per packet, we assume the maximum + // header length to avoid fragmentation should the entire header be used. + const size_t bpp = + pkt_size - stream_options.rx_max_len_hdr; // bytes per packet + const size_t bpi = + convert::get_bytes_per_item(args.otw_format); // bytes per item + const size_t spp = std::min(args.args.cast<size_t>("spp", bpp / bpi), + bpp / bpi); // samples per packet + UHD_RX_STREAMER_LOG() << "spp == " << spp; my_streamer = boost::make_shared<device3_recv_packet_streamer>( - spp, - recv_terminator, - xport); + spp, recv_terminator, xport); my_streamer->resize(chan_list.size()); } - //init some streamer stuff + // init some streamer stuff std::string conv_endianness; if (xport.endianness == ENDIANNESS_BIG) { my_streamer->set_vrt_unpacker(&vrt::chdr::if_hdr_unpack_be); @@ -445,63 +437,51 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t &args_) conv_endianness = "le"; } - //set the converter + // set the converter uhd::convert::id_type id; - id.input_format = args.otw_format + "_item32_" + conv_endianness; - id.num_inputs = 1; + id.input_format = args.otw_format + "_item32_" + conv_endianness; + id.num_inputs = 1; id.output_format = args.cpu_format; - id.num_outputs = 1; + id.num_outputs = 1; my_streamer->set_converter(id); // Give the streamer a functor to handle flow control ACK messages my_streamer->set_xport_handle_flowctrl_ack( - stream_i, - [fc_cache](const uint32_t *payload) { - handle_rx_flowctrl_ack( - fc_cache, - payload - ); - } - ); + stream_i, [fc_cache](const uint32_t* payload) { + handle_rx_flowctrl_ack(fc_cache, payload); + }); - //Give the streamer a functor to get the recv_buffer - my_streamer->set_xport_chan_get_buff( - stream_i, - [xport](double timeout) { - return xport.recv->get_recv_buff(timeout); - }, + // Give the streamer a functor to get the recv_buffer + my_streamer->set_xport_chan_get_buff(stream_i, + [xport](double timeout) { return xport.recv->get_recv_buff(timeout); }, true /*flush*/ ); - //Give the streamer a functor to handle overruns - //bind requires a weak_ptr to break the a streamer->streamer circular dependency - //Using "this" is OK because we know that this device3_impl will outlive the streamer + // Give the streamer a functor to handle overruns + // bind requires a weak_ptr to break the a streamer->streamer circular dependency + // Using "this" is OK because we know that this device3_impl will outlive the + // streamer boost::weak_ptr<uhd::rx_streamer> weak_ptr(my_streamer); my_streamer->set_overflow_handler( - stream_i, - [recv_terminator, weak_ptr, stream_i]() { - recv_terminator->handle_overrun( - weak_ptr, - stream_i); - } - ); + stream_i, [recv_terminator, weak_ptr, stream_i]() { + recv_terminator->handle_overrun(weak_ptr, stream_i); + }); - //Give the streamer a functor issue stream cmd + // Give the streamer a functor issue stream cmd my_streamer->set_issue_stream_cmd( - stream_i, - [blk_ctrl, block_port](const stream_cmd_t& stream_cmd) { + stream_i, [blk_ctrl, block_port](const stream_cmd_t& stream_cmd) { blk_ctrl->issue_stream_cmd(stream_cmd, block_port); - } - ); + }); } // Notify all blocks in this chain that they are connected to an active streamer recv_terminator->set_rx_streamer(true, 0); - // Store a weak pointer to prevent a streamer->device3_impl->streamer circular dependency. - // Note that we store the streamer only once, and use its terminator's - // ID to do so. - _rx_streamers[recv_terminator->unique_id()] = boost::weak_ptr<uhd::rx_streamer>(my_streamer); + // Store a weak pointer to prevent a streamer->device3_impl->streamer circular + // dependency. Note that we store the streamer only once, and use its terminator's ID + // to do so. + _rx_streamers[recv_terminator->unique_id()] = + boost::weak_ptr<uhd::rx_streamer>(my_streamer); // Sets tick rate, samp rate and scaling on this streamer. // A registered terminator is required to do this. @@ -516,10 +496,11 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t &args_) **********************************************************************/ void device3_impl::update_tx_streamers(double /* rate */) { - for(const std::string &block_id: _tx_streamers.keys()) { + for (const std::string& block_id : _tx_streamers.keys()) { UHD_TX_STREAMER_LOG() << "updating TX streamer: " << block_id; boost::shared_ptr<device3_send_packet_streamer> my_streamer = - boost::dynamic_pointer_cast<device3_send_packet_streamer>(_tx_streamers[block_id].lock()); + boost::dynamic_pointer_cast<device3_send_packet_streamer>( + _tx_streamers[block_id].lock()); if (my_streamer) { double tick_rate = my_streamer->get_terminator()->get_tick_rate(); if (tick_rate == rfnoc::tick_node_ctrl::RATE_UNDEFINED) { @@ -533,7 +514,9 @@ void device3_impl::update_tx_streamers(double /* rate */) if (scaling == rfnoc::scalar_node_ctrl::SCALE_UNDEFINED) { scaling = 32767.; } - UHD_TX_STREAMER_LOG() << "New tick_rate == " << tick_rate << " New samp_rate == " << samp_rate << " New scaling == " << scaling ; + UHD_TX_STREAMER_LOG() + << "New tick_rate == " << tick_rate << " New samp_rate == " << samp_rate + << " New scaling == " << scaling; my_streamer->set_tick_rate(tick_rate); my_streamer->set_samp_rate(samp_rate); my_streamer->set_scale_factor(scaling); @@ -541,7 +524,7 @@ void device3_impl::update_tx_streamers(double /* rate */) } } -tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t &args_) +tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t& args_) { boost::mutex::scoped_lock lock(_transport_setup_mutex); stream_args_t args = sanitize_stream_args(args_); @@ -552,108 +535,111 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t &args_) generate_channel_list(args, chan_list, chan_args); // Note: All 'args.args' are merged into chan_args now. - //shared async queue for all channels in streamer - boost::shared_ptr<async_md_type> async_md(new async_md_type(1000/*messages deep*/)); + // shared async queue for all channels in streamer + boost::shared_ptr<async_md_type> async_md(new async_md_type(1000 /*messages deep*/)); // II. Iterate over all channels boost::shared_ptr<device3_send_packet_streamer> my_streamer; // The terminator's lifetime is coupled to the streamer. // There is only one terminator. If the streamer has multiple channels, // it will be connected to each downstream block. - rfnoc::tx_stream_terminator::sptr send_terminator = rfnoc::tx_stream_terminator::make(); - for (size_t stream_i = 0; stream_i < chan_list.size(); stream_i++) - { + rfnoc::tx_stream_terminator::sptr send_terminator = + rfnoc::tx_stream_terminator::make(); + for (size_t stream_i = 0; stream_i < chan_list.size(); stream_i++) { // First, configure the downstream blocks and create the transports // Get block ID and mb index uhd::rfnoc::block_id_t block_id = chan_list[stream_i]; // Update args so args.args is always valid for this particular channel: - args.args = chan_args[stream_i]; + args.args = chan_args[stream_i]; size_t mb_index = block_id.get_device_no(); - size_t suggested_block_port = args.args.cast<size_t>("block_port", rfnoc::ANY_PORT); + size_t suggested_block_port = + args.args.cast<size_t>("block_port", rfnoc::ANY_PORT); // Access to this channel's block control uhd::rfnoc::sink_block_ctrl_base::sptr blk_ctrl = - boost::dynamic_pointer_cast<uhd::rfnoc::sink_block_ctrl_base>(get_block_ctrl(block_id)); + boost::dynamic_pointer_cast<uhd::rfnoc::sink_block_ctrl_base>( + get_block_ctrl(block_id)); // Connect the terminator with this channel's block. // This will throw if the connection is not possible. - size_t block_port = blk_ctrl->connect_upstream( - send_terminator, - suggested_block_port, - args.args - ); + size_t block_port = + blk_ctrl->connect_upstream(send_terminator, suggested_block_port, args.args); const size_t terminator_port = send_terminator->connect_downstream(blk_ctrl); blk_ctrl->set_upstream_port(block_port, terminator_port); send_terminator->set_downstream_port(terminator_port, block_port); // Check if the block connection is compatible (spp and item type) - check_stream_sig_compatible(blk_ctrl->get_input_signature(block_port), args, "TX"); + check_stream_sig_compatible( + blk_ctrl->get_input_signature(block_port), args, "TX"); // Setup the dsp transport hints device_addr_t tx_hints = get_tx_hints(mb_index); const size_t fifo_size = blk_ctrl->get_fifo_size(block_port); // Allocate sid and create transport uhd::sid_t stream_address = blk_ctrl->get_address(block_port); - UHD_TX_STREAMER_LOG() << "creating tx stream " << tx_hints.to_string() ; + UHD_TX_STREAMER_LOG() << "creating tx stream " << tx_hints.to_string(); both_xports_t xport = make_transport(stream_address, TX_DATA, tx_hints); - both_xports_t async_xport = make_transport(stream_address, ASYNC_MSG, device_addr_t("")); - UHD_TX_STREAMER_LOG() << std::hex << "data_sid = " << xport.send_sid << std::dec ; + both_xports_t async_xport = + make_transport(stream_address, ASYNC_MSG, device_addr_t("")); + UHD_TX_STREAMER_LOG() << std::hex << "data_sid = " << xport.send_sid << std::dec; // Configure flow control // This disables the FC module's output, do this before configuring flow control blk_ctrl->sr_write(uhd::rfnoc::SR_CLEAR_RX_FC, 0x1, block_port); blk_ctrl->sr_write(uhd::rfnoc::SR_CLEAR_RX_FC, 0x0, block_port); // Configure flow control on downstream block - const size_t fc_window = std::min(tx_hints.cast<size_t>("send_buff_size", fifo_size), fifo_size); - const size_t fc_handle_window = std::max<size_t>(1, fc_window / stream_options.tx_fc_response_freq); - UHD_TX_STREAMER_LOG() << "Flow Control Window = " << fc_window << ", Flow Control Handler Window = " << fc_handle_window ; - blk_ctrl->configure_flow_control_in( - fc_handle_window, /*bytes*/ - block_port - ); + const size_t fc_window = + std::min(tx_hints.cast<size_t>("send_buff_size", fifo_size), fifo_size); + const size_t fc_handle_window = + std::max<size_t>(1, fc_window / stream_options.tx_fc_response_freq); + UHD_TX_STREAMER_LOG() << "Flow Control Window = " << fc_window + << ", Flow Control Handler Window = " << fc_handle_window; + blk_ctrl->configure_flow_control_in(fc_handle_window, /*bytes*/ + block_port); // Add flow control transport boost::shared_ptr<tx_fc_cache_t> fc_cache(new tx_fc_cache_t(fc_window)); - if (xport.endianness == ENDIANNESS_BIG) - { - fc_cache->to_host = uhd::ntohx<uint32_t>; + if (xport.endianness == ENDIANNESS_BIG) { + fc_cache->to_host = uhd::ntohx<uint32_t>; fc_cache->from_host = uhd::htonx<uint32_t>; - fc_cache->pack = vrt::chdr::if_hdr_pack_be; - fc_cache->unpack = vrt::chdr::if_hdr_unpack_be; + fc_cache->pack = vrt::chdr::if_hdr_pack_be; + fc_cache->unpack = vrt::chdr::if_hdr_unpack_be; } else { - fc_cache->to_host = uhd::wtohx<uint32_t>; + fc_cache->to_host = uhd::wtohx<uint32_t>; fc_cache->from_host = uhd::htowx<uint32_t>; - fc_cache->pack = vrt::chdr::if_hdr_pack_le; - fc_cache->unpack = vrt::chdr::if_hdr_unpack_le; + fc_cache->pack = vrt::chdr::if_hdr_pack_le; + fc_cache->unpack = vrt::chdr::if_hdr_unpack_le; } - xport.send = zero_copy_flow_ctrl::make( - xport.send, + xport.send = zero_copy_flow_ctrl::make(xport.send, [fc_cache, xport](managed_buffer::sptr buff) { - return tx_flow_ctrl( - fc_cache, - xport.recv, - buff); + return tx_flow_ctrl(fc_cache, xport.recv, buff); }, - NULL - ); + NULL); // Configure return path for async messages - blk_ctrl->sr_write(uhd::rfnoc::SR_RESP_IN_DST_SID, async_xport.recv_sid.get_dst(), block_port); - UHD_TX_STREAMER_LOG() << "resp_in_dst_sid == " << boost::format("0x%04X") % xport.recv_sid.get_dst() ; + blk_ctrl->sr_write( + uhd::rfnoc::SR_RESP_IN_DST_SID, async_xport.recv_sid.get_dst(), block_port); + UHD_TX_STREAMER_LOG() << "resp_in_dst_sid == " + << boost::format("0x%04X") % xport.recv_sid.get_dst(); // FIXME: Once there is a better way to map the radio block and port // to the channel or another way to receive asynchronous messages that // is not in-band, this should be removed. - if (args.args.has_key("radio_id") and args.args.has_key("radio_port")) - { + if (args.args.has_key("radio_id") and args.args.has_key("radio_port")) { // Find downstream radio node and set the response SID to the host uhd::rfnoc::block_id_t radio_id(args.args["radio_id"]); size_t radio_port = args.args.cast<size_t>("radio_port", 0); - std::vector<boost::shared_ptr<uhd::rfnoc::radio_ctrl> > downstream_radio_nodes = blk_ctrl->find_downstream_node<uhd::rfnoc::radio_ctrl>(); - UHD_TX_STREAMER_LOG() << "Number of downstream radio nodes: " << downstream_radio_nodes.size(); - for(const boost::shared_ptr<uhd::rfnoc::radio_ctrl> &node: downstream_radio_nodes) { + std::vector<boost::shared_ptr<uhd::rfnoc::radio_ctrl>> + downstream_radio_nodes = + blk_ctrl->find_downstream_node<uhd::rfnoc::radio_ctrl>(); + UHD_TX_STREAMER_LOG() + << "Number of downstream radio nodes: " << downstream_radio_nodes.size(); + for (const boost::shared_ptr<uhd::rfnoc::radio_ctrl>& node : + downstream_radio_nodes) { if (node->get_block_id() == radio_id) { - node->sr_write(uhd::rfnoc::SR_RESP_IN_DST_SID, async_xport.recv_sid.get_dst(), radio_port); + node->sr_write(uhd::rfnoc::SR_RESP_IN_DST_SID, + async_xport.recv_sid.get_dst(), + radio_port); } } } else { @@ -663,34 +649,41 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t &args_) // is not the same as the block_port. It should be removed as // soon as possible. // Find all downstream radio nodes and set their response SID to the host - std::vector<boost::shared_ptr<uhd::rfnoc::radio_ctrl> > downstream_radio_nodes = blk_ctrl->find_downstream_node<uhd::rfnoc::radio_ctrl>(); - UHD_TX_STREAMER_LOG() << "Number of downstream radio nodes: " << downstream_radio_nodes.size(); - for(const boost::shared_ptr<uhd::rfnoc::radio_ctrl> &node: downstream_radio_nodes) { - node->sr_write(uhd::rfnoc::SR_RESP_IN_DST_SID, async_xport.recv_sid.get_dst(), block_port); + std::vector<boost::shared_ptr<uhd::rfnoc::radio_ctrl>> + downstream_radio_nodes = + blk_ctrl->find_downstream_node<uhd::rfnoc::radio_ctrl>(); + UHD_TX_STREAMER_LOG() + << "Number of downstream radio nodes: " << downstream_radio_nodes.size(); + for (const boost::shared_ptr<uhd::rfnoc::radio_ctrl>& node : + downstream_radio_nodes) { + node->sr_write(uhd::rfnoc::SR_RESP_IN_DST_SID, + async_xport.recv_sid.get_dst(), + block_port); } } - // Second, configure the streamer now that the blocks and transports are configured - - //make the new streamer given the samples per packet - if (not my_streamer) - { - // To calculate the max number of samples per packet, we assume the maximum header length - // to avoid fragmentation should the entire header be used. - const size_t bpp = tx_hints.cast<size_t>("bpp", xport.send->get_send_frame_size()) - stream_options.tx_max_len_hdr; - const size_t bpi = convert::get_bytes_per_item(args.otw_format); // bytes per item - const size_t spp = std::min(args.args.cast<size_t>("spp", bpp/bpi), bpp/bpi); // samples per packet - UHD_TX_STREAMER_LOG() << "spp == " << spp ; + // Second, configure the streamer now that the blocks and transports are + // configured + + // make the new streamer given the samples per packet + if (not my_streamer) { + // To calculate the max number of samples per packet, we assume the maximum + // header length to avoid fragmentation should the entire header be used. + const size_t bpp = + tx_hints.cast<size_t>("bpp", xport.send->get_send_frame_size()) + - stream_options.tx_max_len_hdr; + const size_t bpi = + convert::get_bytes_per_item(args.otw_format); // bytes per item + const size_t spp = std::min(args.args.cast<size_t>("spp", bpp / bpi), + bpp / bpi); // samples per packet + UHD_TX_STREAMER_LOG() << "spp == " << spp; my_streamer = boost::make_shared<device3_send_packet_streamer>( - spp, - send_terminator, - xport, - async_xport); + spp, send_terminator, xport, async_xport); my_streamer->resize(chan_list.size()); } - //init some streamer stuff + // init some streamer stuff std::string conv_endianness; if (xport.endianness == ENDIANNESS_BIG) { my_streamer->set_vrt_packer(&vrt::chdr::if_hdr_pack_be); @@ -700,69 +693,57 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t &args_) conv_endianness = "le"; } - //set the converter + // set the converter uhd::convert::id_type id; - id.input_format = args.cpu_format; - id.num_inputs = 1; + id.input_format = args.cpu_format; + id.num_inputs = 1; id.output_format = args.otw_format + "_item32_" + conv_endianness; - id.num_outputs = 1; + id.num_outputs = 1; my_streamer->set_converter(id); boost::shared_ptr<async_tx_info_t> async_tx_info(new async_tx_info_t()); - async_tx_info->stream_channel = args.channels[stream_i]; - async_tx_info->device_channel = mb_index; - async_tx_info->async_queue = async_md; + async_tx_info->stream_channel = args.channels[stream_i]; + async_tx_info->device_channel = mb_index; + async_tx_info->async_queue = async_md; async_tx_info->old_async_queue = _async_md; - task::sptr async_task = task::make( - [async_tx_info, async_xport, xport, send_terminator]() { - handle_tx_async_msgs( - async_tx_info, - async_xport.recv, - xport.endianness == ENDIANNESS_BIG ? uhd::ntohx<uint32_t> : uhd::wtohx<uint32_t>, - xport.endianness == ENDIANNESS_BIG ? vrt::chdr::if_hdr_unpack_be : vrt::chdr::if_hdr_unpack_le, - [send_terminator]() {return send_terminator->get_tick_rate();} - ); - } - ); + task::sptr async_task = + task::make([async_tx_info, async_xport, xport, send_terminator]() { + handle_tx_async_msgs(async_tx_info, + async_xport.recv, + xport.endianness == ENDIANNESS_BIG ? uhd::ntohx<uint32_t> + : uhd::wtohx<uint32_t>, + xport.endianness == ENDIANNESS_BIG ? vrt::chdr::if_hdr_unpack_be + : vrt::chdr::if_hdr_unpack_le, + [send_terminator]() { return send_terminator->get_tick_rate(); }); + }); my_streamer->add_async_msg_task(async_task); - //Give the streamer a functor to get the send buffer - my_streamer->set_xport_chan_get_buff( - stream_i, - [xport](const double timeout) { - return xport.send->get_send_buff(timeout); - } - ); - //Give the streamer a functor handled received async messages + // Give the streamer a functor to get the send buffer + my_streamer->set_xport_chan_get_buff(stream_i, + [xport](const double timeout) { return xport.send->get_send_buff(timeout); }); + // Give the streamer a functor handled received async messages my_streamer->set_async_receiver( [async_md](uhd::async_metadata_t& md, const double timeout) { return async_md->pop_with_timed_wait(md, timeout); - } - ); + }); my_streamer->set_xport_chan_sid(stream_i, true, xport.send_sid); // CHDR does not support trailers my_streamer->set_enable_trailer(false); - my_streamer->set_xport_chan_post_send_cb( - stream_i, - [fc_cache, xport]() { - tx_flow_ctrl_ack( - fc_cache, - xport.send, - xport.send_sid - ); - } - ); + my_streamer->set_xport_chan_post_send_cb(stream_i, [fc_cache, xport]() { + tx_flow_ctrl_ack(fc_cache, xport.send, xport.send_sid); + }); } // Notify all blocks in this chain that they are connected to an active streamer send_terminator->set_tx_streamer(true, 0); - // Store a weak pointer to prevent a streamer->device3_impl->streamer circular dependency. - // Note that we store the streamer only once, and use its terminator's - // ID to do so. - _tx_streamers[send_terminator->unique_id()] = boost::weak_ptr<uhd::tx_streamer>(my_streamer); + // Store a weak pointer to prevent a streamer->device3_impl->streamer circular + // dependency. Note that we store the streamer only once, and use its terminator's ID + // to do so. + _tx_streamers[send_terminator->unique_id()] = + boost::weak_ptr<uhd::tx_streamer>(my_streamer); // Sets tick rate, samp rate and scaling on this streamer // A registered terminator is required to do this. @@ -771,5 +752,3 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t &args_) post_streamer_hooks(TX_DIRECTION); return my_streamer; } - - diff --git a/host/lib/usrp/mpmd/mpmd_devices.hpp b/host/lib/usrp/mpmd/mpmd_devices.hpp index ab0cc1271..9cc046037 100644 --- a/host/lib/usrp/mpmd/mpmd_devices.hpp +++ b/host/lib/usrp/mpmd/mpmd_devices.hpp @@ -8,8 +8,8 @@ #ifndef INCLUDED_MPMD_DEVICES_HPP #define INCLUDED_MPMD_DEVICES_HPP -#include <vector> #include <string> +#include <vector> static constexpr char MPM_CATCHALL_DEVICE_TYPE[] = "mpm"; diff --git a/host/lib/usrp/mpmd/mpmd_find.cpp b/host/lib/usrp/mpmd/mpmd_find.cpp index 26230e396..5d2406b30 100644 --- a/host/lib/usrp/mpmd/mpmd_find.cpp +++ b/host/lib/usrp/mpmd/mpmd_find.cpp @@ -6,11 +6,11 @@ // find-related code for MPM devices -#include "mpmd_impl.hpp" #include "mpmd_devices.hpp" -#include <uhd/types/device_addr.hpp> -#include <uhd/transport/udp_simple.hpp> +#include "mpmd_impl.hpp" #include <uhd/transport/if_addrs.hpp> +#include <uhd/transport/udp_simple.hpp> +#include <uhd/types/device_addr.hpp> #include <boost/algorithm/string.hpp> #include <boost/asio.hpp> #include <future> @@ -19,60 +19,50 @@ using namespace uhd; using namespace uhd::mpmd; namespace { - //! How long we wait for discovery responses (in seconds) - constexpr double MPMD_FIND_TIMEOUT = 0.5; - constexpr char MPMD_CHDR_REACHABILITY_KEY[] = "reachable"; - constexpr char MPMD_CHDR_REACHABILITY_NEGATIVE[] = "No"; - //! The preamble for any response on the discovery port. Can be used to - // verify that the response is actually an MPM device. - constexpr char MPM_DISC_RESPONSE_PREAMBLE[] = "USRP-MPM"; - - device_addr_t flag_dev_as_unreachable(const device_addr_t& device_args) - { - device_addr_t flagged_device_args(device_args); - flagged_device_args[MPMD_CHDR_REACHABILITY_KEY] = - MPMD_CHDR_REACHABILITY_NEGATIVE; - return flagged_device_args; - } +//! How long we wait for discovery responses (in seconds) +constexpr double MPMD_FIND_TIMEOUT = 0.5; +constexpr char MPMD_CHDR_REACHABILITY_KEY[] = "reachable"; +constexpr char MPMD_CHDR_REACHABILITY_NEGATIVE[] = "No"; +//! The preamble for any response on the discovery port. Can be used to +// verify that the response is actually an MPM device. +constexpr char MPM_DISC_RESPONSE_PREAMBLE[] = "USRP-MPM"; + +device_addr_t flag_dev_as_unreachable(const device_addr_t& device_args) +{ + device_addr_t flagged_device_args(device_args); + flagged_device_args[MPMD_CHDR_REACHABILITY_KEY] = MPMD_CHDR_REACHABILITY_NEGATIVE; + return flagged_device_args; } +} // namespace device_addrs_t mpmd_find_with_addr( - const std::string& mgmt_addr, - const device_addr_t& hint_ -) { + const std::string& mgmt_addr, const device_addr_t& hint_) +{ UHD_ASSERT_THROW(not mgmt_addr.empty()); const std::string mpm_discovery_port = hint_.get( - mpmd_impl::MPM_DISCOVERY_PORT_KEY, - std::to_string(mpmd_impl::MPM_DISCOVERY_PORT) - ); - UHD_LOG_DEBUG("MPMD", - "Discovering MPM devices on port " << mpm_discovery_port); + mpmd_impl::MPM_DISCOVERY_PORT_KEY, std::to_string(mpmd_impl::MPM_DISCOVERY_PORT)); + UHD_LOG_DEBUG("MPMD", "Discovering MPM devices on port " << mpm_discovery_port); device_addrs_t addrs; - transport::udp_simple::sptr comm = transport::udp_simple::make_broadcast( - mgmt_addr, mpm_discovery_port); - comm->send( - boost::asio::buffer( - mpmd_impl::MPM_DISCOVERY_CMD.c_str(), - mpmd_impl::MPM_DISCOVERY_CMD.size() - ) - ); + transport::udp_simple::sptr comm = + transport::udp_simple::make_broadcast(mgmt_addr, mpm_discovery_port); + comm->send(boost::asio::buffer( + mpmd_impl::MPM_DISCOVERY_CMD.c_str(), mpmd_impl::MPM_DISCOVERY_CMD.size())); while (true) { const size_t MAX_MTU = 8000; - char buff[MAX_MTU] = {}; - const size_t nbytes = comm->recv( - boost::asio::buffer(buff, MAX_MTU), - MPMD_FIND_TIMEOUT - ); + char buff[MAX_MTU] = {}; + const size_t nbytes = + comm->recv(boost::asio::buffer(buff, MAX_MTU), MPMD_FIND_TIMEOUT); if (nbytes == 0) { break; } - const char* reply = (const char*)buff; + const char* reply = (const char*)buff; std::string reply_string = std::string(reply); std::vector<std::string> result; - boost::algorithm::split(result, reply_string, - [](const char& in) { return in == ';'; }, - boost::token_compress_on); + boost::algorithm::split(result, + reply_string, + [](const char& in) { return in == ';'; }, + boost::token_compress_on); if (result.empty()) { continue; } @@ -86,9 +76,8 @@ device_addrs_t mpmd_find_with_addr( // remove external iface addrs if executed directly on device bool external_iface = false; for (const auto& addr : transport::get_if_addrs()) { - if ((addr.inet == comm->get_recv_addr()) && - recv_addr != - boost::asio::ip::address_v4::loopback().to_string()) { + if ((addr.inet == comm->get_recv_addr()) + && recv_addr != boost::asio::ip::address_v4::loopback().to_string()) { external_iface = true; break; } @@ -100,41 +89,40 @@ device_addrs_t mpmd_find_with_addr( // Create result to return device_addr_t new_addr; new_addr[xport::MGMT_ADDR_KEY] = recv_addr; - new_addr["type"] = "mpmd"; // hwd will overwrite this + new_addr["type"] = "mpmd"; // hwd will overwrite this // remove ident string and put other informations into device_args dict result.erase(result.begin()); // parse key-value pairs in the discovery string and add them to the // device_args for (const auto& el : result) { std::vector<std::string> value; - boost::algorithm::split(value, el, - [](const char& in) { return in == '='; }, - boost::token_compress_on); + boost::algorithm::split(value, + el, + [](const char& in) { return in == '='; }, + boost::token_compress_on); if (value[0] != xport::MGMT_ADDR_KEY) { new_addr[value[0]] = value[1]; } } // filter the discovered device below by matching optional keys - if ( - (not hint_.has_key("name") or hint_["name"] == new_addr["name"]) - and (not hint_.has_key("serial") or hint_["serial"] == new_addr["serial"]) - and (not hint_.has_key("type") or hint_["type"] == new_addr["type"] or hint_["type"] == MPM_CATCHALL_DEVICE_TYPE) - and (not hint_.has_key("product") or hint_["product"] == new_addr["product"]) - ){ - UHD_LOG_TRACE("MPMD FIND", - "Found device that matches hints: " << new_addr.to_string()); + if ((not hint_.has_key("name") or hint_["name"] == new_addr["name"]) + and (not hint_.has_key("serial") or hint_["serial"] == new_addr["serial"]) + and (not hint_.has_key("type") or hint_["type"] == new_addr["type"] + or hint_["type"] == MPM_CATCHALL_DEVICE_TYPE) + and (not hint_.has_key("product") + or hint_["product"] == new_addr["product"])) { + UHD_LOG_TRACE( + "MPMD FIND", "Found device that matches hints: " << new_addr.to_string()); addrs.push_back(new_addr); } else { - UHD_LOG_DEBUG("MPMD FIND", - "Found device, but does not match hint: " << recv_addr - ); + UHD_LOG_DEBUG( + "MPMD FIND", "Found device, but does not match hint: " << recv_addr); } } return addrs; }; - // Implements scenario 1) (see below) device_addrs_t mpmd_find_with_addrs(const device_addrs_t& hints) { @@ -142,10 +130,9 @@ device_addrs_t mpmd_find_with_addrs(const device_addrs_t& hints) device_addrs_t found_devices; found_devices.reserve(hints.size()); for (const auto& hint : hints) { - if (not (hint.has_key(xport::FIRST_ADDR_KEY) or - hint.has_key(xport::MGMT_ADDR_KEY))) { - UHD_LOG_DEBUG("MPMD FIND", - "No address given in hint " << hint.to_string()); + if (not(hint.has_key(xport::FIRST_ADDR_KEY) + or hint.has_key(xport::MGMT_ADDR_KEY))) { + UHD_LOG_DEBUG("MPMD FIND", "No address given in hint " << hint.to_string()); continue; } const std::string mgmt_addr = @@ -154,13 +141,12 @@ device_addrs_t mpmd_find_with_addrs(const device_addrs_t& hints) if (reply_addrs.size() > 1) { UHD_LOG_ERROR("MPMD", "Could not resolve device hint \"" << hint.to_string() - << "\" to a unique device."); + << "\" to a unique device."); continue; } else if (reply_addrs.empty()) { continue; } - UHD_LOG_TRACE("MPMD FIND", - "Device responded: " << reply_addrs[0].to_string()); + UHD_LOG_TRACE("MPMD FIND", "Device responded: " << reply_addrs[0].to_string()); found_devices.push_back(reply_addrs[0]); } if (found_devices.size() == 0) { @@ -175,17 +161,14 @@ device_addrs_t mpmd_find_with_addrs(const device_addrs_t& hints) device_addrs_t mpmd_find_with_bcast(const device_addr_t& hint) { device_addrs_t addrs; - UHD_LOG_TRACE("MPMD FIND", - "Broadcasting on all available interfaces to find MPM devices."); + UHD_LOG_TRACE( + "MPMD FIND", "Broadcasting on all available interfaces to find MPM devices."); std::vector<std::future<device_addrs_t>> task_list; for (const auto& if_addr : transport::get_if_addrs()) { task_list.emplace_back(std::async(std::launch::async, - [if_addr, hint](){ - return mpmd_find_with_addr(if_addr.bcast, hint); - } - )); + [if_addr, hint]() { return mpmd_find_with_addr(if_addr.bcast, hint); })); } - for (auto &task : task_list) { + for (auto& task : task_list) { auto reply_addrs = task.get(); addrs.insert(addrs.begin(), reply_addrs.begin(), reply_addrs.end()); } @@ -212,21 +195,19 @@ device_addrs_t mpmd_find(const device_addr_t& hint_) { device_addrs_t hints = separate_device_addr(hint_); if (hint_.has_key("type")) { - if (std::find(MPM_DEVICE_TYPES.cbegin(), - MPM_DEVICE_TYPES.cend(), - hint_["type"]) == MPM_DEVICE_TYPES.cend()) { - UHD_LOG_TRACE("MPMD FIND", - "Returning early, type does not match an MPM device."); + if (std::find(MPM_DEVICE_TYPES.cbegin(), MPM_DEVICE_TYPES.cend(), hint_["type"]) + == MPM_DEVICE_TYPES.cend()) { + UHD_LOG_TRACE( + "MPMD FIND", "Returning early, type does not match an MPM device."); return {}; } } - UHD_LOG_TRACE("MPMD FIND", - "Finding with " << hints.size() << " different hint(s)."); + UHD_LOG_TRACE("MPMD FIND", "Finding with " << hints.size() << " different hint(s)."); // Scenario 1): User gave us at least one address - if (not hints.empty() and - (hints[0].has_key(xport::FIRST_ADDR_KEY) or - hints[0].has_key(xport::MGMT_ADDR_KEY))) { + if (not hints.empty() + and (hints[0].has_key(xport::FIRST_ADDR_KEY) + or hints[0].has_key(xport::MGMT_ADDR_KEY))) { // Note: We don't try and connect to the devices in this mode, because // we only get here if the user specified addresses, and we assume she // knows what she's doing. @@ -238,33 +219,31 @@ device_addrs_t mpmd_find(const device_addr_t& hint_) hints.resize(1); } const auto bcast_mpm_devs = mpmd_find_with_bcast(hints[0]); - UHD_LOG_TRACE("MPMD FIND", - "Found " << bcast_mpm_devs.size() << " device via broadcast."); + UHD_LOG_TRACE( + "MPMD FIND", "Found " << bcast_mpm_devs.size() << " device via broadcast."); const bool find_all = hint_.has_key(mpmd_impl::MPM_FINDALL_KEY); if (find_all) { UHD_LOG_TRACE("MPMD FIND", - "User provided " << mpmd_impl::MPM_FINDALL_KEY << ", will not " - "check devices for CHDR accessibility."); + "User provided " << mpmd_impl::MPM_FINDALL_KEY + << ", will not " + "check devices for CHDR accessibility."); } // Filter found devices for those that we can actually talk to via CHDR device_addrs_t filtered_mpm_devs; - for (const auto &mpm_dev : bcast_mpm_devs) { - const auto reachable_device_addr = - mpmd_mboard_impl::is_device_reachable(mpm_dev); + for (const auto& mpm_dev : bcast_mpm_devs) { + const auto reachable_device_addr = mpmd_mboard_impl::is_device_reachable(mpm_dev); if (bool(reachable_device_addr)) { filtered_mpm_devs.push_back(reachable_device_addr.get()); } else if (find_all) { - filtered_mpm_devs.emplace_back( - flag_dev_as_unreachable(mpm_dev) - ); + filtered_mpm_devs.emplace_back(flag_dev_as_unreachable(mpm_dev)); } } if (filtered_mpm_devs.empty() and not bcast_mpm_devs.empty()) { UHD_LOG_INFO("MPMD FIND", "Found MPM devices, but none are reachable for a UHD session. " - "Specify " << mpmd_impl::MPM_FINDALL_KEY << " to find all devices." - ); + "Specify " + << mpmd_impl::MPM_FINDALL_KEY << " to find all devices."); } return filtered_mpm_devs; diff --git a/host/lib/usrp/mpmd/mpmd_image_loader.cpp b/host/lib/usrp/mpmd/mpmd_image_loader.cpp index e0b85f897..7553b1df4 100644 --- a/host/lib/usrp/mpmd/mpmd_image_loader.cpp +++ b/host/lib/usrp/mpmd/mpmd_image_loader.cpp @@ -7,66 +7,68 @@ #include "mpmd_impl.hpp" #include <uhd/config.hpp> #include <uhd/device.hpp> -#include <uhd/image_loader.hpp> #include <uhd/exception.hpp> -#include <uhd/types/eeprom.hpp> +#include <uhd/image_loader.hpp> #include <uhd/types/component_file.hpp> +#include <uhd/types/eeprom.hpp> #include <uhd/utils/paths.hpp> #include <boost/algorithm/string.hpp> #include <boost/filesystem/convenience.hpp> -#include <sstream> -#include <string> #include <fstream> #include <iterator> +#include <sstream> #include <streambuf> +#include <string> using namespace uhd; -namespace uhd{ namespace /*anon*/{ - const size_t MD5LEN = 32; // Length of a MD5 hash in chars +namespace uhd { namespace /*anon*/ { +const size_t MD5LEN = 32; // Length of a MD5 hash in chars /* * Helper function to generate a component_file_t using the input ID and path to file. */ uhd::usrp::component_file_t generate_component( - const std::string& id, - const std::string& filepath -) { + const std::string& id, const std::string& filepath) +{ uhd::usrp::component_file_t component_file; // Add an ID to the metadata component_file.metadata["id"] = id; - UHD_LOG_TRACE("MPMD IMAGE LOADER", - "Component ID added to the component dictionary: " << id); + UHD_LOG_TRACE( + "MPMD IMAGE LOADER", "Component ID added to the component dictionary: " << id); // Add the filename to the metadata // Remove the path to the filename - component_file.metadata["filename"] = boost::filesystem::path(filepath).filename().string(); + component_file.metadata["filename"] = + boost::filesystem::path(filepath).filename().string(); UHD_LOG_TRACE("MPMD IMAGE LOADER", - "Component filename added to the component dictionary: " << filepath); + "Component filename added to the component dictionary: " << filepath); // Add the hash, if a hash file exists const std::string component_hash_filepath = filepath + ".md5"; - std::ifstream component_hash_ifstream(component_hash_filepath.c_str(), std::ios::binary); + std::ifstream component_hash_ifstream( + component_hash_filepath.c_str(), std::ios::binary); std::string component_hash; if (component_hash_ifstream.is_open()) { // TODO: Verify that the hash read is valid, ie only contains 0-9a-f. component_hash.resize(MD5LEN); - component_hash_ifstream.read( &component_hash[0], MD5LEN ); + component_hash_ifstream.read(&component_hash[0], MD5LEN); component_hash_ifstream.close(); component_file.metadata["md5"] = component_hash; UHD_LOG_TRACE("MPMD IMAGE LOADER", - "Added component file hash to the component dictionary."); + "Added component file hash to the component dictionary."); } else { // If there is no hash file, don't worry about it too much - UHD_LOG_DEBUG("MPMD IMAGE LOADER", "Could not open component file hash file: " - << component_hash_filepath); + UHD_LOG_DEBUG("MPMD IMAGE LOADER", + "Could not open component file hash file: " << component_hash_filepath); } - // Read the component file image into a structure suitable to sent as a binary string to MPM + // Read the component file image into a structure suitable to sent as a binary string + // to MPM std::vector<uint8_t> data; std::ifstream component_ifstream(filepath.c_str(), std::ios::binary); if (component_ifstream.is_open()) { - data.insert( data.begin(), - std::istreambuf_iterator<char>(component_ifstream), - std::istreambuf_iterator<char>()); + data.insert(data.begin(), + std::istreambuf_iterator<char>(component_ifstream), + std::istreambuf_iterator<char>()); component_ifstream.close(); } else { const std::string err_msg("Component file does not exist: " + filepath); @@ -79,7 +81,8 @@ uhd::usrp::component_file_t generate_component( /* * Function to be registered with uhd_image_loader */ -static bool mpmd_image_loader(const image_loader::image_loader_args_t &image_loader_args){ +static bool mpmd_image_loader(const image_loader::image_loader_args_t& image_loader_args) +{ // See if any MPM devices with the given args are found device_addr_t find_hint = image_loader_args.args; find_hint.set("find_all", "1"); // We need to find all devices @@ -94,7 +97,7 @@ static bool mpmd_image_loader(const image_loader::image_loader_args_t &image_loa device_addr_t dev_addr(devs[0]); dev_addr["skip_init"] = "1"; // Make the device - uhd::device::sptr usrp = uhd::device::make(dev_addr, uhd::device::USRP); + uhd::device::sptr usrp = uhd::device::make(dev_addr, uhd::device::USRP); uhd::property_tree::sptr tree = usrp->get_tree(); // Generate the component files @@ -107,44 +110,44 @@ static bool mpmd_image_loader(const image_loader::image_loader_args_t &image_loa if (boost::filesystem::exists(image_loader_args.fpga_path)) { return image_loader_args.fpga_path; } else { - throw uhd::runtime_error(str( - boost::format("FPGA file provided does not exist: %s") - % image_loader_args.fpga_path - )); + throw uhd::runtime_error( + str(boost::format("FPGA file provided does not exist: %s") + % image_loader_args.fpga_path)); } } // Otherwise, we need to generate one else { /* - * The user can specify an FPGA type (HG, XG, AA), rather than a filename. If the user - * does not specify one, this will default to the type currently on the device. If this - * cannot be determined, then the user is forced to specify a filename. - */ + * The user can specify an FPGA type (HG, XG, AA), rather than a filename. If + * the user does not specify one, this will default to the type currently on + * the device. If this cannot be determined, then the user is forced to + * specify a filename. + */ const auto fpga_type = [image_loader_args, tree]() -> std::string { - // If the user didn't provide a type, use the type of currently loaded image on - // the device + // If the user didn't provide a type, use the type of currently loaded + // image on the device if (image_loader_args.args.has_key("fpga")) { return image_loader_args.args.get("fpga"); } else if (tree->exists("/mboards/0/components/fpga")) { - // Pull the FPGA info from the property tree - // The getter should return a vector of a single component_file_t, - // so grab the metadata from that - auto fpga_metadata = - tree->access<uhd::usrp::component_files_t>( - "/mboards/0/components/fpga").get()[0].metadata; - return fpga_metadata.get("type", ""); - // TODO: Do we want to pull the type from the filename if its not - // available in the metadata directly? + // Pull the FPGA info from the property tree + // The getter should return a vector of a single component_file_t, + // so grab the metadata from that + auto fpga_metadata = tree->access<uhd::usrp::component_files_t>( + "/mboards/0/components/fpga") + .get()[0] + .metadata; + return fpga_metadata.get("type", ""); + // TODO: Do we want to pull the type from the filename if its not + // available in the metadata directly? } return ""; }(); // generate_fpga_type lambda function UHD_LOG_TRACE("MPMD IMAGE LOADER", "FPGA type: " << fpga_type); - if(!dev_addr.has_key("product") or fpga_type == ""){ + if (!dev_addr.has_key("product") or fpga_type == "") { throw uhd::runtime_error( - "Found a device but could not auto-generate an image filename."); - } - else { + "Found a device but could not auto-generate an image filename."); + } else { return find_image_path( str(boost::format("usrp_%s_fpga_%s.bit") % (boost::algorithm::to_lower_copy(dev_addr["product"])) @@ -157,9 +160,11 @@ static bool mpmd_image_loader(const image_loader::image_loader_args_t &image_loa all_component_files.push_back(comp_fpga); // DTS component struct // First, we need to determine the name - const std::string base_name = boost::filesystem::change_extension(fpga_path, "").string(); + const std::string base_name = + boost::filesystem::change_extension(fpga_path, "").string(); if (base_name == fpga_path) { - const std::string err_msg("Can't cut extension from FPGA filename... " + fpga_path); + const std::string err_msg( + "Can't cut extension from FPGA filename... " + fpga_path); throw uhd::runtime_error(err_msg); } const std::string dts_path = base_name + ".dts"; @@ -176,20 +181,24 @@ static bool mpmd_image_loader(const image_loader::image_loader_args_t &image_loa // Call RPC to update the component UHD_LOG_INFO("MPMD IMAGE LOADER", "Starting update. This may take a while."); - tree->access<uhd::usrp::component_files_t>("/mboards/0/components/fpga").set(all_component_files); + tree->access<uhd::usrp::component_files_t>("/mboards/0/components/fpga") + .set(all_component_files); UHD_LOG_INFO("MPMD IMAGE LOADER", "Update component function succeeded."); return true; } -}} //namespace uhd::/*anon*/ +}} // namespace uhd:: -UHD_STATIC_BLOCK(register_mpm_image_loader){ +UHD_STATIC_BLOCK(register_mpm_image_loader) +{ // TODO: Update recovery instructions - const std::string recovery_instructions = "Aborting. Your USRP MPM-enabled device's update may or may not have\n" - "completed. The contents of the image files may have been corrupted.\n" - "Please verify those files as soon as possible."; + const std::string recovery_instructions = + "Aborting. Your USRP MPM-enabled device's update may or may not have\n" + "completed. The contents of the image files may have been corrupted.\n" + "Please verify those files as soon as possible."; - //TODO: 'n3xx' doesn't really fit the MPM abstraction, but this is simpler for the time being + // TODO: 'n3xx' doesn't really fit the MPM abstraction, but this is simpler for the + // time being image_loader::register_image_loader("n3xx", mpmd_image_loader, recovery_instructions); image_loader::register_image_loader("e3xx", mpmd_image_loader, recovery_instructions); } diff --git a/host/lib/usrp/mpmd/mpmd_impl.cpp b/host/lib/usrp/mpmd/mpmd_impl.cpp index 87e911e17..b8ce6cabd 100644 --- a/host/lib/usrp/mpmd/mpmd_impl.cpp +++ b/host/lib/usrp/mpmd/mpmd_impl.cpp @@ -5,189 +5,166 @@ // #include "mpmd_impl.hpp" -#include <../device3/device3_impl.hpp> #include <uhd/exception.hpp> -#include <uhd/utils/static.hpp> -#include <uhd/utils/tasks.hpp> -#include <uhd/types/sensors.hpp> -#include <uhd/types/eeprom.hpp> #include <uhd/types/component_file.hpp> +#include <uhd/types/eeprom.hpp> +#include <uhd/types/sensors.hpp> #include <uhd/usrp/mboard_eeprom.hpp> -#include <uhdlib/rfnoc/rpc_block_ctrl.hpp> +#include <uhd/utils/static.hpp> +#include <uhd/utils/tasks.hpp> #include <uhdlib/rfnoc/radio_ctrl_impl.hpp> +#include <uhdlib/rfnoc/rpc_block_ctrl.hpp> +#include <../device3/device3_impl.hpp> #include <boost/algorithm/string.hpp> #include <boost/asio.hpp> #include <boost/make_shared.hpp> #include <boost/thread.hpp> +#include <future> #include <memory> #include <mutex> #include <random> #include <string> -#include <vector> -#include <future> #include <thread> +#include <vector> using namespace uhd; using namespace uhd::mpmd; namespace { - /************************************************************************* - * Local constants - ************************************************************************/ - const size_t MPMD_CROSSBAR_MAX_LADDR = 255; - //! Most pessimistic time for a CHDR query to go to device and back - const double MPMD_CHDR_MAX_RTT = 0.02; - //! MPM Compatibility number - const std::vector<size_t> MPM_COMPAT_NUM = {1, 2}; +/************************************************************************* + * Local constants + ************************************************************************/ +const size_t MPMD_CROSSBAR_MAX_LADDR = 255; +//! Most pessimistic time for a CHDR query to go to device and back +const double MPMD_CHDR_MAX_RTT = 0.02; +//! MPM Compatibility number +const std::vector<size_t> MPM_COMPAT_NUM = {1, 2}; - /************************************************************************* - * Helper functions - ************************************************************************/ - void reset_time_synchronized(uhd::property_tree::sptr tree) - { - const size_t n_mboards = tree->list("/mboards").size(); - UHD_LOGGER_DEBUG("MPMD") - << "Synchronizing " << n_mboards <<" timekeepers..."; - auto get_time_last_pps = [tree](){ - return tree->access<time_spec_t>( - fs_path("/mboards/0/time/pps") - ).get(); - }; - auto end_time = std::chrono::steady_clock::now() - + std::chrono::milliseconds(1100); - auto time_last_pps = get_time_last_pps(); - UHD_LOG_DEBUG("MPMD", "Waiting for PPS clock edge..."); - while (time_last_pps == get_time_last_pps()) - { - if (std::chrono::steady_clock::now() > end_time) { - throw uhd::runtime_error( - "Board 0 may not be getting a PPS signal!\n" - "No PPS detected within the time interval.\n" - "See the application notes for your device.\n" - ); - } - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - UHD_LOG_DEBUG("MPMD", "Setting all timekeepers to 0..."); - for (size_t mboard_idx = 0; mboard_idx < n_mboards; mboard_idx++) { - tree->access<time_spec_t>( - fs_path("/mboards") / mboard_idx / "time" / "pps" - ).set(time_spec_t(0.0)); +/************************************************************************* + * Helper functions + ************************************************************************/ +void reset_time_synchronized(uhd::property_tree::sptr tree) +{ + const size_t n_mboards = tree->list("/mboards").size(); + UHD_LOGGER_DEBUG("MPMD") << "Synchronizing " << n_mboards << " timekeepers..."; + auto get_time_last_pps = [tree]() { + return tree->access<time_spec_t>(fs_path("/mboards/0/time/pps")).get(); + }; + auto end_time = std::chrono::steady_clock::now() + std::chrono::milliseconds(1100); + auto time_last_pps = get_time_last_pps(); + UHD_LOG_DEBUG("MPMD", "Waiting for PPS clock edge..."); + while (time_last_pps == get_time_last_pps()) { + if (std::chrono::steady_clock::now() > end_time) { + throw uhd::runtime_error("Board 0 may not be getting a PPS signal!\n" + "No PPS detected within the time interval.\n" + "See the application notes for your device.\n"); } + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + UHD_LOG_DEBUG("MPMD", "Setting all timekeepers to 0..."); + for (size_t mboard_idx = 0; mboard_idx < n_mboards; mboard_idx++) { + tree->access<time_spec_t>(fs_path("/mboards") / mboard_idx / "time" / "pps") + .set(time_spec_t(0.0)); + } - UHD_LOG_DEBUG("MPMD", "Waiting for next PPS edge..."); - std::this_thread::sleep_for(std::chrono::seconds(1)); + UHD_LOG_DEBUG("MPMD", "Waiting for next PPS edge..."); + std::this_thread::sleep_for(std::chrono::seconds(1)); - UHD_LOG_DEBUG("MPMD", "Verifying all timekeepers are aligned..."); - auto get_time_now = [tree](const size_t mb_index){ - return tree->access<time_spec_t>( - fs_path("/mboards") / mb_index / "time/now" - ).get(); - }; - for (size_t m = 1; m < n_mboards; m++){ - time_spec_t time_0 = get_time_now(0); - time_spec_t time_i = get_time_now(m); - if (time_i < time_0 - or (time_i - time_0) > time_spec_t(MPMD_CHDR_MAX_RTT)) { - UHD_LOGGER_WARNING("MULTI_USRP") << boost::format( - "Detected time deviation between board %d and board 0.\n" - "Board 0 time is %f seconds.\n" - "Board %d time is %f seconds.\n" - ) % m % time_0.get_real_secs() % m % time_i.get_real_secs(); - } + UHD_LOG_DEBUG("MPMD", "Verifying all timekeepers are aligned..."); + auto get_time_now = [tree](const size_t mb_index) { + return tree->access<time_spec_t>(fs_path("/mboards") / mb_index / "time/now") + .get(); + }; + for (size_t m = 1; m < n_mboards; m++) { + time_spec_t time_0 = get_time_now(0); + time_spec_t time_i = get_time_now(m); + if (time_i < time_0 or (time_i - time_0) > time_spec_t(MPMD_CHDR_MAX_RTT)) { + UHD_LOGGER_WARNING("MULTI_USRP") + << boost::format("Detected time deviation between board %d and board 0.\n" + "Board 0 time is %f seconds.\n" + "Board %d time is %f seconds.\n") + % m % time_0.get_real_secs() % m % time_i.get_real_secs(); } } +} - /*! Throw an exception if compat numbers don't match. - * - * \param component Name of the component for which we're checking the - * compat number (for logging and exceptions strings). - * \param expected Tuple of 2 integers representing MAJOR.MINOR compat - * number. - * \param actual Tuple of 2 integers representing MAJOR.MINOR compat - * number. - * \param advice_on_failure A string that is appended to the error message - * when compat number mismatches have occurred. - */ - void assert_compat_number_throw( - const std::string &component, - const std::vector<size_t> &expected, - const std::vector<size_t> &actual, - const std::string& advice_on_failure="" - ) { - UHD_ASSERT_THROW(expected.size() == 2); - UHD_ASSERT_THROW(actual.size() == 2); - UHD_LOGGER_TRACE("MPMD") - << "Checking " << component << " compat number. Expected: " - << expected[0] << "." << expected[1] - << " Actual: " - << actual[0] << "." << actual[1] - ; +/*! Throw an exception if compat numbers don't match. + * + * \param component Name of the component for which we're checking the + * compat number (for logging and exceptions strings). + * \param expected Tuple of 2 integers representing MAJOR.MINOR compat + * number. + * \param actual Tuple of 2 integers representing MAJOR.MINOR compat + * number. + * \param advice_on_failure A string that is appended to the error message + * when compat number mismatches have occurred. + */ +void assert_compat_number_throw(const std::string& component, + const std::vector<size_t>& expected, + const std::vector<size_t>& actual, + const std::string& advice_on_failure = "") +{ + UHD_ASSERT_THROW(expected.size() == 2); + UHD_ASSERT_THROW(actual.size() == 2); + UHD_LOGGER_TRACE("MPMD") << "Checking " << component + << " compat number. Expected: " << expected[0] << "." + << expected[1] << " Actual: " << actual[0] << "." + << actual[1]; - if (actual[0] != expected[0]) { - const std::string err_msg = - str(boost::format("%s major compat number mismatch. " - "Expected: %i.%i Actual: %i.%i.%s%s") - % component - % expected[0] % expected[1] - % actual[0] % actual[1] - % (advice_on_failure.empty() ? "" : " ") - % advice_on_failure); - UHD_LOG_ERROR("MPMD", err_msg); - throw uhd::runtime_error(err_msg); - } - if (actual[1] < expected[1]) { - const std::string err_msg = - str(boost::format("%s minor compat number mismatch. " - "Expected: %i.%i Actual: %i.%i.%s%s") - % component - % expected[0] % expected[1] - % actual[0] % actual[1] - % (advice_on_failure.empty() ? "" : " ") - % advice_on_failure); - UHD_LOG_ERROR("MPMD", err_msg); - throw uhd::runtime_error(err_msg); - } - if (actual[1] > expected[1]) { - const std::string err_msg = - str(boost::format("%s minor compat number mismatch. " - "Expected: %i.%i Actual: %i.%i") - % component - % expected[0] % expected[1] - % actual[0] % actual[1]); - UHD_LOG_WARNING("MPMD", err_msg); - } + if (actual[0] != expected[0]) { + const std::string err_msg = + str(boost::format("%s major compat number mismatch. " + "Expected: %i.%i Actual: %i.%i.%s%s") + % component % expected[0] % expected[1] % actual[0] % actual[1] + % (advice_on_failure.empty() ? "" : " ") % advice_on_failure); + UHD_LOG_ERROR("MPMD", err_msg); + throw uhd::runtime_error(err_msg); + } + if (actual[1] < expected[1]) { + const std::string err_msg = + str(boost::format("%s minor compat number mismatch. " + "Expected: %i.%i Actual: %i.%i.%s%s") + % component % expected[0] % expected[1] % actual[0] % actual[1] + % (advice_on_failure.empty() ? "" : " ") % advice_on_failure); + UHD_LOG_ERROR("MPMD", err_msg); + throw uhd::runtime_error(err_msg); + } + if (actual[1] > expected[1]) { + const std::string err_msg = + str(boost::format("%s minor compat number mismatch. " + "Expected: %i.%i Actual: %i.%i") + % component % expected[0] % expected[1] % actual[0] % actual[1]); + UHD_LOG_WARNING("MPMD", err_msg); } } +} // namespace /***************************************************************************** * Static class attributes ****************************************************************************/ -const std::string mpmd_impl::MPM_FINDALL_KEY = "find_all"; -const size_t mpmd_impl::MPM_DISCOVERY_PORT = 49600; -const std::string mpmd_impl::MPM_DISCOVERY_PORT_KEY = "discovery_port"; -const size_t mpmd_impl::MPM_RPC_PORT = 49601; -const std::string mpmd_impl::MPM_RPC_PORT_KEY = "rpc_port"; +const std::string mpmd_impl::MPM_FINDALL_KEY = "find_all"; +const size_t mpmd_impl::MPM_DISCOVERY_PORT = 49600; +const std::string mpmd_impl::MPM_DISCOVERY_PORT_KEY = "discovery_port"; +const size_t mpmd_impl::MPM_RPC_PORT = 49601; +const std::string mpmd_impl::MPM_RPC_PORT_KEY = "rpc_port"; const std::string mpmd_impl::MPM_RPC_GET_LAST_ERROR_CMD = "get_last_error"; -const std::string mpmd_impl::MPM_DISCOVERY_CMD = "MPM-DISC"; -const std::string mpmd_impl::MPM_ECHO_CMD = "MPM-ECHO"; +const std::string mpmd_impl::MPM_DISCOVERY_CMD = "MPM-DISC"; +const std::string mpmd_impl::MPM_ECHO_CMD = "MPM-ECHO"; /***************************************************************************** * Structors ****************************************************************************/ mpmd_impl::mpmd_impl(const device_addr_t& device_args) - : usrp::device3_impl() - , _device_args(device_args) + : usrp::device3_impl(), _device_args(device_args) { const device_addrs_t mb_args = separate_device_addr(device_args); - const size_t num_mboards = mb_args.size(); + const size_t num_mboards = mb_args.size(); _mb.reserve(num_mboards); const bool serialize_init = device_args.has_key("serialize_init"); - const bool skip_init = device_args.has_key("skip_init"); - UHD_LOGGER_INFO("MPMD") - << "Initializing " << num_mboards << " device(s) " - << (serialize_init ? "serially " : "in parallel ") - << "with args: " << device_args.to_string(); + const bool skip_init = device_args.has_key("skip_init"); + UHD_LOGGER_INFO("MPMD") << "Initializing " << num_mboards << " device(s) " + << (serialize_init ? "serially " : "in parallel ") + << "with args: " << device_args.to_string(); // First, claim all the devices (so we own them and no one else can claim // them). @@ -202,8 +179,8 @@ mpmd_impl::mpmd_impl(const device_addr_t& device_args) // can run _mb[*]->init() in parallel on all the _mb. // This can *not* be parallelized. std::vector<size_t> base_xport_addr(num_mboards, 2); // Starts at 2 [sic] - for (size_t mb_i = 0; mb_i < num_mboards-1; ++mb_i) { - base_xport_addr[mb_i+1] = base_xport_addr[mb_i] + _mb[mb_i]->num_xbars; + for (size_t mb_i = 0; mb_i < num_mboards - 1; ++mb_i) { + base_xport_addr[mb_i + 1] = base_xport_addr[mb_i] + _mb[mb_i]->num_xbars; } if (not skip_init) { @@ -260,35 +237,28 @@ mpmd_impl::~mpmd_impl() /***************************************************************************** * Private methods ****************************************************************************/ -mpmd_mboard_impl::uptr mpmd_impl::claim_and_make( - const uhd::device_addr_t& device_args -) { +mpmd_mboard_impl::uptr mpmd_impl::claim_and_make(const uhd::device_addr_t& device_args) +{ const std::string rpc_addr = device_args.get(xport::MGMT_ADDR_KEY); - UHD_LOGGER_DEBUG("MPMD") - << "Device args: `" << device_args.to_string() - << "'. RPC address: " << rpc_addr - ; + UHD_LOGGER_DEBUG("MPMD") << "Device args: `" << device_args.to_string() + << "'. RPC address: " << rpc_addr; if (rpc_addr.empty()) { UHD_LOG_ERROR("MPMD", "Could not determine RPC address from device args: " - << device_args.to_string()); + << device_args.to_string()); throw uhd::runtime_error("Could not determine device RPC address."); } return mpmd_mboard_impl::make(device_args, rpc_addr); } void mpmd_impl::setup_mb( - mpmd_mboard_impl *mb, - const size_t mb_index, - const size_t base_xport_addr -) { - assert_compat_number_throw( - "MPM", + mpmd_mboard_impl* mb, const size_t mb_index, const size_t base_xport_addr) +{ + assert_compat_number_throw("MPM", MPM_COMPAT_NUM, mb->rpc->request<std::vector<size_t>>("get_mpm_compat_num"), - "Please update the version of MPM on your USRP device." - ); + "Please update the version of MPM on your USRP device."); UHD_LOG_DEBUG("MPMD", "Initializing mboard " << mb_index); mb->init(); @@ -297,94 +267,83 @@ void mpmd_impl::setup_mb( } } -void mpmd_impl::setup_rfnoc_blocks( - mpmd_mboard_impl* mb, +void mpmd_impl::setup_rfnoc_blocks(mpmd_mboard_impl* mb, const size_t mb_index, - const uhd::device_addr_t& ctrl_xport_args -) { - UHD_LOG_TRACE("MPMD", - "Mboard " << mb_index << " reports " << mb->num_xbars << " crossbar(s)." - ); + const uhd::device_addr_t& ctrl_xport_args) +{ + UHD_LOG_TRACE( + "MPMD", "Mboard " << mb_index << " reports " << mb->num_xbars << " crossbar(s)."); // TODO: The args apply to all xbars, which may or may not be true for (size_t xbar_index = 0; xbar_index < mb->num_xbars; xbar_index++) { // Pull the number of blocks and base port from the args, if available. // Otherwise, get the values from MPM. - const size_t num_blocks = ctrl_xport_args.has_key("rfnoc_num_blocks") - ? ctrl_xport_args.cast<size_t>("rfnoc_num_blocks", 0) - : mb->rpc->request<size_t>("get_num_blocks", xbar_index); - const size_t base_port = ctrl_xport_args.has_key("rfnoc_base_port") - ? ctrl_xport_args.cast<size_t>("rfnoc_base_port", 0) - : mb->rpc->request<size_t>("get_base_port", xbar_index); + const size_t num_blocks = + ctrl_xport_args.has_key("rfnoc_num_blocks") + ? ctrl_xport_args.cast<size_t>("rfnoc_num_blocks", 0) + : mb->rpc->request<size_t>("get_num_blocks", xbar_index); + const size_t base_port = + ctrl_xport_args.has_key("rfnoc_base_port") + ? ctrl_xport_args.cast<size_t>("rfnoc_base_port", 0) + : mb->rpc->request<size_t>("get_base_port", xbar_index); const size_t local_addr = mb->get_xbar_local_addr(xbar_index); UHD_LOGGER_TRACE("MPMD") << "Enumerating RFNoC blocks for xbar " << xbar_index - << ". Total blocks: " << num_blocks - << " Base port: " << base_port - << " Local address: " << local_addr - ; - if (ctrl_xport_args.has_key("rfnoc_num_blocks") or - ctrl_xport_args.has_key("rfnoc_base_port")) { + << ". Total blocks: " << num_blocks << " Base port: " << base_port + << " Local address: " << local_addr; + if (ctrl_xport_args.has_key("rfnoc_num_blocks") + or ctrl_xport_args.has_key("rfnoc_base_port")) { // TODO: Remove this warning once we're confident this is // (relatively) safe and useful. Also add documentation to // usrp_n3xx.dox UHD_LOGGER_WARNING("MPMD") << "Overriding default RFNoC configuration. You are using an " << "experimental development feature, which may go away in " - << "future versions." - ; + << "future versions."; } try { - enumerate_rfnoc_blocks( - mb_index, - num_blocks, - base_port, - uhd::sid_t(0, 0, local_addr, 0), - ctrl_xport_args - ); - } catch (const std::exception &ex) { - UHD_LOGGER_ERROR("MPMD") - << "Failure during block enumeration: " - << ex.what(); + enumerate_rfnoc_blocks(mb_index, + num_blocks, + base_port, + uhd::sid_t(0, 0, local_addr, 0), + ctrl_xport_args); + } catch (const std::exception& ex) { + UHD_LOGGER_ERROR("MPMD") << "Failure during block enumeration: " << ex.what(); throw uhd::runtime_error("Failed to run enumerate_rfnoc_blocks()"); } } } void mpmd_impl::setup_rpc_blocks( - const device_addr_t &block_args, - const bool serialize_init -) { + const device_addr_t& block_args, const bool serialize_init) +{ std::vector<std::future<void>> task_list; // If we don't force async, most compilers, at least now, will default to // deferred. - const auto launch_policy = serialize_init ? - std::launch::deferred : - std::launch::async; + const auto launch_policy = serialize_init ? std::launch::deferred + : std::launch::async; // Preload all the tasks (they might start running on emplace_back) - for (const auto &block_ctrl: _rfnoc_block_ctrl) { + for (const auto& block_ctrl : _rfnoc_block_ctrl) { auto rpc_block_id = block_ctrl->get_block_id(); if (has_block<uhd::rfnoc::rpc_block_ctrl>(rpc_block_id)) { const size_t mboard_idx = rpc_block_id.get_device_no(); auto rpc_block_ctrl = get_block_ctrl<uhd::rfnoc::rpc_block_ctrl>(rpc_block_id); auto rpc_sptr = _mb[mboard_idx]->rpc; - task_list.emplace_back(std::async(launch_policy, - [rpc_block_id, rpc_block_ctrl, &block_args, rpc_sptr](){ + task_list.emplace_back(std::async( + launch_policy, [rpc_block_id, rpc_block_ctrl, &block_args, rpc_sptr]() { UHD_LOGGER_DEBUG("MPMD") << "Adding RPC access to block: " << rpc_block_id - << " Block args: " << block_args.to_string() - ; + << " Block args: " << block_args.to_string(); rpc_block_ctrl->set_rpc_client(rpc_sptr, block_args); - } - )); + })); } } // Execute all the calls to set_rpc_client(), either concurrently, or // serially - for (auto &task : task_list) { + for (auto& task : task_list) { task.get(); } } diff --git a/host/lib/usrp/mpmd/mpmd_impl.hpp b/host/lib/usrp/mpmd/mpmd_impl.hpp index e9d942c9d..f3328dc6f 100644 --- a/host/lib/usrp/mpmd/mpmd_impl.hpp +++ b/host/lib/usrp/mpmd/mpmd_impl.hpp @@ -7,14 +7,14 @@ #ifndef INCLUDED_MPMD_IMPL_HPP #define INCLUDED_MPMD_IMPL_HPP -#include "mpmd_xport_mgr.hpp" #include "../device3/device3_impl.hpp" +#include "mpmd_xport_mgr.hpp" +#include <uhd/property_tree.hpp> #include <uhd/stream.hpp> +#include <uhd/transport/muxed_zero_copy_if.hpp> #include <uhd/types/device_addr.hpp> #include <uhd/types/dict.hpp> #include <uhd/utils/tasks.hpp> -#include <uhd/transport/muxed_zero_copy_if.hpp> -#include <uhd/property_tree.hpp> #include <uhdlib/utils/rpc.hpp> #include <boost/optional.hpp> #include <map> @@ -24,16 +24,16 @@ * RPC timeout constants for MPMD ************************************************************************/ //! Time between reclaims (ms) -static constexpr size_t MPMD_RECLAIM_INTERVAL_MS = 1000; +static constexpr size_t MPMD_RECLAIM_INTERVAL_MS = 1000; //! Default timeout value for the init() RPC call (ms) -static constexpr size_t MPMD_DEFAULT_INIT_TIMEOUT = 120000; +static constexpr size_t MPMD_DEFAULT_INIT_TIMEOUT = 120000; //! Default timeout value for RPC calls (ms) -static constexpr size_t MPMD_DEFAULT_RPC_TIMEOUT = 2000; +static constexpr size_t MPMD_DEFAULT_RPC_TIMEOUT = 2000; //! Short timeout value for RPC calls (ms), used for calls that shouldn't // take long. This value can be used to quickly determine a link status. -static constexpr size_t MPMD_SHORT_RPC_TIMEOUT = 2000; +static constexpr size_t MPMD_SHORT_RPC_TIMEOUT = 2000; //! Claimer loop timeout value for RPC calls (ms). -static constexpr size_t MPMD_CLAIMER_RPC_TIMEOUT = 10000; +static constexpr size_t MPMD_CLAIMER_RPC_TIMEOUT = 10000; namespace uhd { namespace mpmd { @@ -41,9 +41,9 @@ namespace uhd { namespace mpmd { */ class mpmd_mboard_impl { - public: +public: /*** Types ***************************************************************/ - using uptr = std::unique_ptr<mpmd_mboard_impl>; + using uptr = std::unique_ptr<mpmd_mboard_impl>; using dev_info = std::map<std::string, std::string>; /*** Static helper *******************************************************/ @@ -53,8 +53,7 @@ class mpmd_mboard_impl * \param device_addr Device args. Must contain an mgmt_addr. */ static boost::optional<device_addr_t> is_device_reachable( - const device_addr_t& device_addr - ); + const device_addr_t& device_addr); /*** Structors ***********************************************************/ /*! Ctor: Claim device or throw an exception on failure. @@ -64,10 +63,7 @@ class mpmd_mboard_impl * \param mb_args Device args that pertain to this motherboard * \param ip_addr RPC client will attempt to connect to this IP address */ - mpmd_mboard_impl( - const uhd::device_addr_t &mb_args, - const std::string& ip_addr - ); + mpmd_mboard_impl(const uhd::device_addr_t& mb_args, const std::string& ip_addr); ~mpmd_mboard_impl(); /*** Factory *************************************************************/ @@ -75,10 +71,7 @@ class mpmd_mboard_impl * \param mb_args Device args that pertain to this motherboard * \param ip_addr RPC client will attempt to connect to this IP address */ - static uptr make( - const uhd::device_addr_t &mb_args, - const std::string& addr - ); + static uptr make(const uhd::device_addr_t& mb_args, const std::string& addr); /*** Init ****************************************************************/ void init(); @@ -112,7 +105,8 @@ class mpmd_mboard_impl void set_xbar_local_addr(const size_t xbar_index, const size_t local_addr); //! Return the local address of a given crossbar - size_t get_xbar_local_addr(const size_t xbar_index) const { + size_t get_xbar_local_addr(const size_t xbar_index) const + { return xbar_local_addrs.at(xbar_index); } @@ -126,11 +120,9 @@ class mpmd_mboard_impl // \param sid The full SID of this transport (UHD to device) // \param xport_type Transport type (CTRL, RX_DATA, ...) // \param args Any kind of args passed in via get_?x_stream() - uhd::both_xports_t make_transport( - const sid_t& sid, + uhd::both_xports_t make_transport(const sid_t& sid, usrp::device3_impl::xport_type_t xport_type, - const uhd::device_addr_t& args - ); + const uhd::device_addr_t& args); size_t get_mtu(const uhd::direction_t dir) const; @@ -138,7 +130,7 @@ class mpmd_mboard_impl uhd::device_addr_t get_rx_hints() const; uhd::device_addr_t get_tx_hints() const; - private: +private: /*! Reference to the RPC client that handles claiming */ uhd::rpc_client::sptr _claim_rpc; @@ -152,21 +144,18 @@ class mpmd_mboard_impl */ bool claim(); - /*! Set RPC client timeout value - * - * \param timeout_ms time limit (in ms) that a rpc client waits for a single call - */ - void set_rpcc_timeout( - const uint64_t timeout_ms - ); + /*! Set RPC client timeout value + * + * \param timeout_ms time limit (in ms) that a rpc client waits for a single call + */ + void set_rpcc_timeout(const uint64_t timeout_ms); - uhd::task::sptr claim_device_and_make_task( - ); + uhd::task::sptr claim_device_and_make_task(); /*! Read out the log buffer from the MPM device and send it to native * logging system. */ - void dump_logs(const bool dump_to_null=false); + void dump_logs(const bool dump_to_null = false); /************************************************************************* * Private attributes @@ -224,10 +213,10 @@ public: * API ************************************************************************/ uhd::both_xports_t make_transport(const uhd::sid_t&, - uhd::usrp::device3_impl::xport_type_t, - const uhd::device_addr_t&); + uhd::usrp::device3_impl::xport_type_t, + const uhd::device_addr_t&); - private: +private: uhd::device_addr_t get_rx_hints(size_t mb_index); uhd::device_addr_t get_tx_hints(size_t mb_index); @@ -238,9 +227,7 @@ public: * * Does not initialize the device (see setup_mb() for that). */ - mpmd_mboard_impl::uptr claim_and_make( - const uhd::device_addr_t& dev_args - ); + mpmd_mboard_impl::uptr claim_and_make(const uhd::device_addr_t& dev_args); /*! Initialize a single motherboard * @@ -253,23 +240,15 @@ public: * */ void setup_mb( - mpmd_mboard_impl *mb, - const size_t mb_index, - const size_t base_xport_addr - ); + mpmd_mboard_impl* mb, const size_t mb_index, const size_t base_xport_addr); //! Setup all RFNoC blocks running on mboard \p mb_i void setup_rfnoc_blocks( - mpmd_mboard_impl* mb, - const size_t mb_i, - const uhd::device_addr_t& block_args - ); + mpmd_mboard_impl* mb, const size_t mb_i, const uhd::device_addr_t& block_args); //! Configure all blocks that require access to an RPC client void setup_rpc_blocks( - const uhd::device_addr_t &block_args, - const bool serialize_init - ); + const uhd::device_addr_t& block_args, const bool serialize_init); /*! Return the index of the motherboard given the local address of a * crossbar @@ -283,10 +262,7 @@ public: * \param mb Reference to the actual device */ static void init_property_tree( - uhd::property_tree::sptr tree, - fs_path mb_path, - mpmd_mboard_impl *mb - ); + uhd::property_tree::sptr tree, fs_path mb_path, mpmd_mboard_impl* mb); /************************************************************************* diff --git a/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp b/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp index a49651f10..261b6f2aa 100644 --- a/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp +++ b/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp @@ -5,209 +5,166 @@ // #include "mpmd_impl.hpp" -#include <uhd/utils/safe_call.hpp> -#include <uhd/utils/log.hpp> #include <uhd/transport/udp_simple.hpp> +#include <uhd/utils/log.hpp> +#include <uhd/utils/safe_call.hpp> #include <chrono> #include <thread> namespace { - /************************************************************************* - * Local constants - ************************************************************************/ - //! Timeout for pings (seconds). - constexpr double MPMD_PING_TIMEOUT = 0.1; - //! Default session ID (MPM will recognize a session by this name) - const std::string MPMD_DEFAULT_SESSION_ID = "UHD"; - //! Key to initialize a ping/measurement latency test - const std::string MPMD_MEAS_LATENCY_KEY = "measure_rpc_latency"; - //! Duration of a latency measurement test - constexpr size_t MPMD_MEAS_LATENCY_DURATION = 1000; - - using log_buf_t = std::vector<std::map<std::string, std::string>>; - - - /************************************************************************* - * Helper functions - ************************************************************************/ - /*! Return true if we can MPM ping a device via discovery service. - */ - bool is_pingable(const std::string& ip_addr, const std::string& udp_port) - { - auto udp = uhd::transport::udp_simple::make_broadcast( - ip_addr, - udp_port - ); - const std::string send_buf( - uhd::mpmd::mpmd_impl::MPM_ECHO_CMD + " ping" - ); - std::vector<uint8_t> recv_buf; - recv_buf.resize(send_buf.size(), ' '); - udp->send(boost::asio::buffer(send_buf.c_str(), send_buf.size())); - const size_t len = - udp->recv(boost::asio::buffer(recv_buf), MPMD_PING_TIMEOUT); - if (len == 0) { - UHD_LOG_TRACE("MPMD", - "Received no MPM ping, assuming device is unreachable."); - return false; - } - if (len != send_buf.size()) { - UHD_LOG_DEBUG("MPMD", - "Received bad return packet on MPM ping. Assuming endpoint" - " is not a valid MPM device."); - return false; - } - if (std::memcmp( - (void *) &recv_buf[0], - (void *) &send_buf[0], - send_buf.size()) != 0) { - UHD_LOG_DEBUG("MPMD", - "Received invalid return packet on MPM ping. Assuming endpoint" - " is not a valid MPM device."); - return false; - } - return true; +/************************************************************************* + * Local constants + ************************************************************************/ +//! Timeout for pings (seconds). +constexpr double MPMD_PING_TIMEOUT = 0.1; +//! Default session ID (MPM will recognize a session by this name) +const std::string MPMD_DEFAULT_SESSION_ID = "UHD"; +//! Key to initialize a ping/measurement latency test +const std::string MPMD_MEAS_LATENCY_KEY = "measure_rpc_latency"; +//! Duration of a latency measurement test +constexpr size_t MPMD_MEAS_LATENCY_DURATION = 1000; + +using log_buf_t = std::vector<std::map<std::string, std::string>>; + + +/************************************************************************* + * Helper functions + ************************************************************************/ +/*! Return true if we can MPM ping a device via discovery service. + */ +bool is_pingable(const std::string& ip_addr, const std::string& udp_port) +{ + auto udp = uhd::transport::udp_simple::make_broadcast(ip_addr, udp_port); + const std::string send_buf(uhd::mpmd::mpmd_impl::MPM_ECHO_CMD + " ping"); + std::vector<uint8_t> recv_buf; + recv_buf.resize(send_buf.size(), ' '); + udp->send(boost::asio::buffer(send_buf.c_str(), send_buf.size())); + const size_t len = udp->recv(boost::asio::buffer(recv_buf), MPMD_PING_TIMEOUT); + if (len == 0) { + UHD_LOG_TRACE("MPMD", "Received no MPM ping, assuming device is unreachable."); + return false; } - - /*! Call init() on an MPM device. - */ - void init_device( - uhd::rpc_client::sptr rpc, - const uhd::device_addr_t mb_args - ) { - auto init_status = - rpc->request_with_token<std::vector<std::string>>( - MPMD_DEFAULT_INIT_TIMEOUT, "get_init_status"); - if (init_status[0] != "true") { - throw uhd::runtime_error( - std::string("Device is in bad state: ") + init_status[1] - ); - } - - // TODO maybe put this somewhere else? - const std::set<std::string> key_blacklist{ - "serial", "claimed", "type", "rev", "addr" - }; - std::map<std::string, std::string> mpm_device_args; - for (const auto &key : mb_args.keys()) { - if (not key_blacklist.count(key)) { - mpm_device_args[key] = mb_args[key]; - } - } - if (not rpc->request_with_token<bool>(MPMD_DEFAULT_INIT_TIMEOUT, "init", mpm_device_args)) { - throw uhd::runtime_error("Failed to initialize device."); - } + if (len != send_buf.size()) { + UHD_LOG_DEBUG("MPMD", + "Received bad return packet on MPM ping. Assuming endpoint" + " is not a valid MPM device."); + return false; + } + if (std::memcmp((void*)&recv_buf[0], (void*)&send_buf[0], send_buf.size()) != 0) { + UHD_LOG_DEBUG("MPMD", + "Received invalid return packet on MPM ping. Assuming endpoint" + " is not a valid MPM device."); + return false; } + return true; +} - void measure_rpc_latency( - uhd::rpc_client::sptr rpc, - const size_t duration_ms=MPMD_MEAS_LATENCY_DURATION - ) { - const double alpha = 0.99; - const std::string payload = "1234567890"; - auto measure_once = [payload, rpc](){ - const auto start = std::chrono::steady_clock::now(); - rpc->request<std::string>("ping", payload); - return (double) std::chrono::duration_cast<std::chrono::microseconds>( - std::chrono::steady_clock::now() - start - ).count(); - }; +/*! Call init() on an MPM device. + */ +void init_device(uhd::rpc_client::sptr rpc, const uhd::device_addr_t mb_args) +{ + auto init_status = rpc->request_with_token<std::vector<std::string>>( + MPMD_DEFAULT_INIT_TIMEOUT, "get_init_status"); + if (init_status[0] != "true") { + throw uhd::runtime_error( + std::string("Device is in bad state: ") + init_status[1]); + } - double max_latency = measure_once(); - double avg_latency = max_latency; - - auto end_time = std::chrono::steady_clock::now() - + std::chrono::milliseconds(duration_ms); - size_t ctr = 1; - while (std::chrono::steady_clock::now() < end_time) { - const auto duration = measure_once(); - max_latency = std::max(max_latency, duration); - avg_latency = avg_latency * alpha + (1-alpha) * duration; - ctr++; - // Light throttle: - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + // TODO maybe put this somewhere else? + const std::set<std::string> key_blacklist{"serial", "claimed", "type", "rev", "addr"}; + std::map<std::string, std::string> mpm_device_args; + for (const auto& key : mb_args.keys()) { + if (not key_blacklist.count(key)) { + mpm_device_args[key] = mb_args[key]; } - - UHD_LOG_INFO("MPMD", - "RPC latency (coarse estimate): Avg = " << avg_latency << " us, " - "Max = " << max_latency - << ", n = " << ctr); } + if (not rpc->request_with_token<bool>( + MPMD_DEFAULT_INIT_TIMEOUT, "init", mpm_device_args)) { + throw uhd::runtime_error("Failed to initialize device."); + } +} - /*! Forward entries from a list of dictionaries to UHD's native logging - * system. - */ - void forward_logs(log_buf_t&& log_buf) - { - for (const auto &log_record : log_buf) { - if (log_record.count("levelname") == 0 or \ - log_record.count("message") == 0) { - UHD_LOG_ERROR("MPMD", - "Invalid logging structure returned from MPM device!"); - continue; - } - if (log_record.at("levelname") == "TRACE") { - UHD_LOG_TRACE( - log_record.at("name"), - log_record.at("message") - ); - } - else if (log_record.at("levelname") == "DEBUG") { - UHD_LOG_DEBUG( - log_record.at("name"), - log_record.at("message") - ); - } - else if (log_record.at("levelname") == "INFO") { - UHD_LOG_INFO( - log_record.at("name"), - log_record.at("message") - ); - } - else if (log_record.at("levelname") == "WARNING") { - UHD_LOG_WARNING( - log_record.at("name"), - log_record.at("message") - ); - } - else if (log_record.at("levelname") == "ERROR") { - UHD_LOG_ERROR( - log_record.at("name"), - log_record.at("message") - ); - } - else if (log_record.at("levelname") == "CRITICAL") { - UHD_LOG_FATAL( - log_record.at("name"), - log_record.at("message") - ); - } else { - UHD_LOG_ERROR("MPMD", - "Invalid log level returned from MPM device: " - "`" << log_record.at("levelname") << "'"); - } - } +void measure_rpc_latency( + uhd::rpc_client::sptr rpc, const size_t duration_ms = MPMD_MEAS_LATENCY_DURATION) +{ + const double alpha = 0.99; + const std::string payload = "1234567890"; + auto measure_once = [payload, rpc]() { + const auto start = std::chrono::steady_clock::now(); + rpc->request<std::string>("ping", payload); + return (double)std::chrono::duration_cast<std::chrono::microseconds>( + std::chrono::steady_clock::now() - start) + .count(); + }; + + double max_latency = measure_once(); + double avg_latency = max_latency; + + auto end_time = + std::chrono::steady_clock::now() + std::chrono::milliseconds(duration_ms); + size_t ctr = 1; + while (std::chrono::steady_clock::now() < end_time) { + const auto duration = measure_once(); + max_latency = std::max(max_latency, duration); + avg_latency = avg_latency * alpha + (1 - alpha) * duration; + ctr++; + // Light throttle: + std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - /*! Return a new rpc_client with given addr and mb args - */ - uhd::rpc_client::sptr make_mpm_rpc_client( - const std::string& rpc_server_addr, - const uhd::device_addr_t& mb_args, - const size_t timeout_ms = MPMD_DEFAULT_RPC_TIMEOUT - ){ - return uhd::rpc_client::make( - rpc_server_addr, - mb_args.cast<size_t>( - uhd::mpmd::mpmd_impl::MPM_RPC_PORT_KEY, - uhd::mpmd::mpmd_impl::MPM_RPC_PORT - ), - timeout_ms, - uhd::mpmd::mpmd_impl::MPM_RPC_GET_LAST_ERROR_CMD); + UHD_LOG_INFO("MPMD", + "RPC latency (coarse estimate): Avg = " << avg_latency + << " us, " + "Max = " + << max_latency << ", n = " << ctr); +} + +/*! Forward entries from a list of dictionaries to UHD's native logging + * system. + */ +void forward_logs(log_buf_t&& log_buf) +{ + for (const auto& log_record : log_buf) { + if (log_record.count("levelname") == 0 or log_record.count("message") == 0) { + UHD_LOG_ERROR("MPMD", "Invalid logging structure returned from MPM device!"); + continue; + } + if (log_record.at("levelname") == "TRACE") { + UHD_LOG_TRACE(log_record.at("name"), log_record.at("message")); + } else if (log_record.at("levelname") == "DEBUG") { + UHD_LOG_DEBUG(log_record.at("name"), log_record.at("message")); + } else if (log_record.at("levelname") == "INFO") { + UHD_LOG_INFO(log_record.at("name"), log_record.at("message")); + } else if (log_record.at("levelname") == "WARNING") { + UHD_LOG_WARNING(log_record.at("name"), log_record.at("message")); + } else if (log_record.at("levelname") == "ERROR") { + UHD_LOG_ERROR(log_record.at("name"), log_record.at("message")); + } else if (log_record.at("levelname") == "CRITICAL") { + UHD_LOG_FATAL(log_record.at("name"), log_record.at("message")); + } else { + UHD_LOG_ERROR("MPMD", + "Invalid log level returned from MPM device: " + "`" << log_record.at("levelname") + << "'"); + } } +} +/*! Return a new rpc_client with given addr and mb args + */ +uhd::rpc_client::sptr make_mpm_rpc_client(const std::string& rpc_server_addr, + const uhd::device_addr_t& mb_args, + const size_t timeout_ms = MPMD_DEFAULT_RPC_TIMEOUT) +{ + return uhd::rpc_client::make(rpc_server_addr, + mb_args.cast<size_t>( + uhd::mpmd::mpmd_impl::MPM_RPC_PORT_KEY, uhd::mpmd::mpmd_impl::MPM_RPC_PORT), + timeout_ms, + uhd::mpmd::mpmd_impl::MPM_RPC_GET_LAST_ERROR_CMD); } +} // namespace + using namespace uhd; using namespace uhd::mpmd; @@ -215,22 +172,20 @@ using namespace uhd::mpmd; * Static Helpers *****************************************************************************/ boost::optional<device_addr_t> mpmd_mboard_impl::is_device_reachable( - const device_addr_t &device_addr -) { - UHD_LOG_TRACE("MPMD", - "Checking accessibility of device `" << device_addr.to_string() - << "'"); + const device_addr_t& device_addr) +{ + UHD_LOG_TRACE( + "MPMD", "Checking accessibility of device `" << device_addr.to_string() << "'"); UHD_ASSERT_THROW(device_addr.has_key(xport::MGMT_ADDR_KEY)); const std::string rpc_addr = device_addr.get(xport::MGMT_ADDR_KEY); - const size_t rpc_port = device_addr.cast<size_t>( - mpmd_impl::MPM_RPC_PORT_KEY, - mpmd_impl::MPM_RPC_PORT - ); + const size_t rpc_port = + device_addr.cast<size_t>(mpmd_impl::MPM_RPC_PORT_KEY, mpmd_impl::MPM_RPC_PORT); auto rpcc = uhd::rpc_client::make(rpc_addr, rpc_port); // 1) Read back device info dev_info device_info_dict; try { - device_info_dict = rpcc->request<dev_info>(MPMD_SHORT_RPC_TIMEOUT, "get_device_info"); + device_info_dict = + rpcc->request<dev_info>(MPMD_SHORT_RPC_TIMEOUT, "get_device_info"); } catch (const uhd::runtime_error& e) { UHD_LOG_ERROR("MPMD", e.what()); } catch (...) { @@ -240,8 +195,8 @@ boost::optional<device_addr_t> mpmd_mboard_impl::is_device_reachable( return boost::optional<device_addr_t>(); } // 2) Check for local device - if (device_info_dict.count("connection") and - device_info_dict.at("connection") == "local") { + if (device_info_dict.count("connection") + and device_info_dict.at("connection") == "local") { UHD_LOG_TRACE("MPMD", "Device is local, flagging as reachable."); return boost::optional<device_addr_t>(device_addr); } @@ -254,46 +209,43 @@ boost::optional<device_addr_t> mpmd_mboard_impl::is_device_reachable( continue; } const std::string chdr_addr = device_info_dict.at(addr_key); - UHD_LOG_TRACE("MPMD", - "Checking reachability via network addr " << chdr_addr); + UHD_LOG_TRACE("MPMD", "Checking reachability via network addr " << chdr_addr); try { // First do an MPM ping -- there is some issue with rpclib that can // lead to indefinite timeouts - const std::string mpm_discovery_port = device_addr.get( - mpmd_impl::MPM_DISCOVERY_PORT_KEY, - std::to_string(mpmd_impl::MPM_DISCOVERY_PORT) - ); + const std::string mpm_discovery_port = + device_addr.get(mpmd_impl::MPM_DISCOVERY_PORT_KEY, + std::to_string(mpmd_impl::MPM_DISCOVERY_PORT)); if (!is_pingable(chdr_addr, mpm_discovery_port)) { - UHD_LOG_TRACE("MPMD", - "Cannot MPM ping, assuming device is unreachable."); + UHD_LOG_TRACE("MPMD", "Cannot MPM ping, assuming device is unreachable."); continue; } - UHD_LOG_TRACE("MPMD", - "Was able to ping device, trying RPC connection."); + UHD_LOG_TRACE("MPMD", "Was able to ping device, trying RPC connection."); auto chdr_rpcc = uhd::rpc_client::make(chdr_addr, rpc_port); - auto dev_info_chdr = chdr_rpcc->request<dev_info>(MPMD_SHORT_RPC_TIMEOUT, "get_device_info"); + auto dev_info_chdr = + chdr_rpcc->request<dev_info>(MPMD_SHORT_RPC_TIMEOUT, "get_device_info"); if (dev_info_chdr["serial"] != device_info_dict["serial"]) { - UHD_LOG_DEBUG("MPMD", boost::format( - "Connected to CHDR interface, but got wrong device. " - "Tried to reach serial %s, got %s") - % device_info_dict["serial"] % dev_info_chdr["serial"]); + UHD_LOG_DEBUG("MPMD", + boost::format("Connected to CHDR interface, but got wrong device. " + "Tried to reach serial %s, got %s") + % device_info_dict["serial"] % dev_info_chdr["serial"]); return boost::optional<device_addr_t>(); } else { - UHD_LOG_TRACE("MPMD", boost::format( - "Reachable device matches expected device (serial=%s)") - % device_info_dict["serial"] ); + UHD_LOG_TRACE("MPMD", + boost::format("Reachable device matches expected device (serial=%s)") + % device_info_dict["serial"]); } device_addr_t device_addr_copy = device_addr; - device_addr_copy["addr"] = chdr_addr; + device_addr_copy["addr"] = chdr_addr; return boost::optional<device_addr_t>(device_addr_copy); } catch (...) { - UHD_LOG_DEBUG("MPMD", - "Failed to reach device on network addr " << chdr_addr << "."); + UHD_LOG_DEBUG( + "MPMD", "Failed to reach device on network addr " << chdr_addr << "."); } } // If everything fails, we probably can't talk to this chap. - UHD_LOG_TRACE("MPMD", - "All reachability checks failed -- assuming device is not reachable."); + UHD_LOG_TRACE( + "MPMD", "All reachability checks failed -- assuming device is not reachable."); return boost::optional<device_addr_t>(); } @@ -301,9 +253,8 @@ boost::optional<device_addr_t> mpmd_mboard_impl::is_device_reachable( * Structors ****************************************************************************/ mpmd_mboard_impl::mpmd_mboard_impl( - const device_addr_t &mb_args_, - const std::string& rpc_server_addr -) : mb_args(mb_args_) + const device_addr_t& mb_args_, const std::string& rpc_server_addr) + : mb_args(mb_args_) , rpc(make_mpm_rpc_client(rpc_server_addr, mb_args_)) , num_xbars(rpc->request<size_t>("get_num_xbars")) , _claim_rpc(make_mpm_rpc_client(rpc_server_addr, mb_args, MPMD_CLAIMER_RPC_TIMEOUT)) @@ -311,12 +262,9 @@ mpmd_mboard_impl::mpmd_mboard_impl( , xbar_local_addrs(num_xbars, 0xFF) , _xport_mgr(xport::mpmd_xport_mgr::make(mb_args)) { - UHD_LOGGER_TRACE("MPMD") - << "Initializing mboard, connecting to RPC server address: " - << rpc_server_addr - << " mboard args: " << mb_args.to_string() - << " number of crossbars: " << num_xbars - ; + UHD_LOGGER_TRACE("MPMD") << "Initializing mboard, connecting to RPC server address: " + << rpc_server_addr << " mboard args: " << mb_args.to_string() + << " number of crossbars: " << num_xbars; _claimer_task = claim_device_and_make_task(); if (mb_args_.has_key(MPMD_MEAS_LATENCY_KEY)) { @@ -325,23 +273,21 @@ mpmd_mboard_impl::mpmd_mboard_impl( /// Get device info const auto device_info_dict = rpc->request<dev_info>("get_device_info"); - for (const auto &info_pair : device_info_dict) { + for (const auto& info_pair : device_info_dict) { device_info[info_pair.first] = info_pair.second; } - UHD_LOGGER_TRACE("MPMD") - << "MPM reports device info: " << device_info.to_string(); + UHD_LOGGER_TRACE("MPMD") << "MPM reports device info: " << device_info.to_string(); /// Get dboard info - const auto dboards_info = - rpc->request<std::vector<dev_info>>("get_dboard_info"); + const auto dboards_info = rpc->request<std::vector<dev_info>>("get_dboard_info"); UHD_ASSERT_THROW(this->dboard_info.size() == 0); - for (const auto &dboard_info_dict : dboards_info) { + for (const auto& dboard_info_dict : dboards_info) { uhd::device_addr_t this_db_info; - for (const auto &info_pair : dboard_info_dict) { + for (const auto& info_pair : dboard_info_dict) { this_db_info[info_pair.first] = info_pair.second; } UHD_LOGGER_TRACE("MPMD") - << "MPM reports dboard info for slot " << this->dboard_info.size() - << ": " << this_db_info.to_string(); + << "MPM reports dboard info for slot " << this->dboard_info.size() << ": " + << this_db_info.to_string(); this->dboard_info.push_back(this_db_info); } } @@ -353,11 +299,9 @@ mpmd_mboard_impl::~mpmd_mboard_impl() } catch (...) { UHD_LOG_WARNING("MPMD", "Could not flush log queue on exit!"); } - UHD_SAFE_CALL( - if (not rpc->request_with_token<bool>("unclaim")) { - UHD_LOG_WARNING("MPMD", "Failure to ack unclaim!"); - } - ); + UHD_SAFE_CALL(if (not rpc->request_with_token<bool>("unclaim")) { + UHD_LOG_WARNING("MPMD", "Failure to ack unclaim!"); + }); } /***************************************************************************** @@ -373,52 +317,42 @@ void mpmd_mboard_impl::init() * API ****************************************************************************/ void mpmd_mboard_impl::set_xbar_local_addr( - const size_t xbar_index, - const size_t local_addr -) { - UHD_ASSERT_THROW(rpc->request_with_token<bool>("set_xbar_local_addr", xbar_index, local_addr)); + const size_t xbar_index, const size_t local_addr) +{ + UHD_ASSERT_THROW( + rpc->request_with_token<bool>("set_xbar_local_addr", xbar_index, local_addr)); UHD_ASSERT_THROW(xbar_index < xbar_local_addrs.size()); xbar_local_addrs.at(xbar_index) = local_addr; } -uhd::both_xports_t mpmd_mboard_impl::make_transport( - const sid_t& sid, - usrp::device3_impl::xport_type_t xport_type, - const uhd::device_addr_t& xport_args -) { - const std::string xport_type_str = [xport_type](){ +uhd::both_xports_t mpmd_mboard_impl::make_transport(const sid_t& sid, + usrp::device3_impl::xport_type_t xport_type, + const uhd::device_addr_t& xport_args) +{ + const std::string xport_type_str = [xport_type]() { switch (xport_type) { - case mpmd_impl::CTRL: - return "CTRL"; - case mpmd_impl::ASYNC_MSG: - return "ASYNC_MSG"; - case mpmd_impl::RX_DATA: - return "RX_DATA"; - case mpmd_impl::TX_DATA: - return "TX_DATA"; - default: - UHD_THROW_INVALID_CODE_PATH(); + case mpmd_impl::CTRL: + return "CTRL"; + case mpmd_impl::ASYNC_MSG: + return "ASYNC_MSG"; + case mpmd_impl::RX_DATA: + return "RX_DATA"; + case mpmd_impl::TX_DATA: + return "TX_DATA"; + default: + UHD_THROW_INVALID_CODE_PATH(); }; }(); - UHD_LOGGER_TRACE("MPMD") - << __func__ << "(): Creating new transport of type: " - << xport_type_str - ; + UHD_LOGGER_TRACE("MPMD") << __func__ + << "(): Creating new transport of type: " << xport_type_str; using namespace uhd::mpmd::xport; const auto xport_info_list = rpc->request_with_token<mpmd_xport_mgr::xport_info_list_t>( - "request_xport", - sid.get_dst(), - sid.get_src(), - xport_type_str - ); - UHD_LOGGER_TRACE("MPMD") - << __func__ - << "(): request_xport() gave us " << xport_info_list.size() - << " option(s)." - ; + "request_xport", sid.get_dst(), sid.get_src(), xport_type_str); + UHD_LOGGER_TRACE("MPMD") << __func__ << "(): request_xport() gave us " + << xport_info_list.size() << " option(s)."; if (xport_info_list.empty()) { UHD_LOG_ERROR("MPMD", "No viable transport path found!"); throw uhd::runtime_error("No viable transport path found!"); @@ -426,15 +360,9 @@ uhd::both_xports_t mpmd_mboard_impl::make_transport( xport::mpmd_xport_mgr::xport_info_t xport_info_out; auto xports = _xport_mgr->make_transport( - xport_info_list, - xport_type, - xport_args, - xport_info_out - ); + xport_info_list, xport_type, xport_args, xport_info_out); - if (not rpc->request_with_token<bool>( - "commit_xport", - xport_info_out)) { + if (not rpc->request_with_token<bool>("commit_xport", xport_info_out)) { UHD_LOG_ERROR("MPMD", "Failed to create UDP transport!"); throw uhd::runtime_error("commit_xport() failed!"); } @@ -474,11 +402,10 @@ bool mpmd_mboard_impl::claim() } } -uhd::task::sptr mpmd_mboard_impl::claim_device_and_make_task( -) { - auto rpc_token = _claim_rpc->request<std::string>("claim", - mb_args.get("session_id", MPMD_DEFAULT_SESSION_ID) - ); +uhd::task::sptr mpmd_mboard_impl::claim_device_and_make_task() +{ + auto rpc_token = _claim_rpc->request<std::string>( + "claim", mb_args.get("session_id", MPMD_DEFAULT_SESSION_ID)); if (rpc_token.empty()) { throw uhd::value_error("mpmd device claiming failed!"); } @@ -493,8 +420,7 @@ uhd::task::sptr mpmd_mboard_impl::claim_device_and_make_task( }; this->dump_logs(); std::this_thread::sleep_until( - now + std::chrono::milliseconds(MPMD_RECLAIM_INTERVAL_MS) - ); + now + std::chrono::milliseconds(MPMD_RECLAIM_INTERVAL_MS)); }); } @@ -514,12 +440,10 @@ void mpmd_mboard_impl::dump_logs(const bool dump_to_null) * Factory ****************************************************************************/ mpmd_mboard_impl::uptr mpmd_mboard_impl::make( - const uhd::device_addr_t &mb_args, - const std::string& addr -) { + const uhd::device_addr_t& mb_args, const std::string& addr) +{ mpmd_mboard_impl::uptr mb = mpmd_mboard_impl::uptr(new mpmd_mboard_impl(mb_args, addr)); // implicit move return mb; } - diff --git a/host/lib/usrp/mpmd/mpmd_prop_tree.cpp b/host/lib/usrp/mpmd/mpmd_prop_tree.cpp index 27893341d..e4ebee5ac 100644 --- a/host/lib/usrp/mpmd/mpmd_prop_tree.cpp +++ b/host/lib/usrp/mpmd/mpmd_prop_tree.cpp @@ -9,91 +9,86 @@ #include "mpmd_impl.hpp" #include <uhd/property_tree.hpp> #include <uhd/types/component_file.hpp> -#include <uhd/types/sensors.hpp> #include <uhd/types/eeprom.hpp> +#include <uhd/types/sensors.hpp> #include <uhd/usrp/mboard_eeprom.hpp> using namespace uhd; using namespace uhd::mpmd; namespace { - //! Timeout value for the update_component RPC call (ms) - constexpr size_t MPMD_UPDATE_COMPONENT_TIMEOUT = 20000; +//! Timeout value for the update_component RPC call (ms) +constexpr size_t MPMD_UPDATE_COMPONENT_TIMEOUT = 20000; - /*! Update a component using all required files. For example, when updating the FPGA image - * (.bit or .bin), users can provide a new overlay image (DTS) to apply in addition. - * - * \param comps Vector of component files to be updated - * \param mb Reference to the actual device - */ - uhd::usrp::component_files_t _update_component( - const uhd::usrp::component_files_t& comps, - mpmd_mboard_impl *mb - ) { - // Construct the arguments to update component - std::vector<std::vector<uint8_t>> all_data; - std::vector<std::map<std::string, std::string>> all_metadata; - // Also construct a copy of just the metadata to store in the property tree - uhd::usrp::component_files_t all_comps_copy; +/*! Update a component using all required files. For example, when updating the FPGA image + * (.bit or .bin), users can provide a new overlay image (DTS) to apply in addition. + * + * \param comps Vector of component files to be updated + * \param mb Reference to the actual device + */ +uhd::usrp::component_files_t _update_component( + const uhd::usrp::component_files_t& comps, mpmd_mboard_impl* mb) +{ + // Construct the arguments to update component + std::vector<std::vector<uint8_t>> all_data; + std::vector<std::map<std::string, std::string>> all_metadata; + // Also construct a copy of just the metadata to store in the property tree + uhd::usrp::component_files_t all_comps_copy; - for (const auto& comp : comps) { - // Make a map for update components args - std::map<std::string, std::string> metadata; - // Make a component copy to add to the property tree - uhd::usrp::component_file_t comp_copy; - // Copy the metadata - for (const auto& key : comp.metadata.keys()) { - metadata[key] = comp.metadata[key]; - comp_copy.metadata[key] = comp.metadata[key]; - } - // Copy to the update component args - all_data.push_back(comp.data); - all_metadata.push_back(metadata); - // Copy to the property tree - all_comps_copy.push_back(comp_copy); + for (const auto& comp : comps) { + // Make a map for update components args + std::map<std::string, std::string> metadata; + // Make a component copy to add to the property tree + uhd::usrp::component_file_t comp_copy; + // Copy the metadata + for (const auto& key : comp.metadata.keys()) { + metadata[key] = comp.metadata[key]; + comp_copy.metadata[key] = comp.metadata[key]; } - - // Now call update component - const size_t update_component_timeout = MPMD_UPDATE_COMPONENT_TIMEOUT * comps.size(); - mb->rpc->notify_with_token(update_component_timeout, - "update_component", all_metadata, all_data); - return all_comps_copy; + // Copy to the update component args + all_data.push_back(comp.data); + all_metadata.push_back(metadata); + // Copy to the property tree + all_comps_copy.push_back(comp_copy); } - /* - * Query the device to get the metadata for desired component - * - * \param comp_name String component name - * \param mb Reference to the actual device - * \return component files containing the component metadata - */ - uhd::usrp::component_files_t _get_component_info( - const std::string &comp_name, - mpmd_mboard_impl *mb - ) { - UHD_LOG_TRACE("MPMD", "Getting component info for " << comp_name); - const auto component_metadata = mb->rpc->request<std::map<std::string, std::string>>( - "get_component_info", comp_name); - // Copy the contents of the component metadata into a object we can return - uhd::usrp::component_file_t return_component; - auto &return_metadata = return_component.metadata; - for (auto item : component_metadata) { - return_metadata[item.first] = item.second; - } - return uhd::usrp::component_files_t {return_component}; + // Now call update component + const size_t update_component_timeout = MPMD_UPDATE_COMPONENT_TIMEOUT * comps.size(); + mb->rpc->notify_with_token( + update_component_timeout, "update_component", all_metadata, all_data); + return all_comps_copy; +} + +/* + * Query the device to get the metadata for desired component + * + * \param comp_name String component name + * \param mb Reference to the actual device + * \return component files containing the component metadata + */ +uhd::usrp::component_files_t _get_component_info( + const std::string& comp_name, mpmd_mboard_impl* mb) +{ + UHD_LOG_TRACE("MPMD", "Getting component info for " << comp_name); + const auto component_metadata = mb->rpc->request<std::map<std::string, std::string>>( + "get_component_info", comp_name); + // Copy the contents of the component metadata into a object we can return + uhd::usrp::component_file_t return_component; + auto& return_metadata = return_component.metadata; + for (auto item : component_metadata) { + return_metadata[item.first] = item.second; } + return uhd::usrp::component_files_t{return_component}; } +} // namespace void mpmd_impl::init_property_tree( - uhd::property_tree::sptr tree, - fs_path mb_path, - mpmd_mboard_impl *mb -) { + uhd::property_tree::sptr tree, fs_path mb_path, mpmd_mboard_impl* mb) +{ /*** Device info ****************************************************/ if (not tree->exists("/name")) { - tree->create<std::string>("/name") - .set(mb->device_info.get("description", "Unknown MPM device")) - ; + tree->create<std::string>("/name").set( + mb->device_info.get("description", "Unknown MPM device")); } tree->create<std::string>(mb_path / "name") .set(mb->device_info.get("name", "UNKNOWN")); @@ -111,143 +106,98 @@ void mpmd_impl::init_property_tree( /*** Clocking *******************************************************/ tree->create<std::string>(mb_path / "clock_source/value") - .add_coerced_subscriber([mb](const std::string &clock_source){ - mb->rpc->notify_with_token(MPMD_DEFAULT_INIT_TIMEOUT, "set_clock_source", clock_source); + .add_coerced_subscriber([mb](const std::string& clock_source) { + mb->rpc->notify_with_token( + MPMD_DEFAULT_INIT_TIMEOUT, "set_clock_source", clock_source); }) - .set_publisher([mb](){ - return mb->rpc->request_with_token<std::string>( - "get_clock_source" - ); - }) - ; - tree->create<std::vector<std::string>>( - mb_path / "clock_source/options") - .set_publisher([mb](){ + .set_publisher([mb]() { + return mb->rpc->request_with_token<std::string>("get_clock_source"); + }); + tree->create<std::vector<std::string>>(mb_path / "clock_source/options") + .set_publisher([mb]() { return mb->rpc->request_with_token<std::vector<std::string>>( - "get_clock_sources" - ); - }) - ; + "get_clock_sources"); + }); tree->create<std::string>(mb_path / "time_source/value") - .add_coerced_subscriber([mb](const std::string &time_source){ - mb->rpc->notify_with_token(MPMD_DEFAULT_INIT_TIMEOUT, "set_time_source", time_source); + .add_coerced_subscriber([mb](const std::string& time_source) { + mb->rpc->notify_with_token( + MPMD_DEFAULT_INIT_TIMEOUT, "set_time_source", time_source); }) - .set_publisher([mb](){ - return mb->rpc->request_with_token<std::string>( - "get_time_source" - ); - }) - ; - tree->create<std::vector<std::string>>( - mb_path / "time_source/options") - .set_publisher([mb](){ + .set_publisher([mb]() { + return mb->rpc->request_with_token<std::string>("get_time_source"); + }); + tree->create<std::vector<std::string>>(mb_path / "time_source/options") + .set_publisher([mb]() { return mb->rpc->request_with_token<std::vector<std::string>>( - "get_time_sources" - ); - }) - ; + "get_time_sources"); + }); /*** Sensors ********************************************************/ auto sensor_list = - mb->rpc->request_with_token<std::vector<std::string>>( - "get_mb_sensors" - ); - UHD_LOG_DEBUG("MPMD", - "Found " << sensor_list.size() << " motherboard sensors." - ); + mb->rpc->request_with_token<std::vector<std::string>>("get_mb_sensors"); + UHD_LOG_DEBUG("MPMD", "Found " << sensor_list.size() << " motherboard sensors."); for (const auto& sensor_name : sensor_list) { - UHD_LOG_TRACE("MPMD", - "Adding motherboard sensor `" << sensor_name << "'" - ); - tree->create<sensor_value_t>( - mb_path / "sensors" / sensor_name) - .set_publisher([mb, sensor_name](){ + UHD_LOG_TRACE("MPMD", "Adding motherboard sensor `" << sensor_name << "'"); + tree->create<sensor_value_t>(mb_path / "sensors" / sensor_name) + .set_publisher([mb, sensor_name]() { auto sensor_val = sensor_value_t( mb->rpc->request_with_token<sensor_value_t::sensor_map_t>( - MPMD_DEFAULT_INIT_TIMEOUT, "get_mb_sensor", sensor_name - ) - ); + MPMD_DEFAULT_INIT_TIMEOUT, "get_mb_sensor", sensor_name)); return sensor_val; }) - .set_coercer([](const sensor_value_t &){ - throw uhd::runtime_error( - "Trying to write read-only sensor value!" - ); + .set_coercer([](const sensor_value_t&) { + throw uhd::runtime_error("Trying to write read-only sensor value!"); return sensor_value_t("", "", ""); - }) - ; + }); } /*** EEPROM *********************************************************/ tree->create<uhd::usrp::mboard_eeprom_t>(mb_path / "eeprom") - .add_coerced_subscriber([mb](const uhd::usrp::mboard_eeprom_t& mb_eeprom){ + .add_coerced_subscriber([mb](const uhd::usrp::mboard_eeprom_t& mb_eeprom) { eeprom_map_t eeprom_map; for (const auto& key : mb_eeprom.keys()) { - eeprom_map[key] = std::vector<uint8_t>( - mb_eeprom[key].cbegin(), - mb_eeprom[key].cend() - ); + eeprom_map[key] = + std::vector<uint8_t>(mb_eeprom[key].cbegin(), mb_eeprom[key].cend()); } - mb->rpc->notify_with_token(MPMD_DEFAULT_INIT_TIMEOUT, "set_mb_eeprom", eeprom_map); + mb->rpc->notify_with_token( + MPMD_DEFAULT_INIT_TIMEOUT, "set_mb_eeprom", eeprom_map); }) - .set_publisher([mb](){ + .set_publisher([mb]() { auto mb_eeprom = mb->rpc->request_with_token<std::map<std::string, std::string>>( - "get_mb_eeprom" - ); + "get_mb_eeprom"); uhd::usrp::mboard_eeprom_t mb_eeprom_dict( - mb_eeprom.cbegin(), mb_eeprom.cend() - ); + mb_eeprom.cbegin(), mb_eeprom.cend()); return mb_eeprom_dict; - }) - ; + }); /*** Updateable Components ******************************************/ std::vector<std::string> updateable_components = - mb->rpc->request<std::vector<std::string>>( - "list_updateable_components" - ); + mb->rpc->request<std::vector<std::string>>("list_updateable_components"); // TODO: Check the 'id' against the registered property UHD_LOG_DEBUG("MPMD", - "Found " << updateable_components.size() << " updateable motherboard components." - ); + "Found " << updateable_components.size() + << " updateable motherboard components."); for (const auto& comp_name : updateable_components) { - UHD_LOG_TRACE("MPMD", - "Adding motherboard component: " << comp_name); + UHD_LOG_TRACE("MPMD", "Adding motherboard component: " << comp_name); tree->create<uhd::usrp::component_files_t>(mb_path / "components" / comp_name) - .set_coercer([mb](const uhd::usrp::component_files_t& comp_files){ - return _update_component( - comp_files, - mb - ); + .set_coercer([mb](const uhd::usrp::component_files_t& comp_files) { + return _update_component(comp_files, mb); }) - .set_publisher([mb, comp_name](){ - return _get_component_info( - comp_name, - mb - ); - }) - ; // Done adding component to property tree + .set_publisher([mb, comp_name]() { + return _get_component_info(comp_name, mb); + }); // Done adding component to property tree } /*** MTUs ***********************************************************/ tree->create<size_t>(mb_path / "mtu/recv") - .add_coerced_subscriber([](const size_t){ - throw uhd::runtime_error( - "Attempting to write read-only value (MTU)!"); - }) - .set_publisher([mb](){ - return mb->get_mtu(uhd::RX_DIRECTION); + .add_coerced_subscriber([](const size_t) { + throw uhd::runtime_error("Attempting to write read-only value (MTU)!"); }) - ; + .set_publisher([mb]() { return mb->get_mtu(uhd::RX_DIRECTION); }); tree->create<size_t>(mb_path / "mtu/send") - .add_coerced_subscriber([](const size_t){ - throw uhd::runtime_error( - "Attempting to write read-only value (MTU)!"); + .add_coerced_subscriber([](const size_t) { + throw uhd::runtime_error("Attempting to write read-only value (MTU)!"); }) - .set_publisher([mb](){ - return mb->get_mtu(uhd::TX_DIRECTION); - }) - ; + .set_publisher([mb]() { return mb->get_mtu(uhd::TX_DIRECTION); }); } - diff --git a/host/lib/usrp/mpmd/mpmd_xport.cpp b/host/lib/usrp/mpmd/mpmd_xport.cpp index e697b6e80..3ef6a074c 100644 --- a/host/lib/usrp/mpmd/mpmd_xport.cpp +++ b/host/lib/usrp/mpmd/mpmd_xport.cpp @@ -26,52 +26,37 @@ uhd::device_addr_t mpmd_impl::get_tx_hints(size_t mb_index) size_t mpmd_impl::identify_mboard_by_xbar_addr(const size_t xbar_addr) const { for (size_t mb_index = 0; mb_index < _mb.size(); mb_index++) { - for (size_t xbar_index = 0; - xbar_index < _mb[mb_index]->num_xbars; - xbar_index++) { + for (size_t xbar_index = 0; xbar_index < _mb[mb_index]->num_xbars; xbar_index++) { if (_mb.at(mb_index)->get_xbar_local_addr(xbar_index) == xbar_addr) { return mb_index; } } } - throw uhd::lookup_error(str( - boost::format("Cannot identify mboard for crossbar address %d") - % xbar_addr - )); + throw uhd::lookup_error( + str(boost::format("Cannot identify mboard for crossbar address %d") % xbar_addr)); } -both_xports_t mpmd_impl::make_transport( - const sid_t& dst_address, - usrp::device3_impl::xport_type_t xport_type, - const uhd::device_addr_t& args -) { - const size_t mb_index = - identify_mboard_by_xbar_addr(dst_address.get_dst_addr()); +both_xports_t mpmd_impl::make_transport(const sid_t& dst_address, + usrp::device3_impl::xport_type_t xport_type, + const uhd::device_addr_t& args) +{ + const size_t mb_index = identify_mboard_by_xbar_addr(dst_address.get_dst_addr()); - const sid_t sid( - 0, 0, // Not actually an address, more of an 'ignore me' value + const sid_t sid(0, + 0, // Not actually an address, more of an 'ignore me' value dst_address.get_dst_addr(), - dst_address.get_dst_endpoint() - ); - UHD_LOGGER_TRACE("MPMD") - << "Creating new transport to mboard: " << mb_index - << " SID: " << sid.to_pp_string_hex() - << " User-defined xport args: " << args.to_string() - ; - - both_xports_t xports = _mb[mb_index]->make_transport( - sid, - xport_type, - args - ); - UHD_LOGGER_TRACE("MPMD") - << "xport info: send_sid==" << xports.send_sid.to_pp_string_hex() - << " recv_sid==" << xports.recv_sid.to_pp_string_hex() - << " endianness==" - << (xports.endianness == uhd::ENDIANNESS_BIG ? "BE" : "LE") - << " recv_buff_size==" << xports.recv_buff_size - << " send_buff_size==" << xports.send_buff_size - ; + dst_address.get_dst_endpoint()); + UHD_LOGGER_TRACE("MPMD") << "Creating new transport to mboard: " << mb_index + << " SID: " << sid.to_pp_string_hex() + << " User-defined xport args: " << args.to_string(); + + both_xports_t xports = _mb[mb_index]->make_transport(sid, xport_type, args); + UHD_LOGGER_TRACE("MPMD") << "xport info: send_sid==" + << xports.send_sid.to_pp_string_hex() + << " recv_sid==" << xports.recv_sid.to_pp_string_hex() + << " endianness==" + << (xports.endianness == uhd::ENDIANNESS_BIG ? "BE" : "LE") + << " recv_buff_size==" << xports.recv_buff_size + << " send_buff_size==" << xports.send_buff_size; return xports; } - diff --git a/host/lib/usrp/mpmd/mpmd_xport_ctrl_base.hpp b/host/lib/usrp/mpmd/mpmd_xport_ctrl_base.hpp index 78ffeaf1b..a7fff9262 100644 --- a/host/lib/usrp/mpmd/mpmd_xport_ctrl_base.hpp +++ b/host/lib/usrp/mpmd/mpmd_xport_ctrl_base.hpp @@ -7,8 +7,8 @@ #ifndef INCLUDED_MPMD_XPORT_CTRL_BASE_HPP #define INCLUDED_MPMD_XPORT_CTRL_BASE_HPP -#include "mpmd_xport_mgr.hpp" #include "../device3/device3_impl.hpp" +#include "mpmd_xport_mgr.hpp" #include <uhd/types/device_addr.hpp> #include <memory> @@ -29,20 +29,14 @@ public: * \param xport_type CTRL, ASYNC_MSG, ... (see xport_type_t) * \param xport_args Additional arguments. These can come from the user. */ - virtual both_xports_t make_transport( - mpmd_xport_mgr::xport_info_t& xport_info, + virtual both_xports_t make_transport(mpmd_xport_mgr::xport_info_t& xport_info, const usrp::device3_impl::xport_type_t xport_type, - const uhd::device_addr_t& xport_args - ) = 0; + const uhd::device_addr_t& xport_args) = 0; //! Assert if an xport_info is even valid/feasible/available - virtual bool is_valid( - const mpmd_xport_mgr::xport_info_t& xport_info - ) const = 0; + virtual bool is_valid(const mpmd_xport_mgr::xport_info_t& xport_info) const = 0; - virtual size_t get_mtu( - const uhd::direction_t dir - ) const = 0; + virtual size_t get_mtu(const uhd::direction_t dir) const = 0; }; }}} /* namespace uhd::mpmd::xport */ diff --git a/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.cpp b/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.cpp index 13ecea5e9..7efe2bb9a 100644 --- a/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.cpp +++ b/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.cpp @@ -14,42 +14,41 @@ using namespace uhd::mpmd::xport; namespace { - //! Max frame size of a control packet in bytes - const size_t LIBERIO_CTRL_FRAME_MAX_SIZE = 128; - //! Max frame size of an async message packet in bytes - const size_t LIBERIO_ASYNC_FRAME_MAX_SIZE = 256; - //! Max frame size of a flow control packet in bytes - const size_t LIBERIO_FC_FRAME_MAX_SIZE = 64; - //! The max MTU will be this number times the page size - const size_t LIBERIO_PAGES_PER_BUF = 2; - //! Number of descriptors that liberio allocates (receive) - const size_t LIBERIO_NUM_RECV_FRAMES = 128; - //! Number of descriptors that liberio allocates (send) - const size_t LIBERIO_NUM_SEND_FRAMES = 128; - - uint32_t extract_sid_from_pkt(void* pkt, size_t) { - return uhd::sid_t(uhd::wtohx(static_cast<const uint32_t*>(pkt)[1])) - .get_dst(); - } - +//! Max frame size of a control packet in bytes +const size_t LIBERIO_CTRL_FRAME_MAX_SIZE = 128; +//! Max frame size of an async message packet in bytes +const size_t LIBERIO_ASYNC_FRAME_MAX_SIZE = 256; +//! Max frame size of a flow control packet in bytes +const size_t LIBERIO_FC_FRAME_MAX_SIZE = 64; +//! The max MTU will be this number times the page size +const size_t LIBERIO_PAGES_PER_BUF = 2; +//! Number of descriptors that liberio allocates (receive) +const size_t LIBERIO_NUM_RECV_FRAMES = 128; +//! Number of descriptors that liberio allocates (send) +const size_t LIBERIO_NUM_SEND_FRAMES = 128; + +uint32_t extract_sid_from_pkt(void* pkt, size_t) +{ + return uhd::sid_t(uhd::wtohx(static_cast<const uint32_t*>(pkt)[1])).get_dst(); } -mpmd_xport_ctrl_liberio::mpmd_xport_ctrl_liberio( - const uhd::device_addr_t& mb_args -) : _mb_args(mb_args) - , _recv_args(filter_args(mb_args, "recv")) - , _send_args(filter_args(mb_args, "send")) +} // namespace + +mpmd_xport_ctrl_liberio::mpmd_xport_ctrl_liberio(const uhd::device_addr_t& mb_args) + : _mb_args(mb_args) + , _recv_args(filter_args(mb_args, "recv")) + , _send_args(filter_args(mb_args, "send")) { // nop } -uhd::both_xports_t -mpmd_xport_ctrl_liberio::make_transport( - mpmd_xport_mgr::xport_info_t &xport_info, - const usrp::device3_impl::xport_type_t xport_type, - const uhd::device_addr_t& /*xport_args_*/ -) { +uhd::both_xports_t mpmd_xport_ctrl_liberio::make_transport( + mpmd_xport_mgr::xport_info_t& xport_info, + const usrp::device3_impl::xport_type_t xport_type, + const uhd::device_addr_t& /*xport_args_*/ +) +{ transport::zero_copy_xport_params default_buff_args; /* default ones for RX / TX, override below */ @@ -75,8 +74,8 @@ mpmd_xport_ctrl_liberio::make_transport( both_xports_t xports; xports.endianness = uhd::ENDIANNESS_LITTLE; - xports.send_sid = sid_t(xport_info["send_sid"]); - xports.recv_sid = xports.send_sid.reversed(); + xports.send_sid = sid_t(xport_info["send_sid"]); + xports.recv_sid = xports.send_sid.reversed(); // this is kinda ghetto: scale buffer for muxed xports since we share the // buffer... @@ -87,7 +86,7 @@ mpmd_xport_ctrl_liberio::make_transport( divisor = 4; - //if (xport_info["muxed"] == "True") { + // if (xport_info["muxed"] == "True") { //// FIXME tbw //} if (xport_type == usrp::device3_impl::CTRL) { @@ -95,8 +94,8 @@ mpmd_xport_ctrl_liberio::make_transport( if (not _ctrl_dma_xport) { default_buff_args.send_frame_size = LIBERIO_CTRL_FRAME_MAX_SIZE; default_buff_args.recv_frame_size = LIBERIO_CTRL_FRAME_MAX_SIZE; - _ctrl_dma_xport = make_muxed_liberio_xport(tx_dev, rx_dev, - default_buff_args, int(divisor)); + _ctrl_dma_xport = + make_muxed_liberio_xport(tx_dev, rx_dev, default_buff_args, int(divisor)); } UHD_LOGGER_TRACE("MPMD") @@ -107,58 +106,52 @@ mpmd_xport_ctrl_liberio::make_transport( if (not _async_msg_dma_xport) { default_buff_args.send_frame_size = LIBERIO_ASYNC_FRAME_MAX_SIZE; default_buff_args.recv_frame_size = LIBERIO_ASYNC_FRAME_MAX_SIZE; - _async_msg_dma_xport = make_muxed_liberio_xport( - tx_dev, rx_dev, default_buff_args, int(divisor)); + _async_msg_dma_xport = + make_muxed_liberio_xport(tx_dev, rx_dev, default_buff_args, int(divisor)); } UHD_LOGGER_TRACE("MPMD") << "making (muxed) stream with num " << xports.recv_sid.get_dst(); - xports.recv = - _async_msg_dma_xport->make_stream(xports.recv_sid.get_dst()); + xports.recv = _async_msg_dma_xport->make_stream(xports.recv_sid.get_dst()); } else { - xports.recv = transport::liberio_zero_copy::make( - tx_dev, rx_dev, default_buff_args); + xports.recv = + transport::liberio_zero_copy::make(tx_dev, rx_dev, default_buff_args); } transport::udp_zero_copy::buff_params buff_params; - buff_params.recv_buff_size = - float(default_buff_args.recv_frame_size) * - float(default_buff_args.num_recv_frames) / divisor; - buff_params.send_buff_size = - float(default_buff_args.send_frame_size) * - float(default_buff_args.num_send_frames) / divisor; + buff_params.recv_buff_size = float(default_buff_args.recv_frame_size) + * float(default_buff_args.num_recv_frames) / divisor; + buff_params.send_buff_size = float(default_buff_args.send_frame_size) + * float(default_buff_args.num_send_frames) / divisor; // Finish both_xports_t object and return: xports.recv_buff_size = buff_params.recv_buff_size; xports.send_buff_size = buff_params.send_buff_size; - xports.send = xports.recv; + xports.send = xports.recv; return xports; } bool mpmd_xport_ctrl_liberio::is_valid( - const mpmd_xport_mgr::xport_info_t& xport_info -) const { + const mpmd_xport_mgr::xport_info_t& xport_info) const +{ return xport_info.at("type") == "liberio"; } -size_t mpmd_xport_ctrl_liberio::get_mtu( - const uhd::direction_t /* dir */ -) const { +size_t mpmd_xport_ctrl_liberio::get_mtu(const uhd::direction_t /* dir */ + ) const +{ return LIBERIO_PAGES_PER_BUF * getpagesize(); } uhd::transport::muxed_zero_copy_if::sptr -mpmd_xport_ctrl_liberio::make_muxed_liberio_xport( - const std::string &tx_dev, - const std::string &rx_dev, - const uhd::transport::zero_copy_xport_params &buff_args, - const size_t max_muxed_ports -) { - auto base_xport = transport::liberio_zero_copy::make( - tx_dev, rx_dev, buff_args); +mpmd_xport_ctrl_liberio::make_muxed_liberio_xport(const std::string& tx_dev, + const std::string& rx_dev, + const uhd::transport::zero_copy_xport_params& buff_args, + const size_t max_muxed_ports) +{ + auto base_xport = transport::liberio_zero_copy::make(tx_dev, rx_dev, buff_args); return uhd::transport::muxed_zero_copy_if::make( - base_xport, extract_sid_from_pkt, max_muxed_ports); + base_xport, extract_sid_from_pkt, max_muxed_ports); } - diff --git a/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.hpp b/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.hpp index 9bea12aa3..5f635e7e7 100644 --- a/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.hpp +++ b/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.hpp @@ -7,10 +7,10 @@ #ifndef INCLUDED_MPMD_XPORT_ctrl_liberio_HPP #define INCLUDED_MPMD_XPORT_ctrl_liberio_HPP -#include "mpmd_xport_ctrl_base.hpp" -#include <uhd/types/device_addr.hpp> #include "../device3/device3_impl.hpp" +#include "mpmd_xport_ctrl_base.hpp" #include <uhd/transport/muxed_zero_copy_if.hpp> +#include <uhd/types/device_addr.hpp> namespace uhd { namespace mpmd { namespace xport { @@ -19,34 +19,25 @@ namespace uhd { namespace mpmd { namespace xport { class mpmd_xport_ctrl_liberio : public mpmd_xport_ctrl_base { public: - mpmd_xport_ctrl_liberio( - const uhd::device_addr_t& mb_args - ); + mpmd_xport_ctrl_liberio(const uhd::device_addr_t& mb_args); /*! Open DMA interface to kernel (and thus to FPGA DMA engine) */ - both_xports_t make_transport( - mpmd_xport_mgr::xport_info_t& xport_info, + both_xports_t make_transport(mpmd_xport_mgr::xport_info_t& xport_info, const usrp::device3_impl::xport_type_t xport_type, - const uhd::device_addr_t& xport_args - ); + const uhd::device_addr_t& xport_args); - bool is_valid( - const mpmd_xport_mgr::xport_info_t& xport_info - ) const; + bool is_valid(const mpmd_xport_mgr::xport_info_t& xport_info) const; - size_t get_mtu( - const uhd::direction_t dir - ) const ; + size_t get_mtu(const uhd::direction_t dir) const; private: /*! Create a muxed liberio transport for control packets */ uhd::transport::muxed_zero_copy_if::sptr make_muxed_liberio_xport( - const std::string &tx_dev, - const std::string &rx_dev, - const uhd::transport::zero_copy_xport_params &buff_args, - const size_t max_muxed_ports - ); + const std::string& tx_dev, + const std::string& rx_dev, + const uhd::transport::zero_copy_xport_params& buff_args, + const size_t max_muxed_ports); const uhd::device_addr_t _mb_args; const uhd::dict<std::string, std::string> _recv_args; diff --git a/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.cpp b/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.cpp index ee48235ee..df02b183f 100644 --- a/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.cpp +++ b/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.cpp @@ -4,12 +4,12 @@ // SPDX-License-Identifier: GPL-3.0-or-later // +#include "mpmd_xport_ctrl_udp.hpp" #include "mpmd_impl.hpp" #include "mpmd_xport_mgr.hpp" -#include "mpmd_xport_ctrl_udp.hpp" -#include <uhd/transport/udp_zero_copy.hpp> -#include <uhd/transport/udp_simple.hpp> #include <uhd/transport/udp_constants.hpp> +#include <uhd/transport/udp_simple.hpp> +#include <uhd/transport/udp_zero_copy.hpp> using namespace uhd; @@ -17,244 +17,216 @@ using namespace uhd::mpmd::xport; namespace { - #if defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD) - //! Size of the host-side socket buffer for RX - const size_t MPMD_RX_SW_BUFF_SIZE_ETH = 0x100000; // 1Mib - #elif defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32) - //! Size of the host-side socket buffer for RX - // For an ~8k frame size any size >32MiB is just wasted buffer space - const size_t MPMD_RX_SW_BUFF_SIZE_ETH = 0x2000000; // 32 MiB - #endif +#if defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD) +//! Size of the host-side socket buffer for RX +const size_t MPMD_RX_SW_BUFF_SIZE_ETH = 0x100000; // 1Mib +#elif defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32) +//! Size of the host-side socket buffer for RX +// For an ~8k frame size any size >32MiB is just wasted buffer space +const size_t MPMD_RX_SW_BUFF_SIZE_ETH = 0x2000000; // 32 MiB +#endif - //! Maximum CHDR packet size in bytes - const size_t MPMD_10GE_DATA_FRAME_MAX_SIZE = 4000; +//! Maximum CHDR packet size in bytes +const size_t MPMD_10GE_DATA_FRAME_MAX_SIZE = 4000; - //! Maximum CHDR packet size in bytes - const size_t MPMD_10GE_ASYNCMSG_FRAME_MAX_SIZE = 1472; +//! Maximum CHDR packet size in bytes +const size_t MPMD_10GE_ASYNCMSG_FRAME_MAX_SIZE = 1472; - //! Number of send/recv frames - const size_t MPMD_ETH_NUM_FRAMES = 32; +//! Number of send/recv frames +const size_t MPMD_ETH_NUM_FRAMES = 32; - //! - const double MPMD_BUFFER_FILL_RATE = 20.0e-3; // s - //! For MTU discovery, the time we wait for a packet before calling it - // oversized (seconds). - const double MPMD_MTU_DISCOVERY_TIMEOUT = 0.02; +//! +const double MPMD_BUFFER_FILL_RATE = 20.0e-3; // s +//! For MTU discovery, the time we wait for a packet before calling it +// oversized (seconds). +const double MPMD_MTU_DISCOVERY_TIMEOUT = 0.02; - //TODO: move these to appropriate header file for all other devices - const size_t MAX_RATE_1GIGE = 1e9 / 8; // byte/s - const size_t MAX_RATE_10GIGE = 10e9 / 8; // byte/s +// TODO: move these to appropriate header file for all other devices +const size_t MAX_RATE_1GIGE = 1e9 / 8; // byte/s +const size_t MAX_RATE_10GIGE = 10e9 / 8; // byte/s - std::vector<std::string> get_addrs_from_mb_args( - const uhd::device_addr_t& mb_args - ) { - // mb_args must always include addr - if (not mb_args.has_key(FIRST_ADDR_KEY)) { - throw uhd::runtime_error("The " + FIRST_ADDR_KEY + " key must be specified in " - "device args to create an Ethernet transport to an RFNoC block"); - } - std::vector<std::string> addrs{mb_args[FIRST_ADDR_KEY]}; - if (mb_args.has_key(SECOND_ADDR_KEY)){ - addrs.push_back(mb_args[SECOND_ADDR_KEY]); - } - return addrs; +std::vector<std::string> get_addrs_from_mb_args(const uhd::device_addr_t& mb_args) +{ + // mb_args must always include addr + if (not mb_args.has_key(FIRST_ADDR_KEY)) { + throw uhd::runtime_error( + "The " + FIRST_ADDR_KEY + + " key must be specified in " + "device args to create an Ethernet transport to an RFNoC block"); } + std::vector<std::string> addrs{mb_args[FIRST_ADDR_KEY]}; + if (mb_args.has_key(SECOND_ADDR_KEY)) { + addrs.push_back(mb_args[SECOND_ADDR_KEY]); + } + return addrs; +} - /*! Do a binary search to discover MTU - * - * Uses the MPM echo service to figure out MTU. We simply send a bunch of - * packets and see if they come back until we converged on the path MTU. - * The end result must lie between \p min_frame_size and \p max_frame_size. - * - * \param address IP address - * \param port UDP port (yeah it's a string!) - * \param min_frame_size Minimum frame size, initialize algorithm to start - * with this value - * \param max_frame_size Maximum frame size, initialize algorithm to start - * with this value - * \param echo_timeout Timeout value in seconds. For frame sizes that - * exceed the MTU, we don't expect a response, and this - * is the amount of time we'll wait before we assume - * the frame size exceeds the MTU. - */ - size_t discover_mtu( - const std::string &address, - const std::string &port, - size_t min_frame_size, - size_t max_frame_size, - const double echo_timeout = 0.020 - ) { - const size_t echo_prefix_offset = - uhd::mpmd::mpmd_impl::MPM_ECHO_CMD.size(); - const size_t mtu_hdr_len = echo_prefix_offset + 10; - UHD_ASSERT_THROW(min_frame_size < max_frame_size); - UHD_ASSERT_THROW(min_frame_size % 4 == 0); - UHD_ASSERT_THROW(max_frame_size % 4 == 0); - UHD_ASSERT_THROW(min_frame_size >= echo_prefix_offset + mtu_hdr_len); - using namespace uhd::transport; - // The return port will probably differ from the discovery port, so we - // need a "broadcast" UDP connection; using make_connected() would - // drop packets - udp_simple::sptr udp = udp_simple::make_broadcast(address, port); - std::string send_buf(uhd::mpmd::mpmd_impl::MPM_ECHO_CMD); - send_buf.resize(max_frame_size, '#'); - UHD_ASSERT_THROW(send_buf.size() == max_frame_size); - std::vector<uint8_t> recv_buf; - recv_buf.resize(max_frame_size, ' '); - - // Little helper to check returned packets match the sent ones - auto require_bufs_match = [&recv_buf, &send_buf, mtu_hdr_len]( - const size_t len - ){ - if (len < mtu_hdr_len or std::memcmp( - (void *) &recv_buf[0], - (void *) &send_buf[0], - mtu_hdr_len - ) != 0) { - throw uhd::runtime_error("Unexpected content of MTU " - "discovery return packet!"); - } - }; - UHD_LOG_TRACE("MPMD", "Determining UDP MTU... "); - size_t seq_no = 0; - while (min_frame_size < max_frame_size) { - // Only test multiples of 4 bytes! - const size_t test_frame_size = - (max_frame_size/2 + min_frame_size/2 + 3) & ~size_t(3); - // Encode sequence number and current size in the string, makes it - // easy to debug in code or Wireshark. Is also used for identifying - // response packets. - std::sprintf( - &send_buf[echo_prefix_offset], - ";%04lu,%04lu", - seq_no++, - test_frame_size - ); - UHD_LOG_TRACE("MPMD", "Testing frame size " << test_frame_size); - udp->send(boost::asio::buffer(&send_buf[0], test_frame_size)); - - const size_t len = - udp->recv(boost::asio::buffer(recv_buf), echo_timeout); - if (len == 0) { - // Nothing received, so this is probably too big - max_frame_size = test_frame_size - 4; - } else if (len >= test_frame_size) { - // Size went through, so bump the minimum - require_bufs_match(len); - min_frame_size = test_frame_size; - } else if (len < test_frame_size) { - // This is an odd case. Something must have snipped the packet - // on the way back. Still, we'll just back off and try - // something smaller. - UHD_LOG_DEBUG("MPMD", - "Unexpected packet truncation during MTU discovery."); - require_bufs_match(len); - max_frame_size = len; - } +/*! Do a binary search to discover MTU + * + * Uses the MPM echo service to figure out MTU. We simply send a bunch of + * packets and see if they come back until we converged on the path MTU. + * The end result must lie between \p min_frame_size and \p max_frame_size. + * + * \param address IP address + * \param port UDP port (yeah it's a string!) + * \param min_frame_size Minimum frame size, initialize algorithm to start + * with this value + * \param max_frame_size Maximum frame size, initialize algorithm to start + * with this value + * \param echo_timeout Timeout value in seconds. For frame sizes that + * exceed the MTU, we don't expect a response, and this + * is the amount of time we'll wait before we assume + * the frame size exceeds the MTU. + */ +size_t discover_mtu(const std::string& address, + const std::string& port, + size_t min_frame_size, + size_t max_frame_size, + const double echo_timeout = 0.020) +{ + const size_t echo_prefix_offset = uhd::mpmd::mpmd_impl::MPM_ECHO_CMD.size(); + const size_t mtu_hdr_len = echo_prefix_offset + 10; + UHD_ASSERT_THROW(min_frame_size < max_frame_size); + UHD_ASSERT_THROW(min_frame_size % 4 == 0); + UHD_ASSERT_THROW(max_frame_size % 4 == 0); + UHD_ASSERT_THROW(min_frame_size >= echo_prefix_offset + mtu_hdr_len); + using namespace uhd::transport; + // The return port will probably differ from the discovery port, so we + // need a "broadcast" UDP connection; using make_connected() would + // drop packets + udp_simple::sptr udp = udp_simple::make_broadcast(address, port); + std::string send_buf(uhd::mpmd::mpmd_impl::MPM_ECHO_CMD); + send_buf.resize(max_frame_size, '#'); + UHD_ASSERT_THROW(send_buf.size() == max_frame_size); + std::vector<uint8_t> recv_buf; + recv_buf.resize(max_frame_size, ' '); + + // Little helper to check returned packets match the sent ones + auto require_bufs_match = [&recv_buf, &send_buf, mtu_hdr_len](const size_t len) { + if (len < mtu_hdr_len + or std::memcmp((void*)&recv_buf[0], (void*)&send_buf[0], mtu_hdr_len) != 0) { + throw uhd::runtime_error("Unexpected content of MTU " + "discovery return packet!"); + } + }; + UHD_LOG_TRACE("MPMD", "Determining UDP MTU... "); + size_t seq_no = 0; + while (min_frame_size < max_frame_size) { + // Only test multiples of 4 bytes! + const size_t test_frame_size = (max_frame_size / 2 + min_frame_size / 2 + 3) + & ~size_t(3); + // Encode sequence number and current size in the string, makes it + // easy to debug in code or Wireshark. Is also used for identifying + // response packets. + std::sprintf( + &send_buf[echo_prefix_offset], ";%04lu,%04lu", seq_no++, test_frame_size); + UHD_LOG_TRACE("MPMD", "Testing frame size " << test_frame_size); + udp->send(boost::asio::buffer(&send_buf[0], test_frame_size)); + + const size_t len = udp->recv(boost::asio::buffer(recv_buf), echo_timeout); + if (len == 0) { + // Nothing received, so this is probably too big + max_frame_size = test_frame_size - 4; + } else if (len >= test_frame_size) { + // Size went through, so bump the minimum + require_bufs_match(len); + min_frame_size = test_frame_size; + } else if (len < test_frame_size) { + // This is an odd case. Something must have snipped the packet + // on the way back. Still, we'll just back off and try + // something smaller. + UHD_LOG_DEBUG("MPMD", "Unexpected packet truncation during MTU discovery."); + require_bufs_match(len); + max_frame_size = len; } - UHD_LOG_DEBUG("MPMD", - "Path MTU for address " << address << ": " << min_frame_size); - return min_frame_size; } - + UHD_LOG_DEBUG("MPMD", "Path MTU for address " << address << ": " << min_frame_size); + return min_frame_size; } +} // namespace + -mpmd_xport_ctrl_udp::mpmd_xport_ctrl_udp( - const uhd::device_addr_t& mb_args -) : _mb_args(mb_args) - , _recv_args(filter_args(mb_args, "recv")) - , _send_args(filter_args(mb_args, "send")) - , _available_addrs(get_addrs_from_mb_args(mb_args)) - , _mtu(MPMD_10GE_DATA_FRAME_MAX_SIZE) +mpmd_xport_ctrl_udp::mpmd_xport_ctrl_udp(const uhd::device_addr_t& mb_args) + : _mb_args(mb_args) + , _recv_args(filter_args(mb_args, "recv")) + , _send_args(filter_args(mb_args, "send")) + , _available_addrs(get_addrs_from_mb_args(mb_args)) + , _mtu(MPMD_10GE_DATA_FRAME_MAX_SIZE) { const std::string mpm_discovery_port = _mb_args.get( - mpmd_impl::MPM_DISCOVERY_PORT_KEY, - std::to_string(mpmd_impl::MPM_DISCOVERY_PORT) - ); - auto discover_mtu_for_ip = [mpm_discovery_port](const std::string &ip_addr){ - return discover_mtu( - ip_addr, + mpmd_impl::MPM_DISCOVERY_PORT_KEY, std::to_string(mpmd_impl::MPM_DISCOVERY_PORT)); + auto discover_mtu_for_ip = [mpm_discovery_port](const std::string& ip_addr) { + return discover_mtu(ip_addr, mpm_discovery_port, - IP_PROTOCOL_MIN_MTU_SIZE-IP_PROTOCOL_UDP_PLUS_IP_HEADER, + IP_PROTOCOL_MIN_MTU_SIZE - IP_PROTOCOL_UDP_PLUS_IP_HEADER, MPMD_10GE_DATA_FRAME_MAX_SIZE, - MPMD_MTU_DISCOVERY_TIMEOUT - ); + MPMD_MTU_DISCOVERY_TIMEOUT); }; - for (const auto &ip_addr : _available_addrs) { + for (const auto& ip_addr : _available_addrs) { _mtu = std::min(_mtu, discover_mtu_for_ip(ip_addr)); } } -uhd::both_xports_t -mpmd_xport_ctrl_udp::make_transport( - mpmd_xport_mgr::xport_info_t &xport_info, - const usrp::device3_impl::xport_type_t xport_type, - const uhd::device_addr_t& xport_args_ -) { +uhd::both_xports_t mpmd_xport_ctrl_udp::make_transport( + mpmd_xport_mgr::xport_info_t& xport_info, + const usrp::device3_impl::xport_type_t xport_type, + const uhd::device_addr_t& xport_args_) +{ auto xport_args = xport_args_; if (xport_type == usrp::device3_impl::RX_DATA - and not xport_args.has_key("recv_buff_size")) { - xport_args["recv_buff_size"] = - std::to_string(MPMD_RX_SW_BUFF_SIZE_ETH); + and not xport_args.has_key("recv_buff_size")) { + xport_args["recv_buff_size"] = std::to_string(MPMD_RX_SW_BUFF_SIZE_ETH); } size_t link_speed = MAX_RATE_1GIGE; - if(xport_info.count("link_speed") == 0) - { + if (xport_info.count("link_speed") == 0) { UHD_LOG_WARNING("MPMD", "Could not determine link speed; using 1GibE max speed of " - << MAX_RATE_1GIGE); - } - else{ - link_speed = xport_info.at("link_speed") == "10000"? - MAX_RATE_10GIGE: - MAX_RATE_1GIGE; + << MAX_RATE_1GIGE); + } else { + link_speed = xport_info.at("link_speed") == "10000" ? MAX_RATE_10GIGE + : MAX_RATE_1GIGE; } transport::zero_copy_xport_params default_buff_args; // Create actual UDP transport default_buff_args.recv_frame_size = get_mtu(uhd::RX_DIRECTION); - default_buff_args.recv_buff_size = link_speed * MPMD_BUFFER_FILL_RATE; - default_buff_args.send_buff_size = link_speed * MPMD_BUFFER_FILL_RATE; + default_buff_args.recv_buff_size = link_speed * MPMD_BUFFER_FILL_RATE; + default_buff_args.send_buff_size = link_speed * MPMD_BUFFER_FILL_RATE; if (xport_type == usrp::device3_impl::ASYNC_MSG) { default_buff_args.send_frame_size = MPMD_10GE_ASYNCMSG_FRAME_MAX_SIZE; - }else{ + } else { default_buff_args.send_frame_size = get_mtu(uhd::TX_DIRECTION); } transport::udp_zero_copy::buff_params buff_params; - auto recv = transport::udp_zero_copy::make( - xport_info["ipv4"], + auto recv = transport::udp_zero_copy::make(xport_info["ipv4"], xport_info["port"], default_buff_args, buff_params, - xport_args - ); - const uint16_t port = recv->get_local_port(); + xport_args); + const uint16_t port = recv->get_local_port(); const std::string src_ip_addr = recv->get_local_addr(); - xport_info["src_port"] = std::to_string(port); - xport_info["src_ipv4"] = src_ip_addr; + xport_info["src_port"] = std::to_string(port); + xport_info["src_ipv4"] = src_ip_addr; // Create both_xports_t object and finish: both_xports_t xports; - xports.endianness = uhd::ENDIANNESS_BIG; - xports.send_sid = sid_t(xport_info["send_sid"]); - xports.recv_sid = xports.send_sid.reversed(); + xports.endianness = uhd::ENDIANNESS_BIG; + xports.send_sid = sid_t(xport_info["send_sid"]); + xports.recv_sid = xports.send_sid.reversed(); xports.recv_buff_size = buff_params.recv_buff_size; xports.send_buff_size = buff_params.send_buff_size; - xports.recv = recv; // Note: This is a type cast! - xports.send = recv; // This too + xports.recv = recv; // Note: This is a type cast! + xports.send = recv; // This too return xports; } -bool mpmd_xport_ctrl_udp::is_valid( - const mpmd_xport_mgr::xport_info_t& xport_info -) const { +bool mpmd_xport_ctrl_udp::is_valid(const mpmd_xport_mgr::xport_info_t& xport_info) const +{ return std::find( - _available_addrs.cbegin(), - _available_addrs.cend(), - xport_info.at("ipv4") - ) != _available_addrs.cend(); + _available_addrs.cbegin(), _available_addrs.cend(), xport_info.at("ipv4")) + != _available_addrs.cend(); } size_t mpmd_xport_ctrl_udp::get_mtu(const uhd::direction_t /*dir*/) const diff --git a/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.hpp b/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.hpp index ff7e69361..86301bb2a 100644 --- a/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.hpp +++ b/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.hpp @@ -7,9 +7,9 @@ #ifndef INCLUDED_MPMD_XPORT_ctrl_udp_HPP #define INCLUDED_MPMD_XPORT_ctrl_udp_HPP +#include "../device3/device3_impl.hpp" #include "mpmd_xport_ctrl_base.hpp" #include <uhd/types/device_addr.hpp> -#include "../device3/device3_impl.hpp" namespace uhd { namespace mpmd { namespace xport { @@ -20,23 +20,15 @@ namespace uhd { namespace mpmd { namespace xport { class mpmd_xport_ctrl_udp : public mpmd_xport_ctrl_base { public: - mpmd_xport_ctrl_udp( - const uhd::device_addr_t& mb_args - ); + mpmd_xport_ctrl_udp(const uhd::device_addr_t& mb_args); - both_xports_t make_transport( - mpmd_xport_mgr::xport_info_t& xport_info, + both_xports_t make_transport(mpmd_xport_mgr::xport_info_t& xport_info, const usrp::device3_impl::xport_type_t xport_type, - const uhd::device_addr_t& xport_args - ); + const uhd::device_addr_t& xport_args); - bool is_valid( - const mpmd_xport_mgr::xport_info_t& xport_info - ) const; + bool is_valid(const mpmd_xport_mgr::xport_info_t& xport_info) const; - size_t get_mtu( - const uhd::direction_t dir - ) const; + size_t get_mtu(const uhd::direction_t dir) const; private: const uhd::device_addr_t _mb_args; diff --git a/host/lib/usrp/mpmd/mpmd_xport_mgr.cpp b/host/lib/usrp/mpmd/mpmd_xport_mgr.cpp index a4109b51d..c2200c66a 100644 --- a/host/lib/usrp/mpmd/mpmd_xport_mgr.cpp +++ b/host/lib/usrp/mpmd/mpmd_xport_mgr.cpp @@ -4,18 +4,17 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include "mpmd_impl.hpp" #include "mpmd_xport_mgr.hpp" +#include "mpmd_impl.hpp" #include "mpmd_xport_ctrl_base.hpp" #include "mpmd_xport_ctrl_udp.hpp" #ifdef HAVE_LIBERIO -# include "mpmd_xport_ctrl_liberio.hpp" +# include "mpmd_xport_ctrl_liberio.hpp" #endif uhd::dict<std::string, std::string> uhd::mpmd::xport::filter_args( - const uhd::device_addr_t& args, - const std::string& prefix -) { + const uhd::device_addr_t& args, const std::string& prefix) +{ uhd::dict<std::string, std::string> filtered_args; for (const std::string& key : args.keys()) { if (key.find(prefix) != std::string::npos) { @@ -31,9 +30,7 @@ using namespace uhd::mpmd::xport; class mpmd_xport_mgr_impl : public mpmd_xport_mgr { public: - mpmd_xport_mgr_impl( - const uhd::device_addr_t& mb_args - ) : _mb_args(mb_args) + mpmd_xport_mgr_impl(const uhd::device_addr_t& mb_args) : _mb_args(mb_args) { // nop } @@ -41,36 +38,30 @@ public: /************************************************************************** * API (see mpmd_xport_mgr.hpp) *************************************************************************/ - uhd::both_xports_t make_transport( - const xport_info_list_t &xport_info_list, + uhd::both_xports_t make_transport(const xport_info_list_t& xport_info_list, const uhd::usrp::device3_impl::xport_type_t xport_type, const uhd::device_addr_t& xport_args, - xport_info_t& xport_info_out - ) { - for (const auto &xport_info : xport_info_list) { + xport_info_t& xport_info_out) + { + for (const auto& xport_info : xport_info_list) { require_xport_mgr(xport_info.at("type")); } // Run our incredibly smart selection algorithm - xport_info_out = select_xport_option(xport_info_list); + xport_info_out = select_xport_option(xport_info_list); const std::string xport_medium = xport_info_out.at("type"); - UHD_LOG_TRACE("MPMD", - __func__ << "(): xport medium is " << xport_medium); + UHD_LOG_TRACE("MPMD", __func__ << "(): xport medium is " << xport_medium); UHD_ASSERT_THROW(_xport_ctrls.count(xport_medium) > 0); UHD_ASSERT_THROW(_xport_ctrls.at(xport_medium)); // When we've picked our preferred option, pass it to the transport // implementation for execution: - return _xport_ctrls.at(xport_medium)->make_transport( - xport_info_out, - xport_type, - xport_args - ); + return _xport_ctrls.at(xport_medium) + ->make_transport(xport_info_out, xport_type, xport_args); } - size_t get_mtu( - const uhd::direction_t dir - ) const { + size_t get_mtu(const uhd::direction_t dir) const + { if (_xport_ctrls.empty()) { UHD_LOG_WARNING("MPMD", "Cannot determine MTU, no transport controls have been " @@ -79,7 +70,7 @@ public: } size_t mtu = ~size_t(0); - for (const auto &xport_ctrl_pair : _xport_ctrls) { + for (const auto& xport_ctrl_pair : _xport_ctrls) { mtu = std::min(mtu, xport_ctrl_pair.second->get_mtu(dir)); } @@ -99,21 +90,20 @@ private: * \returns One element of \p xport_info_list based on a selection * algorithm. */ - xport_info_t select_xport_option( - const xport_info_list_t &xport_info_list - ) const { + xport_info_t select_xport_option(const xport_info_list_t& xport_info_list) const + { for (const auto& xport_info : xport_info_list) { const std::string xport_medium = xport_info.at("type"); - if (_xport_ctrls.count(xport_medium) != 0 and - _xport_ctrls.at(xport_medium) and - _xport_ctrls.at(xport_medium)->is_valid(xport_info)) { + if (_xport_ctrls.count(xport_medium) != 0 and _xport_ctrls.at(xport_medium) + and _xport_ctrls.at(xport_medium)->is_valid(xport_info)) { return xport_info; } } - throw uhd::runtime_error("Could not select a transport option! " - "Either a transport hint was not specified or the specified " - "hint does not support communication with RFNoC blocks."); + throw uhd::runtime_error( + "Could not select a transport option! " + "Either a transport hint was not specified or the specified " + "hint does not support communication with RFNoC blocks."); } //! Create an instance of an xport manager implementation @@ -121,22 +111,17 @@ private: // \param xport_medium "UDP" or "liberio" // \param mb_args Device args mpmd_xport_ctrl_base::uptr make_mgr_impl( - const std::string &xport_medium, - const uhd::device_addr_t& mb_args - ) const { + const std::string& xport_medium, const uhd::device_addr_t& mb_args) const + { if (xport_medium == "UDP") { - return mpmd_xport_ctrl_base::uptr( - new mpmd_xport_ctrl_udp(mb_args) - ); + return mpmd_xport_ctrl_base::uptr(new mpmd_xport_ctrl_udp(mb_args)); #ifdef HAVE_LIBERIO } else if (xport_medium == "liberio") { - return mpmd_xport_ctrl_base::uptr( - new mpmd_xport_ctrl_liberio(mb_args) - ); + return mpmd_xport_ctrl_base::uptr(new mpmd_xport_ctrl_liberio(mb_args)); #endif } else { - UHD_LOG_WARNING("MPMD", - "Cannot instantiate transport medium " << xport_medium); + UHD_LOG_WARNING( + "MPMD", "Cannot instantiate transport medium " << xport_medium); return nullptr; } } @@ -150,11 +135,11 @@ private: // \param xport_medium Type of transport, e.g. "UDP", "liberio", ... // // \throws uhd::key_error if \p xport_medium is not known or registered - void require_xport_mgr(const std::string &xport_medium) + void require_xport_mgr(const std::string& xport_medium) { if (_xport_ctrls.count(xport_medium) == 0) { - UHD_LOG_TRACE("MPMD", - "Instantiating transport manager `" << xport_medium << "'"); + UHD_LOG_TRACE( + "MPMD", "Instantiating transport manager `" << xport_medium << "'"); auto mgr_impl = make_mgr_impl(xport_medium, _mb_args); if (mgr_impl) { _xport_ctrls[xport_medium] = std::move(mgr_impl); @@ -174,9 +159,7 @@ private: const uhd::device_addr_t _mb_args; }; -mpmd_xport_mgr::uptr mpmd_xport_mgr::make( - const uhd::device_addr_t& mb_args -) { +mpmd_xport_mgr::uptr mpmd_xport_mgr::make(const uhd::device_addr_t& mb_args) +{ return mpmd_xport_mgr::uptr(new mpmd_xport_mgr_impl(mb_args)); } - diff --git a/host/lib/usrp/mpmd/mpmd_xport_mgr.hpp b/host/lib/usrp/mpmd/mpmd_xport_mgr.hpp index 72700e69a..3d96e5ec6 100644 --- a/host/lib/usrp/mpmd/mpmd_xport_mgr.hpp +++ b/host/lib/usrp/mpmd/mpmd_xport_mgr.hpp @@ -9,10 +9,10 @@ #include "../device3/device3_impl.hpp" #include <uhd/types/dict.hpp> -#include <memory> #include <map> -#include <vector> +#include <memory> #include <string> +#include <vector> namespace uhd { namespace mpmd { namespace xport { @@ -21,11 +21,11 @@ namespace uhd { namespace mpmd { namespace xport { */ //! Ethernet address for management and RPC communication -const std::string MGMT_ADDR_KEY = "mgmt_addr"; +const std::string MGMT_ADDR_KEY = "mgmt_addr"; //! Primary Ethernet address for streaming and RFNoC communication -const std::string FIRST_ADDR_KEY = "addr"; +const std::string FIRST_ADDR_KEY = "addr"; //! Secondary Ethernet address for streaming and RFNoC communication -const std::string SECOND_ADDR_KEY = "second_addr"; +const std::string SECOND_ADDR_KEY = "second_addr"; /*! Return filtered subset from a device_addr_t * @@ -36,9 +36,7 @@ const std::string SECOND_ADDR_KEY = "second_addr"; * \param prefix Key prefix to match against */ uhd::dict<std::string, std::string> filter_args( - const uhd::device_addr_t& args, - const std::string& prefix -); + const uhd::device_addr_t& args, const std::string& prefix); /*! MPMD Transport Manager * @@ -50,8 +48,8 @@ uhd::dict<std::string, std::string> filter_args( class mpmd_xport_mgr { public: - using uptr = std::unique_ptr<mpmd_xport_mgr>; - using xport_info_t = std::map<std::string, std::string>; + using uptr = std::unique_ptr<mpmd_xport_mgr>; + using xport_info_t = std::map<std::string, std::string>; using xport_info_list_t = std::vector<std::map<std::string, std::string>>; virtual ~mpmd_xport_mgr() {} @@ -65,9 +63,7 @@ public: * \throws uhd::key_error if \p xport_medium is not supported. The ctor of * the underlying class that is requested can also throw. */ - static uptr make( - const uhd::device_addr_t& mb_args - ); + static uptr make(const uhd::device_addr_t& mb_args); /*! Create a transports object * @@ -94,18 +90,14 @@ public: * The latter needs to get sent back to MPM to complete the * transport handshake. */ - virtual both_xports_t make_transport( - const xport_info_list_t &xport_info_list, + virtual both_xports_t make_transport(const xport_info_list_t& xport_info_list, const usrp::device3_impl::xport_type_t xport_type, const uhd::device_addr_t& xport_args, - xport_info_t& xport_info_out - ) = 0; + xport_info_t& xport_info_out) = 0; /*! Return the path MTU for whatever this manager lets us do */ - virtual size_t get_mtu( - const uhd::direction_t dir - ) const = 0; + virtual size_t get_mtu(const uhd::direction_t dir) const = 0; }; }}} /* namespace uhd::mpmd::xport */ diff --git a/host/lib/usrp/x300/x300_adc_ctrl.cpp b/host/lib/usrp/x300/x300_adc_ctrl.cpp index b8101753f..26c1d85ff 100644 --- a/host/lib/usrp/x300/x300_adc_ctrl.cpp +++ b/host/lib/usrp/x300/x300_adc_ctrl.cpp @@ -7,14 +7,15 @@ #include "x300_adc_ctrl.hpp" #include "ads62p48_regs.hpp" +#include <uhd/exception.hpp> #include <uhd/types/ranges.hpp> #include <uhd/utils/log.hpp> #include <uhd/utils/safe_call.hpp> -#include <uhd/exception.hpp> using namespace uhd; -x300_adc_ctrl::~x300_adc_ctrl(void){ +x300_adc_ctrl::~x300_adc_ctrl(void) +{ /* NOP */ } @@ -24,26 +25,26 @@ x300_adc_ctrl::~x300_adc_ctrl(void){ class x300_adc_ctrl_impl : public x300_adc_ctrl { public: - x300_adc_ctrl_impl(uhd::spi_iface::sptr iface, const size_t slaveno): - _iface(iface), _slaveno(slaveno) + x300_adc_ctrl_impl(uhd::spi_iface::sptr iface, const size_t slaveno) + : _iface(iface), _slaveno(slaveno) { init(); } void init() { - //power-up adc - _ads62p48_regs.reset = 1; - this->send_ads62p48_reg(0x00); //issue a reset to the ADC - _ads62p48_regs.reset = 0; + // power-up adc + _ads62p48_regs.reset = 1; + this->send_ads62p48_reg(0x00); // issue a reset to the ADC + _ads62p48_regs.reset = 0; _ads62p48_regs.enable_low_speed_mode = 0; - _ads62p48_regs.ref = ads62p48_regs_t::REF_INTERNAL; - _ads62p48_regs.standby = ads62p48_regs_t::STANDBY_NORMAL; - _ads62p48_regs.power_down = ads62p48_regs_t::POWER_DOWN_NORMAL; - _ads62p48_regs.lvds_cmos = ads62p48_regs_t::LVDS_CMOS_DDR_LVDS; - _ads62p48_regs.channel_control = ads62p48_regs_t::CHANNEL_CONTROL_INDEPENDENT; - _ads62p48_regs.data_format = ads62p48_regs_t::DATA_FORMAT_2S_COMPLIMENT; + _ads62p48_regs.ref = ads62p48_regs_t::REF_INTERNAL; + _ads62p48_regs.standby = ads62p48_regs_t::STANDBY_NORMAL; + _ads62p48_regs.power_down = ads62p48_regs_t::POWER_DOWN_NORMAL; + _ads62p48_regs.lvds_cmos = ads62p48_regs_t::LVDS_CMOS_DDR_LVDS; + _ads62p48_regs.channel_control = ads62p48_regs_t::CHANNEL_CONTROL_INDEPENDENT; + _ads62p48_regs.data_format = ads62p48_regs_t::DATA_FORMAT_2S_COMPLIMENT; _ads62p48_regs.clk_out_pos_edge = ads62p48_regs_t::CLK_OUT_POS_EDGE_MINUS4_26; _ads62p48_regs.clk_out_neg_edge = ads62p48_regs_t::CLK_OUT_NEG_EDGE_MINUS4_26; @@ -67,7 +68,6 @@ public: this->send_ads62p48_reg(0x6a); this->send_ads62p48_reg(0x75); this->send_ads62p48_reg(0x76); - } void reset() @@ -75,31 +75,42 @@ public: init(); } - double set_gain(const double &gain) + double set_gain(const double& gain) { const meta_range_t gain_range = meta_range_t(0, 6.0, 0.5); - const int gain_bits = int((gain_range.clip(gain)*2.0) + 0.5); - _ads62p48_regs.gain_chA = gain_bits; - _ads62p48_regs.gain_chB = gain_bits; + const int gain_bits = int((gain_range.clip(gain) * 2.0) + 0.5); + _ads62p48_regs.gain_chA = gain_bits; + _ads62p48_regs.gain_chB = gain_bits; this->send_ads62p48_reg(0x55); this->send_ads62p48_reg(0x68); - return gain_bits/2; + return gain_bits / 2; } - void set_test_word(const std::string &patterna, const std::string &patternb, const uint32_t num) + void set_test_word( + const std::string& patterna, const std::string& patternb, const uint32_t num) { - _ads62p48_regs.custom_pattern_low = num & 0xff; + _ads62p48_regs.custom_pattern_low = num & 0xff; _ads62p48_regs.custom_pattern_high = num >> 8; - if (patterna == "ones") _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_ONES; - if (patterna == "zeros") _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_ZEROS; - if (patterna == "custom") _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_CUSTOM; - if (patterna == "ramp") _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_RAMP; - if (patterna == "normal") _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_NORMAL; - if (patternb == "ones") _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_ONES; - if (patternb == "zeros") _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_ZEROS; - if (patternb == "custom") _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_CUSTOM; - if (patterna == "ramp") _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_RAMP; - if (patterna == "normal") _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_NORMAL; + if (patterna == "ones") + _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_ONES; + if (patterna == "zeros") + _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_ZEROS; + if (patterna == "custom") + _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_CUSTOM; + if (patterna == "ramp") + _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_RAMP; + if (patterna == "normal") + _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_NORMAL; + if (patternb == "ones") + _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_ONES; + if (patternb == "zeros") + _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_ZEROS; + if (patternb == "custom") + _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_CUSTOM; + if (patterna == "ramp") + _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_RAMP; + if (patterna == "normal") + _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_NORMAL; this->send_ads62p48_reg(0x51); this->send_ads62p48_reg(0x52); this->send_ads62p48_reg(0x62); @@ -109,10 +120,7 @@ public: ~x300_adc_ctrl_impl(void) { _ads62p48_regs.power_down = ads62p48_regs_t::POWER_DOWN_GLOBAL; - UHD_SAFE_CALL - ( - this->send_ads62p48_reg(0x40); - ) + UHD_SAFE_CALL(this->send_ads62p48_reg(0x40);) } private: diff --git a/host/lib/usrp/x300/x300_adc_ctrl.hpp b/host/lib/usrp/x300/x300_adc_ctrl.hpp index eb29dd28f..106d79eed 100644 --- a/host/lib/usrp/x300/x300_adc_ctrl.hpp +++ b/host/lib/usrp/x300/x300_adc_ctrl.hpp @@ -27,9 +27,10 @@ public: */ static sptr make(uhd::spi_iface::sptr iface, const size_t slaveno); - virtual double set_gain(const double &) = 0; + virtual double set_gain(const double&) = 0; - virtual void set_test_word(const std::string &patterna, const std::string &patternb, const uint32_t = 0) = 0; + virtual void set_test_word( + const std::string& patterna, const std::string& patternb, const uint32_t = 0) = 0; virtual void reset(void) = 0; }; diff --git a/host/lib/usrp/x300/x300_clock_ctrl.cpp b/host/lib/usrp/x300/x300_clock_ctrl.cpp index 93e02ca7d..a867a9138 100644 --- a/host/lib/usrp/x300/x300_clock_ctrl.cpp +++ b/host/lib/usrp/x300/x300_clock_ctrl.cpp @@ -5,32 +5,43 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include "lmk04816_regs.hpp" #include "x300_clock_ctrl.hpp" +#include "lmk04816_regs.hpp" #include "x300_defaults.hpp" -#include <uhd/utils/safe_call.hpp> #include <uhd/utils/math.hpp> +#include <uhd/utils/safe_call.hpp> #include <stdint.h> #include <boost/format.hpp> #include <boost/math/special_functions/round.hpp> -#include <stdexcept> #include <cmath> #include <cstdlib> +#include <stdexcept> -static const double X300_REF_CLK_OUT_RATE = 10e6; +static const double X300_REF_CLK_OUT_RATE = 10e6; static const uint16_t X300_MAX_CLKOUT_DIV = 1045; -constexpr double MIN_VCO_FREQ = 2370e6; -constexpr double MAX_VCO_FREQ = 2600e6; -constexpr double VCXO_FREQ = 96.0e6; // VCXO runs at 96MHz -constexpr int VCXO_PLL2_N = 2; // Assume that the PLL2 N predivider is set to /2. - -struct x300_clk_delays { - x300_clk_delays() : - fpga_dly_ns(0.0),adc_dly_ns(0.0),dac_dly_ns(0.0),db_rx_dly_ns(0.0),db_tx_dly_ns(0.0) - {} - x300_clk_delays(double fpga, double adc, double dac, double db_rx, double db_tx) : - fpga_dly_ns(fpga),adc_dly_ns(adc),dac_dly_ns(dac),db_rx_dly_ns(db_rx),db_tx_dly_ns(db_tx) - {} +constexpr double MIN_VCO_FREQ = 2370e6; +constexpr double MAX_VCO_FREQ = 2600e6; +constexpr double VCXO_FREQ = 96.0e6; // VCXO runs at 96MHz +constexpr int VCXO_PLL2_N = 2; // Assume that the PLL2 N predivider is set to /2. + +struct x300_clk_delays +{ + x300_clk_delays() + : fpga_dly_ns(0.0) + , adc_dly_ns(0.0) + , dac_dly_ns(0.0) + , db_rx_dly_ns(0.0) + , db_tx_dly_ns(0.0) + { + } + x300_clk_delays(double fpga, double adc, double dac, double db_rx, double db_tx) + : fpga_dly_ns(fpga) + , adc_dly_ns(adc) + , dac_dly_ns(dac) + , db_rx_dly_ns(db_rx) + , db_tx_dly_ns(db_tx) + { + } double fpga_dly_ns; double adc_dly_ns; @@ -51,14 +62,14 @@ static const x300_clk_delays X300_REV7_CLK_DELAYS = x300_clk_delays( using namespace uhd; using namespace uhd::math::fp_compare; -x300_clock_ctrl::~x300_clock_ctrl(void){ +x300_clock_ctrl::~x300_clock_ctrl(void) +{ /* NOP */ } -class x300_clock_ctrl_impl : public x300_clock_ctrl { - +class x300_clock_ctrl_impl : public x300_clock_ctrl +{ public: - ~x300_clock_ctrl_impl(void) {} x300_clock_ctrl_impl(uhd::spi_iface::sptr spiface, @@ -66,18 +77,19 @@ public: const size_t hw_rev, const double master_clock_rate, const double dboard_clock_rate, - const double system_ref_rate): - _spiface(spiface), - _slaveno(static_cast<int>(slaveno)), - _hw_rev(hw_rev), - _master_clock_rate(master_clock_rate), - _dboard_clock_rate(dboard_clock_rate), - _system_ref_rate(system_ref_rate) + const double system_ref_rate) + : _spiface(spiface) + , _slaveno(static_cast<int>(slaveno)) + , _hw_rev(hw_rev) + , _master_clock_rate(master_clock_rate) + , _dboard_clock_rate(dboard_clock_rate) + , _system_ref_rate(system_ref_rate) { init(); } - void reset_clocks() { + void reset_clocks() + { _lmk04816_regs.RESET = lmk04816_regs_t::RESET_RESET; this->write_regs(0); _lmk04816_regs.RESET = lmk04816_regs_t::RESET_NO_RESET; @@ -90,52 +102,56 @@ public: sync_clocks(); } - void sync_clocks(void) { - //soft sync: - //put the sync IO into output mode - FPGA must be input - //write low, then write high - this triggers a soft sync + void sync_clocks(void) + { + // soft sync: + // put the sync IO into output mode - FPGA must be input + // write low, then write high - this triggers a soft sync _lmk04816_regs.SYNC_POL_INV = lmk04816_regs_t::SYNC_POL_INV_SYNC_LOW; this->write_regs(11); _lmk04816_regs.SYNC_POL_INV = lmk04816_regs_t::SYNC_POL_INV_SYNC_HIGH; this->write_regs(11); } - double get_master_clock_rate(void) { + double get_master_clock_rate(void) + { return _master_clock_rate; } - double get_sysref_clock_rate(void) { + double get_sysref_clock_rate(void) + { return _system_ref_rate; } - double get_refout_clock_rate(void) { - //We support only one reference output rate + double get_refout_clock_rate(void) + { + // We support only one reference output rate return X300_REF_CLK_OUT_RATE; } - void set_dboard_rate(const x300_clock_which_t which, double rate) { - uint16_t div = uint16_t(_vco_freq / rate); - uint16_t *reg = NULL; - uint8_t addr = 0xFF; + void set_dboard_rate(const x300_clock_which_t which, double rate) + { + uint16_t div = uint16_t(_vco_freq / rate); + uint16_t* reg = NULL; + uint8_t addr = 0xFF; // Make sure requested rate is an even divisor of the VCO frequency if (not math::frequencies_are_equal(_vco_freq / div, rate)) throw uhd::value_error("invalid dboard rate requested"); - switch (which) - { - case X300_CLOCK_WHICH_DB0_RX: - case X300_CLOCK_WHICH_DB1_RX: - reg = &_lmk04816_regs.CLKout2_3_DIV; - addr = 1; - break; - case X300_CLOCK_WHICH_DB0_TX: - case X300_CLOCK_WHICH_DB1_TX: - reg = &_lmk04816_regs.CLKout4_5_DIV; - addr = 2; - break; - default: - UHD_THROW_INVALID_CODE_PATH(); + switch (which) { + case X300_CLOCK_WHICH_DB0_RX: + case X300_CLOCK_WHICH_DB1_RX: + reg = &_lmk04816_regs.CLKout2_3_DIV; + addr = 1; + break; + case X300_CLOCK_WHICH_DB0_TX: + case X300_CLOCK_WHICH_DB1_TX: + reg = &_lmk04816_regs.CLKout4_5_DIV; + addr = 2; + break; + default: + UHD_THROW_INVALID_CODE_PATH(); } if (*reg == div) @@ -143,13 +159,15 @@ public: // Since the clock rate on one daughter board cannot be changed without // affecting the other daughter board, don't allow it. - throw uhd::not_implemented_error("x3xx set dboard clock rate does not support changing the clock rate"); + throw uhd::not_implemented_error( + "x3xx set dboard clock rate does not support changing the clock rate"); // This is open source code and users may need to enable this function // to support other daughterboards. If so, comment out the line above // that throws the error and allow the program to reach the code below. - // The LMK04816 datasheet says the register must be written twice if SYNC is enabled + // The LMK04816 datasheet says the register must be written twice if SYNC is + // enabled *reg = div; write_regs(addr); write_regs(addr); @@ -159,18 +177,17 @@ public: double get_dboard_rate(const x300_clock_which_t which) { double rate = 0.0; - switch (which) - { - case X300_CLOCK_WHICH_DB0_RX: - case X300_CLOCK_WHICH_DB1_RX: - rate = _vco_freq / _lmk04816_regs.CLKout2_3_DIV; - break; - case X300_CLOCK_WHICH_DB0_TX: - case X300_CLOCK_WHICH_DB1_TX: - rate = _vco_freq / _lmk04816_regs.CLKout4_5_DIV; - break; - default: - UHD_THROW_INVALID_CODE_PATH(); + switch (which) { + case X300_CLOCK_WHICH_DB0_RX: + case X300_CLOCK_WHICH_DB1_RX: + rate = _vco_freq / _lmk04816_regs.CLKout2_3_DIV; + break; + case X300_CLOCK_WHICH_DB0_TX: + case X300_CLOCK_WHICH_DB1_TX: + rate = _vco_freq / _lmk04816_regs.CLKout4_5_DIV; + break; + default: + UHD_THROW_INVALID_CODE_PATH(); } return rate; } @@ -178,49 +195,63 @@ public: std::vector<double> get_dboard_rates(const x300_clock_which_t) { std::vector<double> rates; - for (size_t div = size_t(_vco_freq / _master_clock_rate); div <= X300_MAX_CLKOUT_DIV; div++) + for (size_t div = size_t(_vco_freq / _master_clock_rate); + div <= X300_MAX_CLKOUT_DIV; + div++) rates.push_back(_vco_freq / div); return rates; } void enable_dboard_clock(const x300_clock_which_t which, const bool enable) { - switch (which) - { - case X300_CLOCK_WHICH_DB0_RX: - if (enable != (_lmk04816_regs.CLKout2_TYPE == lmk04816_regs_t::CLKOUT2_TYPE_LVPECL_700MVPP)) - { - _lmk04816_regs.CLKout2_TYPE = enable ? lmk04816_regs_t::CLKOUT2_TYPE_LVPECL_700MVPP : lmk04816_regs_t::CLKOUT2_TYPE_P_DOWN; - write_regs(6); - } - break; - case X300_CLOCK_WHICH_DB1_RX: - if (enable != (_lmk04816_regs.CLKout3_TYPE == lmk04816_regs_t::CLKOUT3_TYPE_LVPECL_700MVPP)) - { - _lmk04816_regs.CLKout3_TYPE = enable ? lmk04816_regs_t::CLKOUT3_TYPE_LVPECL_700MVPP : lmk04816_regs_t::CLKOUT3_TYPE_P_DOWN; - write_regs(6); - } - break; - case X300_CLOCK_WHICH_DB0_TX: - if (enable != (_lmk04816_regs.CLKout5_TYPE == lmk04816_regs_t::CLKOUT5_TYPE_LVPECL_700MVPP)) - { - _lmk04816_regs.CLKout5_TYPE = enable ? lmk04816_regs_t::CLKOUT5_TYPE_LVPECL_700MVPP : lmk04816_regs_t::CLKOUT5_TYPE_P_DOWN; - write_regs(7); - } - break; - case X300_CLOCK_WHICH_DB1_TX: - if (enable != (_lmk04816_regs.CLKout4_TYPE == lmk04816_regs_t::CLKOUT4_TYPE_LVPECL_700MVPP)) - { - _lmk04816_regs.CLKout4_TYPE = enable ? lmk04816_regs_t::CLKOUT4_TYPE_LVPECL_700MVPP : lmk04816_regs_t::CLKOUT4_TYPE_P_DOWN; - write_regs(7); - } - break; - default: - UHD_THROW_INVALID_CODE_PATH(); + switch (which) { + case X300_CLOCK_WHICH_DB0_RX: + if (enable + != (_lmk04816_regs.CLKout2_TYPE + == lmk04816_regs_t::CLKOUT2_TYPE_LVPECL_700MVPP)) { + _lmk04816_regs.CLKout2_TYPE = + enable ? lmk04816_regs_t::CLKOUT2_TYPE_LVPECL_700MVPP + : lmk04816_regs_t::CLKOUT2_TYPE_P_DOWN; + write_regs(6); + } + break; + case X300_CLOCK_WHICH_DB1_RX: + if (enable + != (_lmk04816_regs.CLKout3_TYPE + == lmk04816_regs_t::CLKOUT3_TYPE_LVPECL_700MVPP)) { + _lmk04816_regs.CLKout3_TYPE = + enable ? lmk04816_regs_t::CLKOUT3_TYPE_LVPECL_700MVPP + : lmk04816_regs_t::CLKOUT3_TYPE_P_DOWN; + write_regs(6); + } + break; + case X300_CLOCK_WHICH_DB0_TX: + if (enable + != (_lmk04816_regs.CLKout5_TYPE + == lmk04816_regs_t::CLKOUT5_TYPE_LVPECL_700MVPP)) { + _lmk04816_regs.CLKout5_TYPE = + enable ? lmk04816_regs_t::CLKOUT5_TYPE_LVPECL_700MVPP + : lmk04816_regs_t::CLKOUT5_TYPE_P_DOWN; + write_regs(7); + } + break; + case X300_CLOCK_WHICH_DB1_TX: + if (enable + != (_lmk04816_regs.CLKout4_TYPE + == lmk04816_regs_t::CLKOUT4_TYPE_LVPECL_700MVPP)) { + _lmk04816_regs.CLKout4_TYPE = + enable ? lmk04816_regs_t::CLKOUT4_TYPE_LVPECL_700MVPP + : lmk04816_regs_t::CLKOUT4_TYPE_P_DOWN; + write_regs(7); + } + break; + default: + UHD_THROW_INVALID_CODE_PATH(); } } - void set_ref_out(const bool enable) { + void set_ref_out(const bool enable) + { // TODO Implement divider configuration to allow for configurable output // rates if (enable) @@ -230,44 +261,48 @@ public: this->write_regs(8); } - void write_regs(uint8_t addr) { + void write_regs(uint8_t addr) + { uint32_t data = _lmk04816_regs.get_reg(addr); - _spiface->write_spi(_slaveno, spi_config_t::EDGE_RISE, data,32); + _spiface->write_spi(_slaveno, spi_config_t::EDGE_RISE, data, 32); } - double set_clock_delay(const x300_clock_which_t which, const double delay_ns, const bool resync = true) { - //All dividers have are delayed by 5 taps by default. The delay - //set by this function is relative to the 5 tap delay - static const uint16_t DDLY_MIN_TAPS = 5; - static const uint16_t DDLY_MAX_TAPS = 522; //Extended mode + double set_clock_delay( + const x300_clock_which_t which, const double delay_ns, const bool resync = true) + { + // All dividers have are delayed by 5 taps by default. The delay + // set by this function is relative to the 5 tap delay + static const uint16_t DDLY_MIN_TAPS = 5; + static const uint16_t DDLY_MAX_TAPS = 522; // Extended mode - //The resolution and range of the analog delay is fixed + // The resolution and range of the analog delay is fixed static const double ADLY_RES_NS = 0.025; static const double ADLY_MIN_NS = 0.500; static const double ADLY_MAX_NS = 0.975; - //Each digital tap delays the clock by one VCO period - double vco_period_ns = 1.0e9/_vco_freq; - double half_vco_period_ns = vco_period_ns/2.0; + // Each digital tap delays the clock by one VCO period + double vco_period_ns = 1.0e9 / _vco_freq; + double half_vco_period_ns = vco_period_ns / 2.0; - //Implement as much of the requested delay using digital taps. Whatever is leftover - //will be made up using the analog delay element and the half-cycle digital tap. - //A caveat here is that the analog delay starts at ADLY_MIN_NS, so we need to back off - //by that much when coming up with the digital taps so that the difference can be made - //up using the analog delay. + // Implement as much of the requested delay using digital taps. Whatever is + // leftover will be made up using the analog delay element and the half-cycle + // digital tap. A caveat here is that the analog delay starts at ADLY_MIN_NS, so + // we need to back off by that much when coming up with the digital taps so that + // the difference can be made up using the analog delay. uint16_t ddly_taps = 0; if (delay_ns < ADLY_MIN_NS) { - ddly_taps = static_cast<uint16_t>(std::floor((delay_ns)/vco_period_ns)); + ddly_taps = static_cast<uint16_t>(std::floor((delay_ns) / vco_period_ns)); } else { - ddly_taps = static_cast<uint16_t>(std::floor((delay_ns-ADLY_MIN_NS)/vco_period_ns)); + ddly_taps = static_cast<uint16_t>( + std::floor((delay_ns - ADLY_MIN_NS) / vco_period_ns)); } double leftover_delay = delay_ns - (vco_period_ns * ddly_taps); - //Compute settings - uint16_t ddly_value = ddly_taps + DDLY_MIN_TAPS; - bool adly_en = false; - uint8_t adly_value = 0; - uint8_t half_shift_en = 0; + // Compute settings + uint16_t ddly_value = ddly_taps + DDLY_MIN_TAPS; + bool adly_en = false; + uint8_t adly_value = 0; + uint8_t half_shift_en = 0; if (ddly_value > DDLY_MAX_TAPS) { throw uhd::value_error("set_clock_delay: Requested delay is out of range."); @@ -275,172 +310,203 @@ public: double coerced_delay = (vco_period_ns * ddly_taps); if (leftover_delay > ADLY_MAX_NS) { - //The VCO is running too slowly for us to compensate the digital delay difference using - //analog delay. Do the best we can. - adly_en = true; - adly_value = static_cast<uint8_t>(boost::math::round((ADLY_MAX_NS-ADLY_MIN_NS)/ADLY_RES_NS)); + // The VCO is running too slowly for us to compensate the digital delay + // difference using analog delay. Do the best we can. + adly_en = true; + adly_value = static_cast<uint8_t>( + boost::math::round((ADLY_MAX_NS - ADLY_MIN_NS) / ADLY_RES_NS)); coerced_delay += ADLY_MAX_NS; } else if (leftover_delay >= ADLY_MIN_NS && leftover_delay <= ADLY_MAX_NS) { - //The leftover delay can be compensated by the analog delay up to the analog delay resolution - adly_en = true; - adly_value = static_cast<uint8_t>(boost::math::round((leftover_delay-ADLY_MIN_NS)/ADLY_RES_NS)); - coerced_delay += ADLY_MIN_NS+(ADLY_RES_NS*adly_value); - } else if (leftover_delay >= (ADLY_MIN_NS - half_vco_period_ns) && leftover_delay < ADLY_MIN_NS) { - //The leftover delay if less than the minimum supported analog delay but if we move the digital - //delay back by half a VCO cycle then it will be in the range of the analog delay. So do that! - adly_en = true; - adly_value = static_cast<uint8_t>(boost::math::round((leftover_delay+half_vco_period_ns-ADLY_MIN_NS)/ADLY_RES_NS)); + // The leftover delay can be compensated by the analog delay up to the analog + // delay resolution + adly_en = true; + adly_value = static_cast<uint8_t>( + boost::math::round((leftover_delay - ADLY_MIN_NS) / ADLY_RES_NS)); + coerced_delay += ADLY_MIN_NS + (ADLY_RES_NS * adly_value); + } else if (leftover_delay >= (ADLY_MIN_NS - half_vco_period_ns) + && leftover_delay < ADLY_MIN_NS) { + // The leftover delay if less than the minimum supported analog delay but if + // we move the digital delay back by half a VCO cycle then it will be in the + // range of the analog delay. So do that! + adly_en = true; + adly_value = static_cast<uint8_t>(boost::math::round( + (leftover_delay + half_vco_period_ns - ADLY_MIN_NS) / ADLY_RES_NS)); half_shift_en = 1; - coerced_delay += ADLY_MIN_NS+(ADLY_RES_NS*adly_value)-half_vco_period_ns; + coerced_delay += + ADLY_MIN_NS + (ADLY_RES_NS * adly_value) - half_vco_period_ns; } else { - //Even after moving the digital delay back by half a cycle, we cannot make up the difference - //so give up on compensating for the difference from the digital delay tap. - //If control reaches here then the value of leftover_delay is possible very small and will still - //be close to what the client requested. + // Even after moving the digital delay back by half a cycle, we cannot make up + // the difference so give up on compensating for the difference from the + // digital delay tap. If control reaches here then the value of leftover_delay + // is possible very small and will still be close to what the client + // requested. } - UHD_LOG_DEBUG("X300", boost::format("x300_clock_ctrl::set_clock_delay: Which=%d, Requested=%f, Digital Taps=%d, Half Shift=%d, Analog Delay=%d (%s), Coerced Delay=%fns" - ) % which % delay_ns % ddly_value % (half_shift_en?"ON":"OFF") % ((int)adly_value) % (adly_en?"ON":"OFF") % coerced_delay) - - //Apply settings - switch (which) - { - case X300_CLOCK_WHICH_FPGA: - _lmk04816_regs.CLKout0_1_DDLY = ddly_value; - _lmk04816_regs.CLKout0_1_HS = half_shift_en; - if (adly_en) { - _lmk04816_regs.CLKout0_ADLY_SEL = lmk04816_regs_t::CLKOUT0_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout1_ADLY_SEL = lmk04816_regs_t::CLKOUT1_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout0_1_ADLY = adly_value; - } else { - _lmk04816_regs.CLKout0_ADLY_SEL = lmk04816_regs_t::CLKOUT0_ADLY_SEL_D_PD; - _lmk04816_regs.CLKout1_ADLY_SEL = lmk04816_regs_t::CLKOUT1_ADLY_SEL_D_PD; - } - write_regs(0); - write_regs(6); - _delays.fpga_dly_ns = coerced_delay; - break; - case X300_CLOCK_WHICH_DB0_RX: - case X300_CLOCK_WHICH_DB1_RX: - _lmk04816_regs.CLKout2_3_DDLY = ddly_value; - _lmk04816_regs.CLKout2_3_HS = half_shift_en; - if (adly_en) { - _lmk04816_regs.CLKout2_ADLY_SEL = lmk04816_regs_t::CLKOUT2_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout3_ADLY_SEL = lmk04816_regs_t::CLKOUT3_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout2_3_ADLY = adly_value; - } else { - _lmk04816_regs.CLKout2_ADLY_SEL = lmk04816_regs_t::CLKOUT2_ADLY_SEL_D_PD; - _lmk04816_regs.CLKout3_ADLY_SEL = lmk04816_regs_t::CLKOUT3_ADLY_SEL_D_PD; - } - write_regs(1); - write_regs(6); - _delays.db_rx_dly_ns = coerced_delay; - break; - case X300_CLOCK_WHICH_DB0_TX: - case X300_CLOCK_WHICH_DB1_TX: - _lmk04816_regs.CLKout4_5_DDLY = ddly_value; - _lmk04816_regs.CLKout4_5_HS = half_shift_en; - if (adly_en) { - _lmk04816_regs.CLKout4_ADLY_SEL = lmk04816_regs_t::CLKOUT4_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout5_ADLY_SEL = lmk04816_regs_t::CLKOUT5_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout4_5_ADLY = adly_value; - } else { - _lmk04816_regs.CLKout4_ADLY_SEL = lmk04816_regs_t::CLKOUT4_ADLY_SEL_D_PD; - _lmk04816_regs.CLKout5_ADLY_SEL = lmk04816_regs_t::CLKOUT5_ADLY_SEL_D_PD; - } - write_regs(2); - write_regs(7); - _delays.db_tx_dly_ns = coerced_delay; - break; - case X300_CLOCK_WHICH_DAC0: - case X300_CLOCK_WHICH_DAC1: - _lmk04816_regs.CLKout6_7_DDLY = ddly_value; - _lmk04816_regs.CLKout6_7_HS = half_shift_en; - if (adly_en) { - _lmk04816_regs.CLKout6_ADLY_SEL = lmk04816_regs_t::CLKOUT6_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout7_ADLY_SEL = lmk04816_regs_t::CLKOUT7_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout6_7_ADLY = adly_value; - } else { - _lmk04816_regs.CLKout6_ADLY_SEL = lmk04816_regs_t::CLKOUT6_ADLY_SEL_D_PD; - _lmk04816_regs.CLKout7_ADLY_SEL = lmk04816_regs_t::CLKOUT7_ADLY_SEL_D_PD; - } - write_regs(3); - write_regs(7); - _delays.dac_dly_ns = coerced_delay; - break; - case X300_CLOCK_WHICH_ADC0: - case X300_CLOCK_WHICH_ADC1: - _lmk04816_regs.CLKout8_9_DDLY = ddly_value; - _lmk04816_regs.CLKout8_9_HS = half_shift_en; - if (adly_en) { - _lmk04816_regs.CLKout8_ADLY_SEL = lmk04816_regs_t::CLKOUT8_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout9_ADLY_SEL = lmk04816_regs_t::CLKOUT9_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout8_9_ADLY = adly_value; - } else { - _lmk04816_regs.CLKout8_ADLY_SEL = lmk04816_regs_t::CLKOUT8_ADLY_SEL_D_PD; - _lmk04816_regs.CLKout9_ADLY_SEL = lmk04816_regs_t::CLKOUT9_ADLY_SEL_D_PD; - } - write_regs(4); - write_regs(8); - _delays.adc_dly_ns = coerced_delay; - break; - default: - throw uhd::value_error("set_clock_delay: Requested source is invalid."); + UHD_LOG_DEBUG("X300", + boost::format( + "x300_clock_ctrl::set_clock_delay: Which=%d, Requested=%f, Digital " + "Taps=%d, Half Shift=%d, Analog Delay=%d (%s), Coerced Delay=%fns") + % which % delay_ns % ddly_value % (half_shift_en ? "ON" : "OFF") + % ((int)adly_value) % (adly_en ? "ON" : "OFF") % coerced_delay) + + // Apply settings + switch (which) { + case X300_CLOCK_WHICH_FPGA: + _lmk04816_regs.CLKout0_1_DDLY = ddly_value; + _lmk04816_regs.CLKout0_1_HS = half_shift_en; + if (adly_en) { + _lmk04816_regs.CLKout0_ADLY_SEL = + lmk04816_regs_t::CLKOUT0_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout1_ADLY_SEL = + lmk04816_regs_t::CLKOUT1_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout0_1_ADLY = adly_value; + } else { + _lmk04816_regs.CLKout0_ADLY_SEL = + lmk04816_regs_t::CLKOUT0_ADLY_SEL_D_PD; + _lmk04816_regs.CLKout1_ADLY_SEL = + lmk04816_regs_t::CLKOUT1_ADLY_SEL_D_PD; + } + write_regs(0); + write_regs(6); + _delays.fpga_dly_ns = coerced_delay; + break; + case X300_CLOCK_WHICH_DB0_RX: + case X300_CLOCK_WHICH_DB1_RX: + _lmk04816_regs.CLKout2_3_DDLY = ddly_value; + _lmk04816_regs.CLKout2_3_HS = half_shift_en; + if (adly_en) { + _lmk04816_regs.CLKout2_ADLY_SEL = + lmk04816_regs_t::CLKOUT2_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout3_ADLY_SEL = + lmk04816_regs_t::CLKOUT3_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout2_3_ADLY = adly_value; + } else { + _lmk04816_regs.CLKout2_ADLY_SEL = + lmk04816_regs_t::CLKOUT2_ADLY_SEL_D_PD; + _lmk04816_regs.CLKout3_ADLY_SEL = + lmk04816_regs_t::CLKOUT3_ADLY_SEL_D_PD; + } + write_regs(1); + write_regs(6); + _delays.db_rx_dly_ns = coerced_delay; + break; + case X300_CLOCK_WHICH_DB0_TX: + case X300_CLOCK_WHICH_DB1_TX: + _lmk04816_regs.CLKout4_5_DDLY = ddly_value; + _lmk04816_regs.CLKout4_5_HS = half_shift_en; + if (adly_en) { + _lmk04816_regs.CLKout4_ADLY_SEL = + lmk04816_regs_t::CLKOUT4_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout5_ADLY_SEL = + lmk04816_regs_t::CLKOUT5_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout4_5_ADLY = adly_value; + } else { + _lmk04816_regs.CLKout4_ADLY_SEL = + lmk04816_regs_t::CLKOUT4_ADLY_SEL_D_PD; + _lmk04816_regs.CLKout5_ADLY_SEL = + lmk04816_regs_t::CLKOUT5_ADLY_SEL_D_PD; + } + write_regs(2); + write_regs(7); + _delays.db_tx_dly_ns = coerced_delay; + break; + case X300_CLOCK_WHICH_DAC0: + case X300_CLOCK_WHICH_DAC1: + _lmk04816_regs.CLKout6_7_DDLY = ddly_value; + _lmk04816_regs.CLKout6_7_HS = half_shift_en; + if (adly_en) { + _lmk04816_regs.CLKout6_ADLY_SEL = + lmk04816_regs_t::CLKOUT6_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout7_ADLY_SEL = + lmk04816_regs_t::CLKOUT7_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout6_7_ADLY = adly_value; + } else { + _lmk04816_regs.CLKout6_ADLY_SEL = + lmk04816_regs_t::CLKOUT6_ADLY_SEL_D_PD; + _lmk04816_regs.CLKout7_ADLY_SEL = + lmk04816_regs_t::CLKOUT7_ADLY_SEL_D_PD; + } + write_regs(3); + write_regs(7); + _delays.dac_dly_ns = coerced_delay; + break; + case X300_CLOCK_WHICH_ADC0: + case X300_CLOCK_WHICH_ADC1: + _lmk04816_regs.CLKout8_9_DDLY = ddly_value; + _lmk04816_regs.CLKout8_9_HS = half_shift_en; + if (adly_en) { + _lmk04816_regs.CLKout8_ADLY_SEL = + lmk04816_regs_t::CLKOUT8_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout9_ADLY_SEL = + lmk04816_regs_t::CLKOUT9_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout8_9_ADLY = adly_value; + } else { + _lmk04816_regs.CLKout8_ADLY_SEL = + lmk04816_regs_t::CLKOUT8_ADLY_SEL_D_PD; + _lmk04816_regs.CLKout9_ADLY_SEL = + lmk04816_regs_t::CLKOUT9_ADLY_SEL_D_PD; + } + write_regs(4); + write_regs(8); + _delays.adc_dly_ns = coerced_delay; + break; + default: + throw uhd::value_error("set_clock_delay: Requested source is invalid."); } - //Delays are applied only on a sync event - if (resync) sync_clocks(); + // Delays are applied only on a sync event + if (resync) + sync_clocks(); return coerced_delay; } - double get_clock_delay(const x300_clock_which_t which) { - switch (which) - { - case X300_CLOCK_WHICH_FPGA: - return _delays.fpga_dly_ns; - case X300_CLOCK_WHICH_DB0_RX: - case X300_CLOCK_WHICH_DB1_RX: - return _delays.db_rx_dly_ns; - case X300_CLOCK_WHICH_DB0_TX: - case X300_CLOCK_WHICH_DB1_TX: - return _delays.db_tx_dly_ns; - case X300_CLOCK_WHICH_DAC0: - case X300_CLOCK_WHICH_DAC1: - return _delays.dac_dly_ns; - case X300_CLOCK_WHICH_ADC0: - case X300_CLOCK_WHICH_ADC1: - return _delays.adc_dly_ns; - default: - throw uhd::value_error("get_clock_delay: Requested source is invalid."); + double get_clock_delay(const x300_clock_which_t which) + { + switch (which) { + case X300_CLOCK_WHICH_FPGA: + return _delays.fpga_dly_ns; + case X300_CLOCK_WHICH_DB0_RX: + case X300_CLOCK_WHICH_DB1_RX: + return _delays.db_rx_dly_ns; + case X300_CLOCK_WHICH_DB0_TX: + case X300_CLOCK_WHICH_DB1_TX: + return _delays.db_tx_dly_ns; + case X300_CLOCK_WHICH_DAC0: + case X300_CLOCK_WHICH_DAC1: + return _delays.dac_dly_ns; + case X300_CLOCK_WHICH_ADC0: + case X300_CLOCK_WHICH_ADC1: + return _delays.adc_dly_ns; + default: + throw uhd::value_error("get_clock_delay: Requested source is invalid."); } } private: - double autoset_pll2_config(const double output_freq) { // VCXO runs at 96MHz, assume PLL2 reference doubler is enabled const double ref = VCXO_FREQ * 2; const int lowest_vcodiv = static_cast<int>(std::ceil(MIN_VCO_FREQ / output_freq)); - const int highest_vcodiv = static_cast<int>(std::floor(MAX_VCO_FREQ / output_freq)); + const int highest_vcodiv = + static_cast<int>(std::floor(MAX_VCO_FREQ / output_freq)); // Find the PLL2 configuration with the lowest frequency error, favoring // higher phase comparison frequencies. - double best_error = 1e10; - double best_mcr = 0.0; + double best_error = 1e10; + double best_mcr = 0.0; double best_vco_freq = _vco_freq; - int best_N = _lmk04816_regs.PLL2_N_30; - int best_R = _lmk04816_regs.PLL2_R_28; + int best_N = _lmk04816_regs.PLL2_N_30; + int best_R = _lmk04816_regs.PLL2_R_28; for (int vcodiv = lowest_vcodiv; vcodiv <= highest_vcodiv; vcodiv++) { const double try_vco_freq = vcodiv * output_freq; // Start at R=2: with a min value of 2 for R, we don't have to worry // about exceeding the maximum phase comparison frequency for PLL2. - for (int r = 2; r <= 50; r++) - { + for (int r = 2; r <= 50; r++) { // Note: We could accomplish somewhat higher resolution if we change // the N predivider to odd values as well, and we may be able to get // better spur performance by balancing the predivider and the @@ -449,56 +515,60 @@ private: boost::math::round((r * try_vco_freq) / (VCXO_PLL2_N * ref))); const double actual_mcr = (ref * VCXO_PLL2_N * n) / (vcodiv * r); - const double error = std::abs(actual_mcr - output_freq); + const double error = std::abs(actual_mcr - output_freq); if (error < best_error) { - best_error = error; - best_mcr = actual_mcr; + best_error = error; + best_mcr = actual_mcr; best_vco_freq = try_vco_freq; - best_N = n; - best_R = r; + best_N = n; + best_R = r; } } } UHD_ASSERT_THROW(best_mcr > 0.0); - _vco_freq = best_vco_freq; + _vco_freq = best_vco_freq; _lmk04816_regs.PLL2_N_30 = best_N; _lmk04816_regs.PLL2_R_28 = best_R; _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; if (fp_compare_epsilon<double>(best_error) > 0.0) { UHD_LOGGER_WARNING("X300") - << boost::format("Attempted master clock rate %0.2f MHz, got %0.2f MHz") - % (output_freq / 1e6) % (best_mcr / 1e6); + << boost::format("Attempted master clock rate %0.2f MHz, got %0.2f MHz") + % (output_freq / 1e6) % (best_mcr / 1e6); } - UHD_LOGGER_TRACE("X300") << boost::format( - "Using automatic LMK04816 PLL2 config: N=%d, R=%d, VCO=%0.2f MHz, MCR=%0.2f MHz") - % _lmk04816_regs.PLL2_N_30 % _lmk04816_regs.PLL2_R_28 - % (_vco_freq / 1e6) % (best_mcr / 1e6); + UHD_LOGGER_TRACE("X300") + << boost::format("Using automatic LMK04816 PLL2 config: N=%d, R=%d, " + "VCO=%0.2f MHz, MCR=%0.2f MHz") + % _lmk04816_regs.PLL2_N_30 % _lmk04816_regs.PLL2_R_28 + % (_vco_freq / 1e6) % (best_mcr / 1e6); return best_mcr; } - void init() { + void init() + { /* The X3xx has two primary rates. The first is the * _system_ref_rate, which is sourced from the "clock_source"/"value" field - * of the property tree, and whose value can be 10e6, 11.52e6, 23.04e6, or 30.72e6. - * The _system_ref_rate is the input to the clocking system, and - * what comes out is a disciplined master clock running at the - * _master_clock_rate. As such, only certain combinations of - * system reference rates and master clock rates are supported. - * Additionally, a subset of these will operate in "zero delay" mode. */ - - enum opmode_t { INVALID, - m10M_200M_NOZDEL, // used for debug purposes only - m10M_200M_ZDEL, // Normal mode - m11_52M_184_32M_ZDEL, // LTE with 11.52 MHz ref - m23_04M_184_32M_ZDEL, // LTE with 23.04 MHz ref - m30_72M_184_32M_ZDEL, // LTE with external ref, aka CPRI Mode - m10M_184_32M_NOZDEL, // LTE with 10 MHz ref - m10M_120M_ZDEL, // NI USRP 120 MHz Clocking - m10M_AUTO_NOZDEL }; // automatic for arbitrary clock from 10MHz ref + * of the property tree, and whose value can be 10e6, 11.52e6, 23.04e6, + * or 30.72e6. The _system_ref_rate is the input to the clocking system, and what + * comes out is a disciplined master clock running at the _master_clock_rate. As + * such, only certain combinations of system reference rates and master clock + * rates are supported. Additionally, a subset of these will operate in "zero + * delay" mode. */ + + enum opmode_t { + INVALID, + m10M_200M_NOZDEL, // used for debug purposes only + m10M_200M_ZDEL, // Normal mode + m11_52M_184_32M_ZDEL, // LTE with 11.52 MHz ref + m23_04M_184_32M_ZDEL, // LTE with 23.04 MHz ref + m30_72M_184_32M_ZDEL, // LTE with external ref, aka CPRI Mode + m10M_184_32M_NOZDEL, // LTE with 10 MHz ref + m10M_120M_ZDEL, // NI USRP 120 MHz Clocking + m10M_AUTO_NOZDEL + }; // automatic for arbitrary clock from 10MHz ref /* The default clocking mode is 10MHz reference generating a 200 MHz master * clock, in zero-delay mode. */ @@ -515,61 +585,61 @@ private: } else if (math::frequencies_are_equal(_master_clock_rate, 120e6)) { /* 10MHz reference, 120 MHz master clock rate, Zero Delay */ clocking_mode = m10M_120M_ZDEL; - } else if ( - fp_compare_epsilon<double>(_master_clock_rate) >= uhd::usrp::x300::MIN_TICK_RATE - && fp_compare_epsilon<double>(_master_clock_rate) <= uhd::usrp::x300::MAX_TICK_RATE - ) { + } else if (fp_compare_epsilon<double>(_master_clock_rate) + >= uhd::usrp::x300::MIN_TICK_RATE + && fp_compare_epsilon<double>(_master_clock_rate) + <= uhd::usrp::x300::MAX_TICK_RATE) { /* 10MHz reference, attempt to automatically configure PLL * for arbitrary master clock rate, Zero Delay */ - UHD_LOGGER_WARNING("X300") - << "Using automatic master clock PLL config. This is an experimental feature."; + UHD_LOGGER_WARNING("X300") << "Using automatic master clock PLL config. " + "This is an experimental feature."; clocking_mode = m10M_AUTO_NOZDEL; } else { - throw uhd::runtime_error(str( - boost::format("Invalid master clock rate: %.2f MHz.\n" - "Valid master clock rates when using a %f MHz reference clock are:\n" - "120 MHz, 184.32 MHz and 200 MHz.") - % (_master_clock_rate / 1e6) % (_system_ref_rate / 1e6) - )); + throw uhd::runtime_error( + str(boost::format("Invalid master clock rate: %.2f MHz.\n" + "Valid master clock rates when using a %f MHz " + "reference clock are:\n" + "120 MHz, 184.32 MHz and 200 MHz.") + % (_master_clock_rate / 1e6) % (_system_ref_rate / 1e6))); } } else if (math::frequencies_are_equal(_system_ref_rate, 11.52e6)) { if (math::frequencies_are_equal(_master_clock_rate, 184.32e6)) { /* 11.52MHz reference, 184.32 MHz master clock out, Zero Delay */ clocking_mode = m11_52M_184_32M_ZDEL; } else { - throw uhd::runtime_error(str( - boost::format("Invalid master clock rate: %.2f MHz.\n" - "Valid master clock rate when using a %.2f MHz reference clock is: 184.32 MHz.") - % (_master_clock_rate / 1e6) % (_system_ref_rate / 1e6) - )); + throw uhd::runtime_error( + str(boost::format("Invalid master clock rate: %.2f MHz.\n" + "Valid master clock rate when using a %.2f MHz " + "reference clock is: 184.32 MHz.") + % (_master_clock_rate / 1e6) % (_system_ref_rate / 1e6))); } } else if (math::frequencies_are_equal(_system_ref_rate, 23.04e6)) { if (math::frequencies_are_equal(_master_clock_rate, 184.32e6)) { /* 11.52MHz reference, 184.32 MHz master clock out, Zero Delay */ clocking_mode = m23_04M_184_32M_ZDEL; } else { - throw uhd::runtime_error(str( - boost::format("Invalid master clock rate: %.2f MHz.\n" - "Valid master clock rate when using a %.2f MHz reference clock is: 184.32 MHz.") - % (_master_clock_rate / 1e6) % (_system_ref_rate / 1e6) - )); + throw uhd::runtime_error( + str(boost::format("Invalid master clock rate: %.2f MHz.\n" + "Valid master clock rate when using a %.2f MHz " + "reference clock is: 184.32 MHz.") + % (_master_clock_rate / 1e6) % (_system_ref_rate / 1e6))); } } else if (math::frequencies_are_equal(_system_ref_rate, 30.72e6)) { if (math::frequencies_are_equal(_master_clock_rate, 184.32e6)) { /* 30.72MHz reference, 184.32 MHz master clock out, Zero Delay */ clocking_mode = m30_72M_184_32M_ZDEL; } else { - throw uhd::runtime_error(str( - boost::format("Invalid master clock rate: %.2f MHz.\n" - "Valid master clock rate when using a %.2f MHz reference clock is: 184.32 MHz.") - % (_master_clock_rate / 1e6) % (_system_ref_rate / 1e6) - )); + throw uhd::runtime_error( + str(boost::format("Invalid master clock rate: %.2f MHz.\n" + "Valid master clock rate when using a %.2f MHz " + "reference clock is: 184.32 MHz.") + % (_master_clock_rate / 1e6) % (_system_ref_rate / 1e6))); } } else { - throw uhd::runtime_error(str( - boost::format("Invalid system reference rate: %.2f MHz.\nValid reference frequencies are: 10 MHz, 30.72 MHz.") - % (_system_ref_rate / 1e6) - )); + throw uhd::runtime_error( + str(boost::format("Invalid system reference rate: %.2f MHz.\nValid " + "reference frequencies are: 10 MHz, 30.72 MHz.") + % (_system_ref_rate / 1e6))); } UHD_ASSERT_THROW(clocking_mode != INVALID); @@ -583,29 +653,29 @@ private: * architecture. Please refer to the datasheet for more information. */ switch (clocking_mode) { case m10M_200M_NOZDEL: - _vco_freq = 2400e6; + _vco_freq = 2400e6; _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT; // PLL1 - 2 MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 48; - _lmk04816_regs.PLL1_R_27 = 5; + _lmk04816_regs.PLL1_N_28 = 48; + _lmk04816_regs.PLL1_R_27 = 5; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_100UA; // PLL2 - 48 MHz compare frequency - _lmk04816_regs.PLL2_N_30 = 25; - _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; - _lmk04816_regs.PLL2_R_28 = 4; + _lmk04816_regs.PLL2_N_30 = 25; + _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; + _lmk04816_regs.PLL2_R_28 = 4; _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_3200UA; break; case m10M_200M_ZDEL: - _vco_freq = 2400e6; + _vco_freq = 2400e6; _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT_ZER_DELAY; // PLL1 - 2 MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 5; - _lmk04816_regs.PLL1_R_27 = 5; + _lmk04816_regs.PLL1_N_28 = 5; + _lmk04816_regs.PLL1_R_27 = 5; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_1600UA; // PLL2 - 96 MHz compare frequency @@ -613,26 +683,28 @@ private: _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_5; _lmk04816_regs.PLL2_R_28 = 2; - if(_hw_rev <= 4) - _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_1600UA; + if (_hw_rev <= 4) + _lmk04816_regs.PLL2_CP_GAIN_26 = + lmk04816_regs_t::PLL2_CP_GAIN_26_1600UA; else - _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_400UA; + _lmk04816_regs.PLL2_CP_GAIN_26 = + lmk04816_regs_t::PLL2_CP_GAIN_26_400UA; break; case m10M_184_32M_NOZDEL: - _vco_freq = 2580.48e6; + _vco_freq = 2580.48e6; _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT; // PLL1 - 2 MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 48; - _lmk04816_regs.PLL1_R_27 = 5; + _lmk04816_regs.PLL1_N_28 = 48; + _lmk04816_regs.PLL1_R_27 = 5; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_100UA; // PLL2 - 7.68 MHz compare frequency - _lmk04816_regs.PLL2_N_30 = 168; - _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; - _lmk04816_regs.PLL2_R_28 = 25; + _lmk04816_regs.PLL2_N_30 = 168; + _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; + _lmk04816_regs.PLL2_R_28 = 25; _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_3200UA; _lmk04816_regs.PLL2_R3_LF = lmk04816_regs_t::PLL2_R3_LF_4KILO_OHM; @@ -644,18 +716,18 @@ private: break; case m11_52M_184_32M_ZDEL: - _vco_freq = 2580.48e6; + _vco_freq = 2580.48e6; _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT_ZER_DELAY; // PLL1 - 1.92 MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 6; - _lmk04816_regs.PLL1_R_27 = 6; + _lmk04816_regs.PLL1_N_28 = 6; + _lmk04816_regs.PLL1_R_27 = 6; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_100UA; // PLL2 - 7.68 MHz compare frequency - _lmk04816_regs.PLL2_N_30 = 168; - _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; - _lmk04816_regs.PLL2_R_28 = 25; + _lmk04816_regs.PLL2_N_30 = 168; + _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; + _lmk04816_regs.PLL2_R_28 = 25; _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_3200UA; _lmk04816_regs.PLL2_R3_LF = lmk04816_regs_t::PLL2_R3_LF_1KILO_OHM; @@ -667,18 +739,18 @@ private: break; case m23_04M_184_32M_ZDEL: - _vco_freq = 2580.48e6; + _vco_freq = 2580.48e6; _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT_ZER_DELAY; // PLL1 - 1.92 MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 12; - _lmk04816_regs.PLL1_R_27 = 12; + _lmk04816_regs.PLL1_N_28 = 12; + _lmk04816_regs.PLL1_R_27 = 12; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_100UA; // PLL2 - 7.68 MHz compare frequency - _lmk04816_regs.PLL2_N_30 = 168; - _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; - _lmk04816_regs.PLL2_R_28 = 25; + _lmk04816_regs.PLL2_N_30 = 168; + _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; + _lmk04816_regs.PLL2_R_28 = 25; _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_3200UA; _lmk04816_regs.PLL2_R3_LF = lmk04816_regs_t::PLL2_R3_LF_1KILO_OHM; @@ -690,18 +762,18 @@ private: break; case m30_72M_184_32M_ZDEL: - _vco_freq = 2580.48e6; + _vco_freq = 2580.48e6; _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT_ZER_DELAY; // PLL1 - 2.048 MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 15; - _lmk04816_regs.PLL1_R_27 = 15; + _lmk04816_regs.PLL1_N_28 = 15; + _lmk04816_regs.PLL1_R_27 = 15; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_100UA; // PLL2 - 7.68 MHz compare frequency - _lmk04816_regs.PLL2_N_30 = 168; - _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; - _lmk04816_regs.PLL2_R_28 = 25; + _lmk04816_regs.PLL2_N_30 = 168; + _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; + _lmk04816_regs.PLL2_R_28 = 25; _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_3200UA; _lmk04816_regs.PLL2_R3_LF = lmk04816_regs_t::PLL2_R3_LF_1KILO_OHM; @@ -713,12 +785,12 @@ private: break; case m10M_120M_ZDEL: - _vco_freq = 2400e6; + _vco_freq = 2400e6; _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT_ZER_DELAY; // PLL1 - 2 MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 5; - _lmk04816_regs.PLL1_R_27 = 5; + _lmk04816_regs.PLL1_N_28 = 5; + _lmk04816_regs.PLL1_R_27 = 5; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_100UA; // PLL2 - 96 MHz compare frequency @@ -726,10 +798,12 @@ private: _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_5; _lmk04816_regs.PLL2_R_28 = 2; - if(_hw_rev <= 4) - _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_1600UA; + if (_hw_rev <= 4) + _lmk04816_regs.PLL2_CP_GAIN_26 = + lmk04816_regs_t::PLL2_CP_GAIN_26_1600UA; else - _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_400UA; + _lmk04816_regs.PLL2_CP_GAIN_26 = + lmk04816_regs_t::PLL2_CP_GAIN_26_400UA; break; @@ -737,8 +811,8 @@ private: _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT; // PLL1 - 2MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 48; - _lmk04816_regs.PLL1_R_27 = 5; + _lmk04816_regs.PLL1_N_28 = 48; + _lmk04816_regs.PLL1_R_27 = 5; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_100UA; // PLL2 - this call will set _vco_freq and PLL2 P/N/R registers. @@ -751,11 +825,11 @@ private: break; }; - uint16_t master_clock_div = static_cast<uint16_t>( - std::ceil(_vco_freq / _master_clock_rate)); + uint16_t master_clock_div = + static_cast<uint16_t>(std::ceil(_vco_freq / _master_clock_rate)); - uint16_t dboard_div = static_cast<uint16_t>( - std::ceil(_vco_freq / _dboard_clock_rate)); + uint16_t dboard_div = + static_cast<uint16_t>(std::ceil(_vco_freq / _dboard_clock_rate)); /* Reset the LMK clock controller. */ _lmk04816_regs.RESET = lmk04816_regs_t::RESET_RESET; @@ -770,13 +844,13 @@ private: this->write_regs(0); // Register 1 - _lmk04816_regs.CLKout2_3_PD = lmk04816_regs_t::CLKOUT2_3_PD_POWER_UP; + _lmk04816_regs.CLKout2_3_PD = lmk04816_regs_t::CLKOUT2_3_PD_POWER_UP; _lmk04816_regs.CLKout2_3_DIV = dboard_div; // Register 2 - _lmk04816_regs.CLKout4_5_PD = lmk04816_regs_t::CLKOUT4_5_PD_POWER_UP; + _lmk04816_regs.CLKout4_5_PD = lmk04816_regs_t::CLKOUT4_5_PD_POWER_UP; _lmk04816_regs.CLKout4_5_DIV = dboard_div; // Register 3 - _lmk04816_regs.CLKout6_7_DIV = master_clock_div; + _lmk04816_regs.CLKout6_7_DIV = master_clock_div; _lmk04816_regs.CLKout6_7_OSCin_Sel = lmk04816_regs_t::CLKOUT6_7_OSCIN_SEL_VCO; // Register 4 _lmk04816_regs.CLKout8_9_DIV = master_clock_div; @@ -786,39 +860,55 @@ private: static_cast<uint16_t>(std::ceil(_vco_freq / _system_ref_rate)); // Register 6 - _lmk04816_regs.CLKout0_TYPE = lmk04816_regs_t::CLKOUT0_TYPE_LVDS; //FPGA - _lmk04816_regs.CLKout1_TYPE = lmk04816_regs_t::CLKOUT1_TYPE_P_DOWN; //CPRI feedback clock, use LVDS - _lmk04816_regs.CLKout2_TYPE = lmk04816_regs_t::CLKOUT2_TYPE_LVPECL_700MVPP; //DB_0_RX - _lmk04816_regs.CLKout3_TYPE = lmk04816_regs_t::CLKOUT3_TYPE_LVPECL_700MVPP; //DB_1_RX + _lmk04816_regs.CLKout0_TYPE = lmk04816_regs_t::CLKOUT0_TYPE_LVDS; // FPGA + _lmk04816_regs.CLKout1_TYPE = + lmk04816_regs_t::CLKOUT1_TYPE_P_DOWN; // CPRI feedback clock, use LVDS + _lmk04816_regs.CLKout2_TYPE = + lmk04816_regs_t::CLKOUT2_TYPE_LVPECL_700MVPP; // DB_0_RX + _lmk04816_regs.CLKout3_TYPE = + lmk04816_regs_t::CLKOUT3_TYPE_LVPECL_700MVPP; // DB_1_RX // Register 7 - _lmk04816_regs.CLKout4_TYPE = lmk04816_regs_t::CLKOUT4_TYPE_LVPECL_700MVPP; //DB_1_TX - _lmk04816_regs.CLKout5_TYPE = lmk04816_regs_t::CLKOUT5_TYPE_LVPECL_700MVPP; //DB_0_TX - _lmk04816_regs.CLKout6_TYPE = lmk04816_regs_t::CLKOUT6_TYPE_LVPECL_700MVPP; //DB0_DAC - _lmk04816_regs.CLKout7_TYPE = lmk04816_regs_t::CLKOUT7_TYPE_LVPECL_700MVPP; //DB1_DAC - _lmk04816_regs.CLKout8_TYPE = lmk04816_regs_t::CLKOUT8_TYPE_LVPECL_700MVPP; //DB0_ADC + _lmk04816_regs.CLKout4_TYPE = + lmk04816_regs_t::CLKOUT4_TYPE_LVPECL_700MVPP; // DB_1_TX + _lmk04816_regs.CLKout5_TYPE = + lmk04816_regs_t::CLKOUT5_TYPE_LVPECL_700MVPP; // DB_0_TX + _lmk04816_regs.CLKout6_TYPE = + lmk04816_regs_t::CLKOUT6_TYPE_LVPECL_700MVPP; // DB0_DAC + _lmk04816_regs.CLKout7_TYPE = + lmk04816_regs_t::CLKOUT7_TYPE_LVPECL_700MVPP; // DB1_DAC + _lmk04816_regs.CLKout8_TYPE = + lmk04816_regs_t::CLKOUT8_TYPE_LVPECL_700MVPP; // DB0_ADC // Register 8 - _lmk04816_regs.CLKout9_TYPE = lmk04816_regs_t::CLKOUT9_TYPE_LVPECL_700MVPP; //DB1_ADC - _lmk04816_regs.CLKout10_TYPE = lmk04816_regs_t::CLKOUT10_TYPE_LVDS; //REF_CLKOUT - _lmk04816_regs.CLKout11_TYPE = lmk04816_regs_t::CLKOUT11_TYPE_P_DOWN; //Debug header, use LVPECL + _lmk04816_regs.CLKout9_TYPE = + lmk04816_regs_t::CLKOUT9_TYPE_LVPECL_700MVPP; // DB1_ADC + _lmk04816_regs.CLKout10_TYPE = lmk04816_regs_t::CLKOUT10_TYPE_LVDS; // REF_CLKOUT + _lmk04816_regs.CLKout11_TYPE = + lmk04816_regs_t::CLKOUT11_TYPE_P_DOWN; // Debug header, use LVPECL // Register 10 - _lmk04816_regs.EN_OSCout0 = lmk04816_regs_t::EN_OSCOUT0_DISABLED; //Debug header - _lmk04816_regs.FEEDBACK_MUX = 5; //use output 10 (REF OUT) for feedback + _lmk04816_regs.EN_OSCout0 = lmk04816_regs_t::EN_OSCOUT0_DISABLED; // Debug header + _lmk04816_regs.FEEDBACK_MUX = 5; // use output 10 (REF OUT) for feedback _lmk04816_regs.EN_FEEDBACK_MUX = lmk04816_regs_t::EN_FEEDBACK_MUX_ENABLED; // Register 11 // MODE set in individual cases above _lmk04816_regs.SYNC_QUAL = lmk04816_regs_t::SYNC_QUAL_FB_MUX; - _lmk04816_regs.EN_SYNC = lmk04816_regs_t::EN_SYNC_ENABLE; - _lmk04816_regs.NO_SYNC_CLKout0_1 = lmk04816_regs_t::NO_SYNC_CLKOUT0_1_CLOCK_XY_SYNC; - _lmk04816_regs.NO_SYNC_CLKout2_3 = lmk04816_regs_t::NO_SYNC_CLKOUT2_3_CLOCK_XY_SYNC; - _lmk04816_regs.NO_SYNC_CLKout4_5 = lmk04816_regs_t::NO_SYNC_CLKOUT4_5_CLOCK_XY_SYNC; - _lmk04816_regs.NO_SYNC_CLKout6_7 = lmk04816_regs_t::NO_SYNC_CLKOUT6_7_CLOCK_XY_SYNC; - _lmk04816_regs.NO_SYNC_CLKout8_9 = lmk04816_regs_t::NO_SYNC_CLKOUT8_9_CLOCK_XY_SYNC; - _lmk04816_regs.NO_SYNC_CLKout10_11 = lmk04816_regs_t::NO_SYNC_CLKOUT10_11_CLOCK_XY_SYNC; + _lmk04816_regs.EN_SYNC = lmk04816_regs_t::EN_SYNC_ENABLE; + _lmk04816_regs.NO_SYNC_CLKout0_1 = + lmk04816_regs_t::NO_SYNC_CLKOUT0_1_CLOCK_XY_SYNC; + _lmk04816_regs.NO_SYNC_CLKout2_3 = + lmk04816_regs_t::NO_SYNC_CLKOUT2_3_CLOCK_XY_SYNC; + _lmk04816_regs.NO_SYNC_CLKout4_5 = + lmk04816_regs_t::NO_SYNC_CLKOUT4_5_CLOCK_XY_SYNC; + _lmk04816_regs.NO_SYNC_CLKout6_7 = + lmk04816_regs_t::NO_SYNC_CLKOUT6_7_CLOCK_XY_SYNC; + _lmk04816_regs.NO_SYNC_CLKout8_9 = + lmk04816_regs_t::NO_SYNC_CLKOUT8_9_CLOCK_XY_SYNC; + _lmk04816_regs.NO_SYNC_CLKout10_11 = + lmk04816_regs_t::NO_SYNC_CLKOUT10_11_CLOCK_XY_SYNC; _lmk04816_regs.SYNC_TYPE = lmk04816_regs_t::SYNC_TYPE_INPUT; // Register 12 @@ -826,14 +916,18 @@ private: /* Input Clock Configurations */ // Register 13 - _lmk04816_regs.EN_CLKin0 = lmk04816_regs_t::EN_CLKIN0_NO_VALID_USE; // This is not connected - _lmk04816_regs.EN_CLKin2 = lmk04816_regs_t::EN_CLKIN2_NO_VALID_USE; // Used only for CPRI + _lmk04816_regs.EN_CLKin0 = + lmk04816_regs_t::EN_CLKIN0_NO_VALID_USE; // This is not connected + _lmk04816_regs.EN_CLKin2 = + lmk04816_regs_t::EN_CLKIN2_NO_VALID_USE; // Used only for CPRI _lmk04816_regs.Status_CLKin1_MUX = lmk04816_regs_t::STATUS_CLKIN1_MUX_UWIRE_RB; _lmk04816_regs.CLKin_Select_MODE = lmk04816_regs_t::CLKIN_SELECT_MODE_CLKIN1_MAN; - _lmk04816_regs.HOLDOVER_MUX = lmk04816_regs_t::HOLDOVER_MUX_PLL1_R; + _lmk04816_regs.HOLDOVER_MUX = lmk04816_regs_t::HOLDOVER_MUX_PLL1_R; // Register 14 - _lmk04816_regs.Status_CLKin1_TYPE = lmk04816_regs_t::STATUS_CLKIN1_TYPE_OUT_PUSH_PULL; - _lmk04816_regs.Status_CLKin0_TYPE = lmk04816_regs_t::STATUS_CLKIN0_TYPE_OUT_PUSH_PULL; + _lmk04816_regs.Status_CLKin1_TYPE = + lmk04816_regs_t::STATUS_CLKIN1_TYPE_OUT_PUSH_PULL; + _lmk04816_regs.Status_CLKin0_TYPE = + lmk04816_regs_t::STATUS_CLKIN0_TYPE_OUT_PUSH_PULL; // Register 26 // PLL2_CP_GAIN_26 set above in individual cases @@ -848,7 +942,8 @@ private: // PLL1_N_28 and PLL2_R_28 are set in the individual cases above // Register 29 - _lmk04816_regs.PLL2_N_CAL_29 = _lmk04816_regs.PLL2_N_30; // N_CAL should always match N + _lmk04816_regs.PLL2_N_CAL_29 = + _lmk04816_regs.PLL2_N_30; // N_CAL should always match N _lmk04816_regs.OSCin_FREQ_29 = lmk04816_regs_t::OSCIN_FREQ_29_63_TO_127MHZ; // Register 30 @@ -861,12 +956,18 @@ private: _delays = X300_REV0_6_CLK_DELAYS; } - //Apply delay values - set_clock_delay(X300_CLOCK_WHICH_FPGA, _delays.fpga_dly_ns, false); - set_clock_delay(X300_CLOCK_WHICH_DB0_RX, _delays.db_rx_dly_ns, false); //Sets both Ch0 and Ch1 - set_clock_delay(X300_CLOCK_WHICH_DB0_TX, _delays.db_tx_dly_ns, false); //Sets both Ch0 and Ch1 - set_clock_delay(X300_CLOCK_WHICH_ADC0, _delays.adc_dly_ns, false); //Sets both Ch0 and Ch1 - set_clock_delay(X300_CLOCK_WHICH_DAC0, _delays.dac_dly_ns, false); //Sets both Ch0 and Ch1 + // Apply delay values + set_clock_delay(X300_CLOCK_WHICH_FPGA, _delays.fpga_dly_ns, false); + set_clock_delay(X300_CLOCK_WHICH_DB0_RX, + _delays.db_rx_dly_ns, + false); // Sets both Ch0 and Ch1 + set_clock_delay(X300_CLOCK_WHICH_DB0_TX, + _delays.db_tx_dly_ns, + false); // Sets both Ch0 and Ch1 + set_clock_delay( + X300_CLOCK_WHICH_ADC0, _delays.adc_dly_ns, false); // Sets both Ch0 and Ch1 + set_clock_delay( + X300_CLOCK_WHICH_DAC0, _delays.dac_dly_ns, false); // Sets both Ch0 and Ch1 /* Write the configuration values into the LMK */ for (uint8_t i = 1; i <= 16; ++i) { @@ -879,24 +980,25 @@ private: this->sync_clocks(); } - const spi_iface::sptr _spiface; - const int _slaveno; - const size_t _hw_rev; + const spi_iface::sptr _spiface; + const int _slaveno; + const size_t _hw_rev; // This is technically constant, but it can be coerced during initialization - double _master_clock_rate; - const double _dboard_clock_rate; - const double _system_ref_rate; - lmk04816_regs_t _lmk04816_regs; - double _vco_freq; - x300_clk_delays _delays; + double _master_clock_rate; + const double _dboard_clock_rate; + const double _system_ref_rate; + lmk04816_regs_t _lmk04816_regs; + double _vco_freq; + x300_clk_delays _delays; }; x300_clock_ctrl::sptr x300_clock_ctrl::make(uhd::spi_iface::sptr spiface, - const size_t slaveno, - const size_t hw_rev, - const double master_clock_rate, - const double dboard_clock_rate, - const double system_ref_rate) { - return sptr(new x300_clock_ctrl_impl(spiface, slaveno, hw_rev, - master_clock_rate, dboard_clock_rate, system_ref_rate)); + const size_t slaveno, + const size_t hw_rev, + const double master_clock_rate, + const double dboard_clock_rate, + const double system_ref_rate) +{ + return sptr(new x300_clock_ctrl_impl( + spiface, slaveno, hw_rev, master_clock_rate, dboard_clock_rate, system_ref_rate)); } diff --git a/host/lib/usrp/x300/x300_clock_ctrl.hpp b/host/lib/usrp/x300/x300_clock_ctrl.hpp index 3ab8b45f9..609464ca0 100644 --- a/host/lib/usrp/x300/x300_clock_ctrl.hpp +++ b/host/lib/usrp/x300/x300_clock_ctrl.hpp @@ -13,8 +13,7 @@ #include <boost/utility.hpp> -enum x300_clock_which_t -{ +enum x300_clock_which_t { X300_CLOCK_WHICH_ADC0, X300_CLOCK_WHICH_ADC1, X300_CLOCK_WHICH_DAC0, @@ -29,17 +28,16 @@ enum x300_clock_which_t class x300_clock_ctrl : boost::noncopyable { public: - typedef boost::shared_ptr<x300_clock_ctrl> sptr; virtual ~x300_clock_ctrl(void) = 0; static sptr make(uhd::spi_iface::sptr spiface, - const size_t slaveno, - const size_t hw_rev, - const double master_clock_rate, - const double dboard_clock_rate, - const double system_ref_rate); + const size_t slaveno, + const size_t hw_rev, + const double master_clock_rate, + const double dboard_clock_rate, + const double system_ref_rate); /*! Get the master clock rate of the device. * \return the clock frequency in Hz @@ -78,7 +76,8 @@ public: * \param enable true=enable, false=disable * \return a list of clock rates in Hz */ - virtual void enable_dboard_clock(const x300_clock_which_t which, const bool enable) = 0; + virtual void enable_dboard_clock( + const x300_clock_which_t which, const bool enable) = 0; /*! Turn the reference output on/off * \param true = on, false = off @@ -92,7 +91,9 @@ public: * \return the actual delay value set * \throw exception when which invalid or delay_ns out of range */ - virtual double set_clock_delay(const x300_clock_which_t which, const double delay_ns, const bool resync = true) = 0; + virtual double set_clock_delay(const x300_clock_which_t which, + const double delay_ns, + const bool resync = true) = 0; /*! Get the clock delay for the given clock divider. * \param which which clock diff --git a/host/lib/usrp/x300/x300_dac_ctrl.cpp b/host/lib/usrp/x300/x300_dac_ctrl.cpp index a9df96002..f951a44a2 100644 --- a/host/lib/usrp/x300/x300_dac_ctrl.cpp +++ b/host/lib/usrp/x300/x300_dac_ctrl.cpp @@ -7,11 +7,11 @@ #include "x300_dac_ctrl.hpp" #include "x300_regs.hpp" -#include <uhdlib/utils/system_time.hpp> +#include <uhd/exception.hpp> #include <uhd/types/time_spec.hpp> #include <uhd/utils/log.hpp> #include <uhd/utils/safe_call.hpp> -#include <uhd/exception.hpp> +#include <uhdlib/utils/system_time.hpp> #include <boost/format.hpp> #include <chrono> #include <thread> @@ -22,10 +22,12 @@ using namespace uhd; #define write_ad9146_reg(addr, data) \ _iface->write_spi(_slaveno, spi_config_t::EDGE_RISE, ((addr) << 8) | (data), 16) -#define read_ad9146_reg(addr) \ - (_iface->read_spi(_slaveno, spi_config_t::EDGE_RISE, ((addr) << 8) | (1 << 15), 16) & 0xff) +#define read_ad9146_reg(addr) \ + (_iface->read_spi(_slaveno, spi_config_t::EDGE_RISE, ((addr) << 8) | (1 << 15), 16) \ + & 0xff) -x300_dac_ctrl::~x300_dac_ctrl(void){ +x300_dac_ctrl::~x300_dac_ctrl(void) +{ /* NOP */ } @@ -35,38 +37,41 @@ x300_dac_ctrl::~x300_dac_ctrl(void){ class x300_dac_ctrl_impl : public x300_dac_ctrl { public: - x300_dac_ctrl_impl(uhd::spi_iface::sptr iface, const size_t slaveno, const double refclk): - _iface(iface), _slaveno(static_cast<int>(slaveno)), _refclk(refclk) + x300_dac_ctrl_impl( + uhd::spi_iface::sptr iface, const size_t slaveno, const double refclk) + : _iface(iface), _slaveno(static_cast<int>(slaveno)), _refclk(refclk) { - //Power up all DAC subsystems - write_ad9146_reg(0x01, 0x10); //Up: I DAC, Q DAC, Receiver, Voltage Ref, Clocks - write_ad9146_reg(0x02, 0x00); //No extended delays. Up: Voltage Ref, PLL, DAC, FIFO, Filters + // Power up all DAC subsystems + write_ad9146_reg(0x01, 0x10); // Up: I DAC, Q DAC, Receiver, Voltage Ref, Clocks + write_ad9146_reg( + 0x02, 0x00); // No extended delays. Up: Voltage Ref, PLL, DAC, FIFO, Filters reset(); } ~x300_dac_ctrl_impl(void) { - UHD_SAFE_CALL - ( - //Power down all DAC subsystems - write_ad9146_reg(0x01, 0xEF); //Down: I DAC, Q DAC, Receiver, Voltage Ref, Clocks - write_ad9146_reg(0x02, 0x1F); //No extended delays. Down: Voltage Ref, PLL, DAC, FIFO, Filters + UHD_SAFE_CALL( + // Power down all DAC subsystems + write_ad9146_reg( + 0x01, 0xEF); // Down: I DAC, Q DAC, Receiver, Voltage Ref, Clocks + write_ad9146_reg(0x02, + 0x1F); // No extended delays. Down: Voltage Ref, PLL, DAC, FIFO, Filters ) } void reset() { - //ADI recommendations: + // ADI recommendations: //- soft reset the chip before configuration //- put the chip in sleep mode during configuration and wake it up when done //- configure synchronization settings when sleeping _soft_reset(); _sleep_mode(true); _init(); - //We run backend sync regardless of whether we need to sync multiple DACs - //because we use the internal DAC FIFO to meet system synchronous timing - //and we need to guarantee that the FIFO is not empty. + // We run backend sync regardless of whether we need to sync multiple DACs + // because we use the internal DAC FIFO to meet system synchronous timing + // and we need to guarantee that the FIFO is not empty. _backend_sync(); _sleep_mode(false); } @@ -78,20 +83,20 @@ public: _check_pll(); _check_dac_sync(); return; - } catch (...) {} + } catch (...) { + } std::string err_str; // Try 3 times to sync before giving up - for (size_t retries = 0; retries < 3; retries++) - { + for (size_t retries = 0; retries < 3; retries++) { try { _sleep_mode(true); _init(); _backend_sync(); _sleep_mode(false); return; - } catch (const uhd::runtime_error &e) { + } catch (const uhd::runtime_error& e) { err_str = e.what(); } } @@ -114,23 +119,23 @@ public: // void _init() { - write_ad9146_reg(0x1e, 0x01); //Datasheet: "Set 1 for proper operation" - write_ad9146_reg(0x06, 0xFF); //Clear all event flags + write_ad9146_reg(0x1e, 0x01); // Datasheet: "Set 1 for proper operation" + write_ad9146_reg(0x06, 0xFF); // Clear all event flags // Calculate N0 to be VCO friendly. // Aim for VCO between 1 and 2GHz, assert otherwise. const int N1 = 4; int N0_val, N0; - for (N0_val = 0; N0_val < 3; N0_val++) - { - N0 = (1 << N0_val); //1, 2, 4 - if ((_refclk * N0 * N1) >= 1e9) break; + for (N0_val = 0; N0_val < 3; N0_val++) { + N0 = (1 << N0_val); // 1, 2, 4 + if ((_refclk * N0 * N1) >= 1e9) + break; } UHD_ASSERT_THROW((_refclk * N0 * N1) >= 1e9); UHD_ASSERT_THROW((_refclk * N0 * N1) <= 2e9); // Start PLL - write_ad9146_reg(0x06, 0xC0); //Clear PLL event flags + write_ad9146_reg(0x06, 0xC0); // Clear PLL event flags write_ad9146_reg(0x0C, 0xD1); // Narrow PLL loop filter, Midrange charge pump. write_ad9146_reg(0x0D, 0xD1 | (N0_val << 2)); // N1=4, N2=16, N0 as calculated write_ad9146_reg(0x0A, 0xCF); // Auto init VCO band training as per datasheet @@ -149,7 +154,7 @@ public: // - First transaction goes into low bits // - Second transaction goes into high bits // therefore, we want Q to go first (bit 6 == 1) - write_ad9146_reg(0x03, (1 << 6)); //2s comp, i first, byte mode + write_ad9146_reg(0x03, (1 << 6)); // 2s comp, i first, byte mode // Configure interpolation filters write_ad9146_reg(0x1C, 0x00); // Configure HB1 @@ -165,31 +170,33 @@ public: // void _backend_sync(void) { - write_ad9146_reg(0x10, 0x40); // Disable SYNC mode to reset state machines. + write_ad9146_reg(0x10, 0x40); // Disable SYNC mode to reset state machines. - //SYNC Settings: + // SYNC Settings: //- SYNC = Enabled //- Data Rate Mode: Synchronize at the rate at which data is consumed and not at // the granularity of the FIFO //- Falling edge sync: For the X300, DACCLK is generated using RefClk. Within the // DAC, the RefClk is sampled by DACCLK to sync interpolation // stages across multiple DACs. To ensure that we capture the - // RefClk when it is not transitioning, we sample on the falling - // edge of DACCLK + // RefClk when it is not transitioning, we sample on the + // falling edge of DACCLK //- Averaging = MAX - write_ad9146_reg(0x10, 0xC7); // Enable SYNC mode. Falling edge sync. Averaging set to 128. + write_ad9146_reg( + 0x10, 0xC7); // Enable SYNC mode. Falling edge sync. Averaging set to 128. - //Wait for backend SYNC state machine to lock before proceeding. This guarantees that the - //inputs and output of the FIFO have synchronized clocks + // Wait for backend SYNC state machine to lock before proceeding. This guarantees + // that the inputs and output of the FIFO have synchronized clocks _check_dac_sync(); - //FIFO write pointer offset - //One of ADI's requirements to use data-rate synchronization in PLL mode is to meet - //setup and hold times for RefClk -> DCI clock which we *do not* currently meet in - //the FPGA. The DCI clock reaches a full RefClk cycle later which results in the - //FIFO popping before the first push. This results in a steady-state FIFO fullness - //of pointer - 1. To reach the optimal FIFO fullness of 4 we set the pointer to 5. - //FIXME: At some point we should meet timing on this interface + // FIFO write pointer offset + // One of ADI's requirements to use data-rate synchronization in PLL mode is to + // meet setup and hold times for RefClk -> DCI clock which we *do not* currently + // meet in the FPGA. The DCI clock reaches a full RefClk cycle later which results + // in the FIFO popping before the first push. This results in a steady-state FIFO + // fullness of pointer - 1. To reach the optimal FIFO fullness of 4 we set the + // pointer to 5. + // FIXME: At some point we should meet timing on this interface write_ad9146_reg(0x17, 0x05); // We are requesting a soft FIFO align just to put the FIFO @@ -204,22 +211,23 @@ public: // void _check_pll() { - //Clear PLL event flags + // Clear PLL event flags write_ad9146_reg(0x06, 0xC0); // Verify PLL is Locked. 1 sec timeout. // NOTE: Data sheet inconsistent about which pins give PLL lock status. FIXME! const time_spec_t exit_time = uhd::get_system_time() + time_spec_t(1.0); - while (true) - { + while (true) { const size_t reg_e = read_ad9146_reg(0x0E); // PLL Status (Expect bit 7 = 1) - const size_t reg_6 = read_ad9146_reg(0x06); // Event Flags (Expect bit 7 = 0 and bit 6 = 1) + const size_t reg_6 = + read_ad9146_reg(0x06); // Event Flags (Expect bit 7 = 0 and bit 6 = 1) if ((((reg_e >> 7) & 0x1) == 0x1) && (((reg_6 >> 6) & 0x3) == 0x1)) break; if (exit_time < uhd::get_system_time()) - throw uhd::runtime_error("x300_dac_ctrl: timeout waiting for DAC PLL to lock"); - if (reg_6 & (1 << 7)) // Lock lost? - write_ad9146_reg(0x06, 0xC0); // Clear PLL event flags + throw uhd::runtime_error( + "x300_dac_ctrl: timeout waiting for DAC PLL to lock"); + if (reg_6 & (1 << 7)) // Lock lost? + write_ad9146_reg(0x06, 0xC0); // Clear PLL event flags std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } @@ -234,21 +242,25 @@ public: write_ad9146_reg(0x12, 0x00); const time_spec_t exit_time = uhd::get_system_time() + time_spec_t(1.0); - while (true) - { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // wait for sync to complete - const size_t reg_12 = read_ad9146_reg(0x12); // Sync Status (Expect bit 7 = 0, bit 6 = 1) - const size_t reg_6 = read_ad9146_reg(0x06); // Event Flags (Expect bit 5 = 0 and bit 4 = 1) + while (true) { + std::this_thread::sleep_for( + std::chrono::milliseconds(1)); // wait for sync to complete + const size_t reg_12 = + read_ad9146_reg(0x12); // Sync Status (Expect bit 7 = 0, bit 6 = 1) + const size_t reg_6 = + read_ad9146_reg(0x06); // Event Flags (Expect bit 5 = 0 and bit 4 = 1) if ((((reg_12 >> 6) & 0x3) == 0x1) && (((reg_6 >> 4) & 0x3) == 0x1)) break; if (exit_time < uhd::get_system_time()) - throw uhd::runtime_error("x300_dac_ctrl: timeout waiting for backend synchronization"); + throw uhd::runtime_error( + "x300_dac_ctrl: timeout waiting for backend synchronization"); if (reg_6 & (1 << 5)) - write_ad9146_reg(0x06, 0x30); // Clear Sync event flags + write_ad9146_reg(0x06, 0x30); // Clear Sync event flags #ifdef X300_DAC_RETRY_BACKEND_SYNC - if (reg_12 & (1 << 7)) { // Sync acquired and lost? - write_ad9146_reg(0x10, 0xC7); // Enable SYNC mode. Falling edge sync. Averaging set to 128. - write_ad9146_reg(0x12, 0x00); // Clear Sync event flags + if (reg_12 & (1 << 7)) { // Sync acquired and lost? + write_ad9146_reg(0x10, + 0xC7); // Enable SYNC mode. Falling edge sync. Averaging set to 128. + write_ad9146_reg(0x12, 0x00); // Clear Sync event flags } #endif } @@ -262,7 +274,11 @@ public: // Register 0x19 has a thermometer indicator of the FIFO depth const size_t reg_19 = read_ad9146_reg(0x19); if ((reg_19 & 0xFF) != 0xF) { - std::string msg((boost::format("x300_dac_ctrl: front-end sync failed. unexpected FIFO depth [0x%x]") % (reg_19 & 0xFF)).str()); + std::string msg( + (boost::format( + "x300_dac_ctrl: front-end sync failed. unexpected FIFO depth [0x%x]") + % (reg_19 & 0xFF)) + .str()); if (failure_is_fatal) { throw uhd::runtime_error(msg); } else { @@ -273,10 +289,10 @@ public: void _sleep_mode(bool sleep) { - uint8_t sleep_val = sleep ? (1<<7) : 0x00; - //Set sleep word and default fullscale value - write_ad9146_reg(0x41, sleep_val | 0x01); //I DAC - write_ad9146_reg(0x45, sleep_val | 0x01); //Q DAC + uint8_t sleep_val = sleep ? (1 << 7) : 0x00; + // Set sleep word and default fullscale value + write_ad9146_reg(0x41, sleep_val | 0x01); // I DAC + write_ad9146_reg(0x45, sleep_val | 0x01); // Q DAC } void _soft_reset() @@ -294,7 +310,8 @@ private: /*********************************************************************** * Public make function for the DAC control **********************************************************************/ -x300_dac_ctrl::sptr x300_dac_ctrl::make(uhd::spi_iface::sptr iface, const size_t slaveno, const double clock_rate) +x300_dac_ctrl::sptr x300_dac_ctrl::make( + uhd::spi_iface::sptr iface, const size_t slaveno, const double clock_rate) { return sptr(new x300_dac_ctrl_impl(iface, slaveno, clock_rate)); } diff --git a/host/lib/usrp/x300/x300_dac_ctrl.hpp b/host/lib/usrp/x300/x300_dac_ctrl.hpp index 0ef99011b..74dba0cb4 100644 --- a/host/lib/usrp/x300/x300_dac_ctrl.hpp +++ b/host/lib/usrp/x300/x300_dac_ctrl.hpp @@ -25,7 +25,8 @@ public: * \param spiface the interface to spi * \return a new codec control object */ - static sptr make(uhd::spi_iface::sptr iface, const size_t slaveno, const double clock_rate); + static sptr make( + uhd::spi_iface::sptr iface, const size_t slaveno, const double clock_rate); // ! Reset the DAC virtual void reset(void) = 0; diff --git a/host/lib/usrp/x300/x300_dboard_iface.cpp b/host/lib/usrp/x300/x300_dboard_iface.cpp index 6986ee8ab..36e430985 100644 --- a/host/lib/usrp/x300/x300_dboard_iface.cpp +++ b/host/lib/usrp/x300/x300_dboard_iface.cpp @@ -18,14 +18,13 @@ using namespace boost::assign; /*********************************************************************** * Structors **********************************************************************/ -x300_dboard_iface::x300_dboard_iface(const x300_dboard_iface_config_t &config): - _config(config) +x300_dboard_iface::x300_dboard_iface(const x300_dboard_iface_config_t& config) + : _config(config) { - //reset the aux dacs + // reset the aux dacs _dac_regs[UNIT_RX] = ad5623_regs_t(); _dac_regs[UNIT_TX] = ad5623_regs_t(); - for(unit_t unit: _dac_regs.keys()) - { + for (unit_t unit : _dac_regs.keys()) { _dac_regs[unit].data = 1; _dac_regs[unit].addr = ad5623_regs_t::ADDR_ALL; _dac_regs[unit].cmd = ad5623_regs_t::CMD_RESET; @@ -41,11 +40,8 @@ x300_dboard_iface::x300_dboard_iface(const x300_dboard_iface_config_t &config): x300_dboard_iface::~x300_dboard_iface(void) { - UHD_SAFE_CALL - ( - this->set_clock_enabled(UNIT_RX, false); - this->set_clock_enabled(UNIT_TX, false); - ) + UHD_SAFE_CALL(this->set_clock_enabled(UNIT_RX, false); + this->set_clock_enabled(UNIT_TX, false);) } /*********************************************************************** @@ -53,14 +49,14 @@ x300_dboard_iface::~x300_dboard_iface(void) **********************************************************************/ void x300_dboard_iface::set_clock_rate(unit_t unit, double rate) { - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); // Just return if the requested rate is already set if (std::abs(_clock_rates[unit] - rate) < std::numeric_limits<double>::epsilon()) return; - switch(unit) - { + switch (unit) { case UNIT_RX: _config.clock->set_dboard_rate(_config.which_rx_clk, rate); break; @@ -70,20 +66,21 @@ void x300_dboard_iface::set_clock_rate(unit_t unit, double rate) default: UHD_THROW_INVALID_CODE_PATH(); } - _clock_rates[unit] = rate; //set to shadow + _clock_rates[unit] = rate; // set to shadow } double x300_dboard_iface::get_clock_rate(unit_t unit) { - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); - return _clock_rates[unit]; //get from shadow + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); + return _clock_rates[unit]; // get from shadow } std::vector<double> x300_dboard_iface::get_clock_rates(unit_t unit) { - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); - switch(unit) - { + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); + switch (unit) { case UNIT_RX: return _config.clock->get_dboard_rates(_config.which_rx_clk); case UNIT_TX: @@ -95,9 +92,9 @@ std::vector<double> x300_dboard_iface::get_clock_rates(unit_t unit) void x300_dboard_iface::set_clock_enabled(unit_t unit, bool enb) { - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); - switch(unit) - { + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); + switch (unit) { case UNIT_RX: return _config.clock->enable_dboard_clock(_config.which_rx_clk, enb); case UNIT_TX: @@ -109,7 +106,8 @@ void x300_dboard_iface::set_clock_enabled(unit_t unit, bool enb) double x300_dboard_iface::get_codec_rate(unit_t unit) { - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); return _config.clock->get_master_clock_rate(); } @@ -126,7 +124,8 @@ uint32_t x300_dboard_iface::get_pin_ctrl(unit_t unit) return _config.gpio->get_pin_ctrl(unit); } -void x300_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t reg, uint32_t value, uint32_t mask) +void x300_dboard_iface::set_atr_reg( + unit_t unit, atr_reg_t reg, uint32_t value, uint32_t mask) { _config.gpio->set_atr_reg(unit, reg, value, mask); } @@ -165,34 +164,33 @@ uint32_t x300_dboard_iface::read_gpio(unit_t unit) * SPI **********************************************************************/ void x300_dboard_iface::write_spi( - unit_t unit, - const spi_config_t &config, - uint32_t data, - size_t num_bits -){ + unit_t unit, const spi_config_t& config, uint32_t data, size_t num_bits) +{ uint32_t slave = 0; - if (unit == UNIT_TX) slave |= _config.tx_spi_slaveno; - if (unit == UNIT_RX) slave |= _config.rx_spi_slaveno; + if (unit == UNIT_TX) + slave |= _config.tx_spi_slaveno; + if (unit == UNIT_RX) + slave |= _config.rx_spi_slaveno; _config.spi->write_spi(int(slave), config, data, num_bits); } uint32_t x300_dboard_iface::read_write_spi( - unit_t unit, - const spi_config_t &config, - uint32_t data, - size_t num_bits -){ - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + unit_t unit, const spi_config_t& config, uint32_t data, size_t num_bits) +{ + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); return _config.spi->read_spi( - (unit==dboard_iface::UNIT_TX)?_config.tx_spi_slaveno:_config.rx_spi_slaveno, - config, data, num_bits); + (unit == dboard_iface::UNIT_TX) ? _config.tx_spi_slaveno : _config.rx_spi_slaveno, + config, + data, + num_bits); } /*********************************************************************** * I2C **********************************************************************/ -void x300_dboard_iface::write_i2c(uint16_t addr, const byte_vector_t &bytes) +void x300_dboard_iface::write_i2c(uint16_t addr, const byte_vector_t& bytes) { return _config.i2c->write_i2c(addr, bytes); } @@ -207,76 +205,67 @@ byte_vector_t x300_dboard_iface::read_i2c(uint16_t addr, size_t num_bytes) **********************************************************************/ void x300_dboard_iface::_write_aux_dac(unit_t unit) { - static const uhd::dict<unit_t, int> unit_to_spi_dac = map_list_of - (UNIT_RX, DB_RX_LSDAC_SEN) - (UNIT_TX, DB_TX_LSDAC_SEN) - ; - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + static const uhd::dict<unit_t, int> unit_to_spi_dac = + map_list_of(UNIT_RX, DB_RX_LSDAC_SEN)(UNIT_TX, DB_TX_LSDAC_SEN); + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); _config.spi->write_spi( - unit_to_spi_dac[unit], spi_config_t::EDGE_FALL, - _dac_regs[unit].get_reg(), 24 - ); + unit_to_spi_dac[unit], spi_config_t::EDGE_FALL, _dac_regs[unit].get_reg(), 24); } void x300_dboard_iface::write_aux_dac(unit_t unit, aux_dac_t which, double value) { - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); - _dac_regs[unit].data = boost::math::iround(4095*value/3.3); - _dac_regs[unit].cmd = ad5623_regs_t::CMD_WR_UP_DAC_CHAN_N; + _dac_regs[unit].data = boost::math::iround(4095 * value / 3.3); + _dac_regs[unit].cmd = ad5623_regs_t::CMD_WR_UP_DAC_CHAN_N; typedef uhd::dict<aux_dac_t, ad5623_regs_t::addr_t> aux_dac_to_addr; - static const uhd::dict<unit_t, aux_dac_to_addr> unit_to_which_to_addr = map_list_of - (UNIT_RX, map_list_of - (AUX_DAC_A, ad5623_regs_t::ADDR_DAC_A) - (AUX_DAC_B, ad5623_regs_t::ADDR_DAC_B) - (AUX_DAC_C, ad5623_regs_t::ADDR_DAC_B) - (AUX_DAC_D, ad5623_regs_t::ADDR_DAC_A) - ) - (UNIT_TX, map_list_of - (AUX_DAC_A, ad5623_regs_t::ADDR_DAC_A) - (AUX_DAC_B, ad5623_regs_t::ADDR_DAC_B) - (AUX_DAC_C, ad5623_regs_t::ADDR_DAC_B) - (AUX_DAC_D, ad5623_regs_t::ADDR_DAC_A) - ) - ; + static const uhd::dict<unit_t, aux_dac_to_addr> unit_to_which_to_addr = + map_list_of(UNIT_RX, + map_list_of(AUX_DAC_A, ad5623_regs_t::ADDR_DAC_A)(AUX_DAC_B, + ad5623_regs_t::ADDR_DAC_B)(AUX_DAC_C, ad5623_regs_t::ADDR_DAC_B)( + AUX_DAC_D, ad5623_regs_t::ADDR_DAC_A))(UNIT_TX, + map_list_of(AUX_DAC_A, ad5623_regs_t::ADDR_DAC_A)(AUX_DAC_B, + ad5623_regs_t::ADDR_DAC_B)(AUX_DAC_C, ad5623_regs_t::ADDR_DAC_B)( + AUX_DAC_D, ad5623_regs_t::ADDR_DAC_A)); _dac_regs[unit].addr = unit_to_which_to_addr[unit][which]; this->_write_aux_dac(unit); } double x300_dboard_iface::read_aux_adc(unit_t unit, aux_adc_t which) { - static const uhd::dict<unit_t, int> unit_to_spi_adc = map_list_of - (UNIT_RX, DB_RX_LSADC_SEN) - (UNIT_TX, DB_TX_LSADC_SEN) - ; + static const uhd::dict<unit_t, int> unit_to_spi_adc = + map_list_of(UNIT_RX, DB_RX_LSADC_SEN)(UNIT_TX, DB_TX_LSADC_SEN); - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); - //setup spi config args + // setup spi config args spi_config_t config; config.mosi_edge = spi_config_t::EDGE_FALL; config.miso_edge = spi_config_t::EDGE_RISE; - //setup the spi registers + // setup the spi registers ad7922_regs_t ad7922_regs; - switch(which){ - case AUX_ADC_A: ad7922_regs.mod = 0; break; - case AUX_ADC_B: ad7922_regs.mod = 1; break; - } ad7922_regs.chn = ad7922_regs.mod; //normal mode: mod == chn + switch (which) { + case AUX_ADC_A: + ad7922_regs.mod = 0; + break; + case AUX_ADC_B: + ad7922_regs.mod = 1; + break; + } + ad7922_regs.chn = ad7922_regs.mod; // normal mode: mod == chn - //write and read spi - _config.spi->write_spi( - unit_to_spi_adc[unit], config, - ad7922_regs.get_reg(), 16 - ); - ad7922_regs.set_reg(uint16_t(_config.spi->read_spi( - unit_to_spi_adc[unit], config, - ad7922_regs.get_reg(), 16 - ))); - - //convert to voltage and return - return 3.3*ad7922_regs.result/4095; + // write and read spi + _config.spi->write_spi(unit_to_spi_adc[unit], config, ad7922_regs.get_reg(), 16); + ad7922_regs.set_reg(uint16_t( + _config.spi->read_spi(unit_to_spi_adc[unit], config, ad7922_regs.get_reg(), 16))); + + // convert to voltage and return + return 3.3 * ad7922_regs.result / 4095; } uhd::time_spec_t x300_dboard_iface::get_command_time() @@ -290,15 +279,13 @@ void x300_dboard_iface::set_command_time(const uhd::time_spec_t& t) } void x300_dboard_iface::add_rx_fe( - const std::string& fe_name, - rx_frontend_core_3000::sptr fe_core) + const std::string& fe_name, rx_frontend_core_3000::sptr fe_core) { _rx_fes[fe_name] = fe_core; } void x300_dboard_iface::set_fe_connection( - unit_t unit, const std::string& fe_name, - const fe_connection_t& fe_conn) + unit_t unit, const std::string& fe_name, const fe_connection_t& fe_conn) { if (unit == UNIT_RX) { if (_rx_fes.has_key(fe_name)) { diff --git a/host/lib/usrp/x300/x300_dboard_iface.hpp b/host/lib/usrp/x300/x300_dboard_iface.hpp index f41bb3d42..713c90748 100644 --- a/host/lib/usrp/x300/x300_dboard_iface.hpp +++ b/host/lib/usrp/x300/x300_dboard_iface.hpp @@ -8,41 +8,41 @@ #ifndef INCLUDED_X300_DBOARD_IFACE_HPP #define INCLUDED_X300_DBOARD_IFACE_HPP +#include "ad5623_regs.hpp" //aux dac +#include "ad7922_regs.hpp" //aux adc #include "x300_clock_ctrl.hpp" -#include <uhdlib/usrp/cores/spi_core_3000.hpp> -#include <uhdlib/usrp/cores/i2c_core_100_wb32.hpp> +#include <uhd/types/dict.hpp> +#include <uhd/usrp/dboard_iface.hpp> #include <uhdlib/usrp/cores/gpio_atr_3000.hpp> +#include <uhdlib/usrp/cores/i2c_core_100_wb32.hpp> #include <uhdlib/usrp/cores/rx_frontend_core_3000.hpp> -#include "ad7922_regs.hpp" //aux adc -#include "ad5623_regs.hpp" //aux dac -#include <uhd/usrp/dboard_iface.hpp> -#include <uhd/types/dict.hpp> +#include <uhdlib/usrp/cores/spi_core_3000.hpp> struct x300_dboard_iface_config_t { uhd::usrp::gpio_atr::db_gpio_atr_3000::sptr gpio; - spi_core_3000::sptr spi; - size_t rx_spi_slaveno; - size_t tx_spi_slaveno; - uhd::i2c_iface::sptr i2c; - x300_clock_ctrl::sptr clock; - x300_clock_which_t which_rx_clk; - x300_clock_which_t which_tx_clk; - uint8_t dboard_slot; - uhd::timed_wb_iface::sptr cmd_time_ctrl; + spi_core_3000::sptr spi; + size_t rx_spi_slaveno; + size_t tx_spi_slaveno; + uhd::i2c_iface::sptr i2c; + x300_clock_ctrl::sptr clock; + x300_clock_which_t which_rx_clk; + x300_clock_which_t which_tx_clk; + uint8_t dboard_slot; + uhd::timed_wb_iface::sptr cmd_time_ctrl; }; class x300_dboard_iface : public uhd::usrp::dboard_iface { public: - x300_dboard_iface(const x300_dboard_iface_config_t &config); + x300_dboard_iface(const x300_dboard_iface_config_t& config); ~x300_dboard_iface(void); inline special_props_t get_special_props(void) { special_props_t props; props.soft_clock_divider = false; - props.mangle_i2c_addrs = (_config.dboard_slot == 1); + props.mangle_i2c_addrs = (_config.dboard_slot == 1); return props; } @@ -51,7 +51,8 @@ public: void set_pin_ctrl(unit_t unit, uint32_t value, uint32_t mask = 0xffffffff); uint32_t get_pin_ctrl(unit_t unit); - void set_atr_reg(unit_t unit, atr_reg_t reg, uint32_t value, uint32_t mask = 0xffffffff); + void set_atr_reg( + unit_t unit, atr_reg_t reg, uint32_t value, uint32_t mask = 0xffffffff); uint32_t get_atr_reg(unit_t unit, atr_reg_t reg); void set_gpio_ddr(unit_t unit, uint32_t value, uint32_t mask = 0xffffffff); uint32_t get_gpio_ddr(unit_t unit); @@ -62,7 +63,7 @@ public: void set_command_time(const uhd::time_spec_t& t); uhd::time_spec_t get_command_time(void); - void write_i2c(uint16_t, const uhd::byte_vector_t &); + void write_i2c(uint16_t, const uhd::byte_vector_t&); uhd::byte_vector_t read_i2c(uint16_t, size_t); void set_clock_rate(unit_t, double); @@ -72,21 +73,12 @@ public: double get_codec_rate(unit_t); void write_spi( - unit_t unit, - const uhd::spi_config_t &config, - uint32_t data, - size_t num_bits - ); + unit_t unit, const uhd::spi_config_t& config, uint32_t data, size_t num_bits); uint32_t read_write_spi( - unit_t unit, - const uhd::spi_config_t &config, - uint32_t data, - size_t num_bits - ); + unit_t unit, const uhd::spi_config_t& config, uint32_t data, size_t num_bits); void set_fe_connection( - unit_t unit, const std::string& name, - const uhd::usrp::fe_connection_t& fe_conn); + unit_t unit, const std::string& name, const uhd::usrp::fe_connection_t& fe_conn); // X300 can set the FE connection on the RX side bool has_set_fe_connection(const unit_t unit) override @@ -94,9 +86,7 @@ public: return unit == UNIT_RX; } - void add_rx_fe( - const std::string& fe_name, - rx_frontend_core_3000::sptr fe_core); + void add_rx_fe(const std::string& fe_name, rx_frontend_core_3000::sptr fe_core); private: const x300_dboard_iface_config_t _config; @@ -107,5 +97,4 @@ private: }; - #endif /* INCLUDED_X300_DBOARD_IFACE_HPP */ diff --git a/host/lib/usrp/x300/x300_defaults.hpp b/host/lib/usrp/x300/x300_defaults.hpp index aa8d1b688..2e242f24f 100644 --- a/host/lib/usrp/x300/x300_defaults.hpp +++ b/host/lib/usrp/x300/x300_defaults.hpp @@ -7,103 +7,100 @@ #ifndef INCLUDED_X300_DEFAULTS_HPP #define INCLUDED_X300_DEFAULTS_HPP -#include <uhd/transport/udp_simple.hpp> //mtu #include "../device3/device3_impl.hpp" +#include <uhd/transport/udp_simple.hpp> //mtu #include <string> - -namespace uhd { -namespace usrp { -namespace x300 { +namespace uhd { namespace usrp { namespace x300 { static constexpr size_t NIUSRPRIO_DEFAULT_RPC_PORT = 5444; static constexpr uint32_t RADIO_DEST_PREFIX_TX = 0; -static constexpr size_t XB_DST_E0 = 0; -static constexpr size_t XB_DST_E1 = 1; -static constexpr size_t XB_DST_PCI = 2; -static constexpr size_t XB_DST_R0 = 3; // Radio 0 -> Slot A -static constexpr size_t XB_DST_R1 = 4; // Radio 1 -> Slot B -static constexpr size_t XB_DST_CE0 = 5; +static constexpr size_t XB_DST_E0 = 0; +static constexpr size_t XB_DST_E1 = 1; +static constexpr size_t XB_DST_PCI = 2; +static constexpr size_t XB_DST_R0 = 3; // Radio 0 -> Slot A +static constexpr size_t XB_DST_R1 = 4; // Radio 1 -> Slot B +static constexpr size_t XB_DST_CE0 = 5; -static constexpr size_t SRC_ADDR0 = 0; -static constexpr size_t SRC_ADDR1 = 1; -static constexpr size_t DST_ADDR = 2; +static constexpr size_t SRC_ADDR0 = 0; +static constexpr size_t SRC_ADDR1 = 1; +static constexpr size_t DST_ADDR = 2; -static constexpr double DEFAULT_TICK_RATE = 200e6; // Hz -static constexpr double MAX_TICK_RATE = 200e6; // Hz -static constexpr double MIN_TICK_RATE = 184.32e6; // Hz -static constexpr double BUS_CLOCK_RATE = 187.5e6; // Hz +static constexpr double DEFAULT_TICK_RATE = 200e6; // Hz +static constexpr double MAX_TICK_RATE = 200e6; // Hz +static constexpr double MIN_TICK_RATE = 184.32e6; // Hz +static constexpr double BUS_CLOCK_RATE = 187.5e6; // Hz -static const std::string FW_FILE_NAME = "usrp_x300_fw.bin"; +static const std::string FW_FILE_NAME = "usrp_x300_fw.bin"; // Clock & Time-related defaults static const std::string DEFAULT_CLOCK_SOURCE = "internal"; static const std::string DEFAULT_TIME_SOURCE = "internal"; -static const bool DEFAULT_TIME_OUTPUT = true; +static const bool DEFAULT_TIME_OUTPUT = true; static const std::vector<std::string> CLOCK_SOURCE_OPTIONS{ - "internal", - "external", - "gpsdo" -}; + "internal", "external", "gpsdo"}; static const std::vector<std::string> TIME_SOURCE_OPTIONS{ - "internal", - "external", - "gpsdo" -}; + "internal", "external", "gpsdo"}; static const std::vector<double> EXTERNAL_FREQ_OPTIONS{10e6, 30.72e6, 200e6}; -static constexpr size_t RX_SW_BUFF_SIZE_ETH = 0x2000000;//32MiB For an ~8k frame size any size >32MiB is just wasted buffer space -static constexpr size_t RX_SW_BUFF_SIZE_ETH_MACOS = 0x100000; //1Mib - -//The FIFO closest to the DMA controller is 1023 elements deep for RX and 1029 elements deep for TX -//where an element is 8 bytes. The buffers (number of frames * frame size) must be aligned to the -//memory page size. For the control, we are getting lucky because 64 frames * 256 bytes each aligns -//with the typical page size of 4096 bytes. Since most page sizes are 4096 bytes or some multiple of -//that, keep the number of frames * frame size aligned to it. -static constexpr size_t PCIE_RX_DATA_FRAME_SIZE = 4096; //bytes -static constexpr size_t PCIE_RX_DATA_NUM_FRAMES = 4096; -static constexpr size_t PCIE_TX_DATA_FRAME_SIZE = 4096; //bytes -static constexpr size_t PCIE_TX_DATA_NUM_FRAMES = 4096; -static constexpr size_t PCIE_MSG_FRAME_SIZE = 256; //bytes -static constexpr size_t PCIE_MSG_NUM_FRAMES = 64; -static constexpr size_t PCIE_MAX_CHANNELS = 6; -static constexpr size_t PCIE_MAX_MUXED_CTRL_XPORTS = 32; -static constexpr size_t PCIE_MAX_MUXED_ASYNC_XPORTS = 4; - -static const size_t DATA_FRAME_MAX_SIZE = 8000; // CHDR packet size in bytes -static const size_t XGE_DATA_FRAME_SEND_SIZE = 4000; // Reduced to make sure flow control packets are not blocked for too long at high rates -static const size_t XGE_DATA_FRAME_RECV_SIZE = 8000; -static const size_t GE_DATA_FRAME_SEND_SIZE = 1472; -static const size_t GE_DATA_FRAME_RECV_SIZE = 1472; - -static const size_t ETH_MSG_FRAME_SIZE = uhd::transport::udp_simple::mtu; //bytes +static constexpr size_t RX_SW_BUFF_SIZE_ETH = + 0x2000000; // 32MiB For an ~8k frame size any size >32MiB is just wasted buffer + // space +static constexpr size_t RX_SW_BUFF_SIZE_ETH_MACOS = 0x100000; // 1Mib + +// The FIFO closest to the DMA controller is 1023 elements deep for RX and 1029 elements +// deep for TX where an element is 8 bytes. The buffers (number of frames * frame size) +// must be aligned to the memory page size. For the control, we are getting lucky because +// 64 frames * 256 bytes each aligns with the typical page size of 4096 bytes. Since most +// page sizes are 4096 bytes or some multiple of that, keep the number of frames * frame +// size aligned to it. +static constexpr size_t PCIE_RX_DATA_FRAME_SIZE = 4096; // bytes +static constexpr size_t PCIE_RX_DATA_NUM_FRAMES = 4096; +static constexpr size_t PCIE_TX_DATA_FRAME_SIZE = 4096; // bytes +static constexpr size_t PCIE_TX_DATA_NUM_FRAMES = 4096; +static constexpr size_t PCIE_MSG_FRAME_SIZE = 256; // bytes +static constexpr size_t PCIE_MSG_NUM_FRAMES = 64; +static constexpr size_t PCIE_MAX_CHANNELS = 6; +static constexpr size_t PCIE_MAX_MUXED_CTRL_XPORTS = 32; +static constexpr size_t PCIE_MAX_MUXED_ASYNC_XPORTS = 4; + +static const size_t DATA_FRAME_MAX_SIZE = 8000; // CHDR packet size in bytes +static const size_t XGE_DATA_FRAME_SEND_SIZE = + 4000; // Reduced to make sure flow control packets are not blocked for too long at + // high rates +static const size_t XGE_DATA_FRAME_RECV_SIZE = 8000; +static const size_t GE_DATA_FRAME_SEND_SIZE = 1472; +static const size_t GE_DATA_FRAME_RECV_SIZE = 1472; + +static const size_t ETH_MSG_FRAME_SIZE = uhd::transport::udp_simple::mtu; // bytes // MTU throttling for ethernet/TX (see above): static constexpr size_t ETH_DATA_FRAME_MAX_TX_SIZE = 8000; -static constexpr double RECV_OFFLOAD_BUFFER_TIMEOUT = 0.1; //seconds -static constexpr double THREAD_BUFFER_TIMEOUT = 0.1; // Time in seconds +static constexpr double RECV_OFFLOAD_BUFFER_TIMEOUT = 0.1; // seconds +static constexpr double THREAD_BUFFER_TIMEOUT = 0.1; // Time in seconds -static constexpr size_t ETH_MSG_NUM_FRAMES = 64; -static constexpr size_t ETH_DATA_NUM_FRAMES = 32; -static constexpr double DEFAULT_SYSREF_RATE = 10e6; +static constexpr size_t ETH_MSG_NUM_FRAMES = 64; +static constexpr size_t ETH_DATA_NUM_FRAMES = 32; +static constexpr double DEFAULT_SYSREF_RATE = 10e6; // Limit the number of initialization threads -static const size_t MAX_INIT_THREADS = 10; - -static const size_t MAX_RATE_PCIE = 800000000; // bytes/s -static const size_t MAX_RATE_10GIGE = (size_t)( // bytes/s - 10e9 / 8 * // wire speed multiplied by percentage of packets that is sample data - ( float(DATA_FRAME_MAX_SIZE - uhd::usrp::DEVICE3_TX_MAX_HDR_LEN) / - float(DATA_FRAME_MAX_SIZE + 8 /* UDP header */ + 20 /* Ethernet header length */ ))); -static const size_t MAX_RATE_1GIGE = (size_t)( // bytes/s - 10e9 / 8 * // wire speed multiplied by percentage of packets that is sample data - ( float(GE_DATA_FRAME_RECV_SIZE - uhd::usrp::DEVICE3_TX_MAX_HDR_LEN) / - float(GE_DATA_FRAME_RECV_SIZE + 8 /* UDP header */ + 20 /* Ethernet header length */ ))); +static const size_t MAX_INIT_THREADS = 10; + +static const size_t MAX_RATE_PCIE = 800000000; // bytes/s +static const size_t MAX_RATE_10GIGE = (size_t)( // bytes/s + 10e9 / 8 * // wire speed multiplied by percentage of packets that is sample data + (float(DATA_FRAME_MAX_SIZE - uhd::usrp::DEVICE3_TX_MAX_HDR_LEN) + / float(DATA_FRAME_MAX_SIZE + + 8 /* UDP header */ + 20 /* Ethernet header length */))); +static const size_t MAX_RATE_1GIGE = (size_t)( // bytes/s + 10e9 / 8 * // wire speed multiplied by percentage of packets that is sample data + (float(GE_DATA_FRAME_RECV_SIZE - uhd::usrp::DEVICE3_TX_MAX_HDR_LEN) + / float(GE_DATA_FRAME_RECV_SIZE + + 8 /* UDP header */ + 20 /* Ethernet header length */))); }}} /* namespace uhd::usrp::x300 */ #endif /* INCLUDED_X300_DEFAULTS_HPP */ - diff --git a/host/lib/usrp/x300/x300_device_args.hpp b/host/lib/usrp/x300/x300_device_args.hpp index db1a01212..bdb3762af 100644 --- a/host/lib/usrp/x300/x300_device_args.hpp +++ b/host/lib/usrp/x300/x300_device_args.hpp @@ -7,8 +7,8 @@ #ifndef INCLUDED_X300_DEV_ARGS_HPP #define INCLUDED_X300_DEV_ARGS_HPP -#include "x300_impl.hpp" #include "x300_defaults.hpp" +#include "x300_impl.hpp" #include <uhdlib/usrp/constrained_device_args.hpp> namespace uhd { namespace usrp { namespace x300 { @@ -16,97 +16,116 @@ namespace uhd { namespace usrp { namespace x300 { class x300_device_args_t : public constrained_device_args_t { public: - x300_device_args_t(): - _master_clock_rate("master_clock_rate", DEFAULT_TICK_RATE), - _dboard_clock_rate("dboard_clock_rate", -1), - _system_ref_rate("system_ref_rate", DEFAULT_SYSREF_RATE), - _clock_source("clock_source", DEFAULT_CLOCK_SOURCE), - _time_source("time_source", DEFAULT_TIME_SOURCE), - _first_addr("addr", ""), - _second_addr("second_addr", ""), - _resource("resource", ""), - _self_cal_adc_delay("self_cal_adc_delay", false), - _ext_adc_self_test("ext_adc_self_test", false), - _ext_adc_self_test_duration("ext_adc_self_test", 30.0), - _recover_mb_eeprom("recover_mb_eeprom", false), - _ignore_cal_file("ignore_cal_file", false), - _niusrprio_rpc_port("niusrprio_rpc_port", NIUSRPRIO_DEFAULT_RPC_PORT), - _has_fw_file("fw", false), - _fw_file("fw", ""), - _blank_eeprom("blank_eeprom", false), - _enable_tx_dual_eth("enable_tx_dual_eth", false) + x300_device_args_t() + : _master_clock_rate("master_clock_rate", DEFAULT_TICK_RATE) + , _dboard_clock_rate("dboard_clock_rate", -1) + , _system_ref_rate("system_ref_rate", DEFAULT_SYSREF_RATE) + , _clock_source("clock_source", DEFAULT_CLOCK_SOURCE) + , _time_source("time_source", DEFAULT_TIME_SOURCE) + , _first_addr("addr", "") + , _second_addr("second_addr", "") + , _resource("resource", "") + , _self_cal_adc_delay("self_cal_adc_delay", false) + , _ext_adc_self_test("ext_adc_self_test", false) + , _ext_adc_self_test_duration("ext_adc_self_test", 30.0) + , _recover_mb_eeprom("recover_mb_eeprom", false) + , _ignore_cal_file("ignore_cal_file", false) + , _niusrprio_rpc_port("niusrprio_rpc_port", NIUSRPRIO_DEFAULT_RPC_PORT) + , _has_fw_file("fw", false) + , _fw_file("fw", "") + , _blank_eeprom("blank_eeprom", false) + , _enable_tx_dual_eth("enable_tx_dual_eth", false) { // nop } - double get_master_clock_rate() const { + double get_master_clock_rate() const + { return _master_clock_rate.get(); } - double get_dboard_clock_rate() const { + double get_dboard_clock_rate() const + { return _dboard_clock_rate.get(); } - double get_system_ref_rate() const { + double get_system_ref_rate() const + { return _system_ref_rate.get(); } - std::string get_clock_source() const { + std::string get_clock_source() const + { return _clock_source.get(); } - std::string get_time_source() const { + std::string get_time_source() const + { return _time_source.get(); } - std::string get_first_addr() const { + std::string get_first_addr() const + { return _first_addr.get(); } - std::string get_second_addr() const { + std::string get_second_addr() const + { return _second_addr.get(); } - bool get_self_cal_adc_delay() const { + bool get_self_cal_adc_delay() const + { return _self_cal_adc_delay.get(); } - bool get_ext_adc_self_test() const { + bool get_ext_adc_self_test() const + { return _ext_adc_self_test.get(); } - double get_ext_adc_self_test_duration() const { + double get_ext_adc_self_test_duration() const + { return _ext_adc_self_test_duration.get(); } - bool get_recover_mb_eeprom() const { + bool get_recover_mb_eeprom() const + { return _recover_mb_eeprom.get(); } - bool get_ignore_cal_file() const { + bool get_ignore_cal_file() const + { return _ignore_cal_file.get(); } // must be a number in the string // default NIUSRPRIO_DEFAULT_RPC_PORT - std::string get_niusrprio_rpc_port() const { + std::string get_niusrprio_rpc_port() const + { return std::to_string(_niusrprio_rpc_port.get()); } - std::string get_resource() const { + std::string get_resource() const + { return _resource.get(); } // must be valid file, key == fw, default x300::FW_FILE_NAME - std::string get_fw_file() const { + std::string get_fw_file() const + { return _fw_file.get(); } // true if the key is set - bool has_fw_file() const { + bool has_fw_file() const + { return _has_fw_file.get(); } - bool get_blank_eeprom() const { + bool get_blank_eeprom() const + { return _blank_eeprom.get(); } - bool get_enable_tx_dual_eth() const { + bool get_enable_tx_dual_eth() const + { return _enable_tx_dual_eth.get(); } - inline virtual std::string to_string() const { - return _master_clock_rate.to_string() + ", " + - ""; + inline virtual std::string to_string() const + { + return _master_clock_rate.to_string() + ", " + ""; } private: - virtual void _parse(const device_addr_t& dev_args) { - //Extract parameters from dev_args + virtual void _parse(const device_addr_t& dev_args) + { + // Extract parameters from dev_args #define PARSE_DEFAULT(arg) parse_arg_default(dev_args, arg); PARSE_DEFAULT(_master_clock_rate) if (dev_args.has_key(_master_clock_rate.key())) { @@ -118,14 +137,12 @@ private: // Some daughterboards may require other rates, but this default // works best for all newer daughterboards (i.e. CBX, WBX, SBX, // UBX, and TwinRX). - if (_master_clock_rate.get() >= MIN_TICK_RATE && - _master_clock_rate.get() <= MAX_TICK_RATE) { + if (_master_clock_rate.get() >= MIN_TICK_RATE + && _master_clock_rate.get() <= MAX_TICK_RATE) { _dboard_clock_rate.set(_master_clock_rate.get() / 4); } else { - throw uhd::value_error( - "Can't infer daughterboard clock rate. Specify " - "dboard_clk_rate in the device args." - ); + throw uhd::value_error("Can't infer daughterboard clock rate. Specify " + "dboard_clk_rate in the device args."); } } PARSE_DEFAULT(_system_ref_rate) @@ -152,11 +169,11 @@ private: PARSE_DEFAULT(_fw_file); } PARSE_DEFAULT(_blank_eeprom) - if (dev_args.has_key("enable_tx_dual_eth")){ + if (dev_args.has_key("enable_tx_dual_eth")) { _enable_tx_dual_eth.set(true); } - //Sanity check params + // Sanity check params _enforce_range(_master_clock_rate, MIN_TICK_RATE, MAX_TICK_RATE); _enforce_discrete(_system_ref_rate, EXTERNAL_FREQ_OPTIONS); _enforce_discrete(_clock_source, CLOCK_SOURCE_OPTIONS); @@ -164,26 +181,26 @@ private: // TODO: If _fw_file is set, make sure it's actually a file } - constrained_device_args_t::num_arg<double> _master_clock_rate; - constrained_device_args_t::num_arg<double> _dboard_clock_rate; - constrained_device_args_t::num_arg<double> _system_ref_rate; - constrained_device_args_t::str_arg<false> _clock_source; - constrained_device_args_t::str_arg<false> _time_source; - constrained_device_args_t::str_arg<false> _first_addr; - constrained_device_args_t::str_arg<false> _second_addr; - constrained_device_args_t::str_arg<true> _resource; - constrained_device_args_t::bool_arg _self_cal_adc_delay; - constrained_device_args_t::bool_arg _ext_adc_self_test; - constrained_device_args_t::num_arg<double> _ext_adc_self_test_duration; - constrained_device_args_t::bool_arg _recover_mb_eeprom; - constrained_device_args_t::bool_arg _ignore_cal_file; - constrained_device_args_t::num_arg<size_t> _niusrprio_rpc_port; - constrained_device_args_t::bool_arg _has_fw_file; - constrained_device_args_t::str_arg<true> _fw_file; - constrained_device_args_t::bool_arg _blank_eeprom; - constrained_device_args_t::bool_arg _enable_tx_dual_eth; + constrained_device_args_t::num_arg<double> _master_clock_rate; + constrained_device_args_t::num_arg<double> _dboard_clock_rate; + constrained_device_args_t::num_arg<double> _system_ref_rate; + constrained_device_args_t::str_arg<false> _clock_source; + constrained_device_args_t::str_arg<false> _time_source; + constrained_device_args_t::str_arg<false> _first_addr; + constrained_device_args_t::str_arg<false> _second_addr; + constrained_device_args_t::str_arg<true> _resource; + constrained_device_args_t::bool_arg _self_cal_adc_delay; + constrained_device_args_t::bool_arg _ext_adc_self_test; + constrained_device_args_t::num_arg<double> _ext_adc_self_test_duration; + constrained_device_args_t::bool_arg _recover_mb_eeprom; + constrained_device_args_t::bool_arg _ignore_cal_file; + constrained_device_args_t::num_arg<size_t> _niusrprio_rpc_port; + constrained_device_args_t::bool_arg _has_fw_file; + constrained_device_args_t::str_arg<true> _fw_file; + constrained_device_args_t::bool_arg _blank_eeprom; + constrained_device_args_t::bool_arg _enable_tx_dual_eth; }; -}}} //namespace +}}} // namespace uhd::usrp::x300 -#endif //INCLUDED_X300_DEV_ARGS_HPP +#endif // INCLUDED_X300_DEV_ARGS_HPP diff --git a/host/lib/usrp/x300/x300_fw_ctrl.cpp b/host/lib/usrp/x300/x300_fw_ctrl.cpp index 21c64b509..cbe48bfe8 100644 --- a/host/lib/usrp/x300/x300_fw_ctrl.cpp +++ b/host/lib/usrp/x300/x300_fw_ctrl.cpp @@ -5,18 +5,18 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include <uhd/types/wb_iface.hpp> #include "x300_fw_common.h" +#include "x300_regs.hpp" +#include <uhd/exception.hpp> +#include <uhd/transport/nirio/niriok_proxy.h> +#include <uhd/transport/nirio/status.h> #include <uhd/transport/udp_simple.hpp> +#include <uhd/types/wb_iface.hpp> #include <uhd/utils/byteswap.hpp> #include <uhd/utils/log.hpp> -#include <uhd/exception.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/format.hpp> #include <boost/thread/mutex.hpp> -#include <uhd/transport/nirio/status.h> -#include <uhd/transport/nirio/niriok_proxy.h> -#include "x300_regs.hpp" -#include <boost/date_time/posix_time/posix_time.hpp> #include <chrono> #include <thread> @@ -26,7 +26,7 @@ using namespace uhd::niusrprio; class x300_ctrl_iface : public wb_iface { public: - enum {num_retries = 3}; + enum { num_retries = 3 }; x300_ctrl_iface(bool enable_errors = true) : errors(enable_errors) { @@ -41,39 +41,37 @@ public: void poke32(const wb_addr_type addr, const uint32_t data) { - for (size_t i = 1; i <= num_retries; i++) - { + for (size_t i = 1; i <= num_retries; i++) { boost::mutex::scoped_lock lock(reg_access); - try - { + try { return this->__poke32(addr, data); - } - catch(const uhd::io_error &ex) - { - std::string error_msg = str(boost::format( - "%s: x300 fw communication failure #%u\n%s") % __loc_info() % i % ex.what()); - if (errors) UHD_LOGGER_ERROR("X300") << error_msg ; - if (i == num_retries) throw uhd::io_error(error_msg); + } catch (const uhd::io_error& ex) { + std::string error_msg = + str(boost::format("%s: x300 fw communication failure #%u\n%s") + % __loc_info() % i % ex.what()); + if (errors) + UHD_LOGGER_ERROR("X300") << error_msg; + if (i == num_retries) + throw uhd::io_error(error_msg); } } } uint32_t peek32(const wb_addr_type addr) { - for (size_t i = 1; i <= num_retries; i++) - { + for (size_t i = 1; i <= num_retries; i++) { boost::mutex::scoped_lock lock(reg_access); - try - { + try { uint32_t data = this->__peek32(addr); return data; - } - catch(const uhd::io_error &ex) - { - std::string error_msg = str(boost::format( - "%s: x300 fw communication failure #%u\n%s") % __loc_info() % i % ex.what()); - if (errors) UHD_LOGGER_ERROR("X300") << error_msg ; - if (i == num_retries) throw uhd::io_error(error_msg); + } catch (const uhd::io_error& ex) { + std::string error_msg = + str(boost::format("%s: x300 fw communication failure #%u\n%s") + % __loc_info() % i % ex.what()); + if (errors) + UHD_LOGGER_ERROR("X300") << error_msg; + if (i == num_retries) + throw uhd::io_error(error_msg); } } return 0; @@ -83,9 +81,9 @@ protected: bool errors; virtual void __poke32(const wb_addr_type addr, const uint32_t data) = 0; - virtual uint32_t __peek32(const wb_addr_type addr) = 0; - virtual void __flush() = 0; - virtual std::string __loc_info() = 0; + virtual uint32_t __peek32(const wb_addr_type addr) = 0; + virtual void __flush() = 0; + virtual std::string __loc_info() = 0; boost::mutex reg_access; }; @@ -97,39 +95,40 @@ protected: class x300_ctrl_iface_enet : public x300_ctrl_iface { public: - x300_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors = true): - x300_ctrl_iface(enable_errors), udp(udp), seq(0) + x300_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors = true) + : x300_ctrl_iface(enable_errors), udp(udp), seq(0) { - try - { + try { this->peek32(0); + } catch (...) { } - catch(...){} } protected: virtual void __poke32(const wb_addr_type addr, const uint32_t data) { - //load request struct + // load request struct x300_fw_comms_t request = x300_fw_comms_t(); - request.flags = uhd::htonx<uint32_t>(X300_FW_COMMS_FLAGS_ACK | X300_FW_COMMS_FLAGS_POKE32); + request.flags = + uhd::htonx<uint32_t>(X300_FW_COMMS_FLAGS_ACK | X300_FW_COMMS_FLAGS_POKE32); request.sequence = uhd::htonx<uint32_t>(seq++); - request.addr = uhd::htonx(addr); - request.data = uhd::htonx(data); + request.addr = uhd::htonx(addr); + request.data = uhd::htonx(data); - //send request + // send request __flush(); udp->send(boost::asio::buffer(&request, sizeof(request))); - //recv reply + // recv reply x300_fw_comms_t reply = x300_fw_comms_t(); const size_t nbytes = udp->recv(boost::asio::buffer(&reply, sizeof(reply)), 1.0); - if (nbytes == 0) throw uhd::io_error("x300 fw poke32 - reply timed out"); + if (nbytes == 0) + throw uhd::io_error("x300 fw poke32 - reply timed out"); - //sanity checks + // sanity checks const size_t flags = uhd::ntohx<uint32_t>(reply.flags); UHD_ASSERT_THROW(nbytes == sizeof(reply)); - UHD_ASSERT_THROW(not (flags & X300_FW_COMMS_FLAGS_ERROR)); + UHD_ASSERT_THROW(not(flags & X300_FW_COMMS_FLAGS_ERROR)); UHD_ASSERT_THROW(flags & X300_FW_COMMS_FLAGS_POKE32); UHD_ASSERT_THROW(flags & X300_FW_COMMS_FLAGS_ACK); UHD_ASSERT_THROW(reply.sequence == request.sequence); @@ -139,39 +138,42 @@ protected: virtual uint32_t __peek32(const wb_addr_type addr) { - //load request struct + // load request struct x300_fw_comms_t request = x300_fw_comms_t(); - request.flags = uhd::htonx<uint32_t>(X300_FW_COMMS_FLAGS_ACK | X300_FW_COMMS_FLAGS_PEEK32); + request.flags = + uhd::htonx<uint32_t>(X300_FW_COMMS_FLAGS_ACK | X300_FW_COMMS_FLAGS_PEEK32); request.sequence = uhd::htonx<uint32_t>(seq++); - request.addr = uhd::htonx(addr); - request.data = 0; + request.addr = uhd::htonx(addr); + request.data = 0; - //send request + // send request __flush(); udp->send(boost::asio::buffer(&request, sizeof(request))); - //recv reply + // recv reply x300_fw_comms_t reply = x300_fw_comms_t(); const size_t nbytes = udp->recv(boost::asio::buffer(&reply, sizeof(reply)), 1.0); - if (nbytes == 0) throw uhd::io_error("x300 fw peek32 - reply timed out"); + if (nbytes == 0) + throw uhd::io_error("x300 fw peek32 - reply timed out"); - //sanity checks + // sanity checks const size_t flags = uhd::ntohx<uint32_t>(reply.flags); UHD_ASSERT_THROW(nbytes == sizeof(reply)); - UHD_ASSERT_THROW(not (flags & X300_FW_COMMS_FLAGS_ERROR)); + UHD_ASSERT_THROW(not(flags & X300_FW_COMMS_FLAGS_ERROR)); UHD_ASSERT_THROW(flags & X300_FW_COMMS_FLAGS_PEEK32); UHD_ASSERT_THROW(flags & X300_FW_COMMS_FLAGS_ACK); UHD_ASSERT_THROW(reply.sequence == request.sequence); UHD_ASSERT_THROW(reply.addr == request.addr); - //return result! + // return result! return uhd::ntohx<uint32_t>(reply.data); } virtual void __flush(void) { char buff[X300_FW_COMMS_MTU] = {}; - while (udp->recv(boost::asio::buffer(buff), 0.0)){} //flush + while (udp->recv(boost::asio::buffer(buff), 0.0)) { + } // flush } virtual std::string __loc_info(void) @@ -191,61 +193,66 @@ private: class x300_ctrl_iface_pcie : public x300_ctrl_iface { public: - x300_ctrl_iface_pcie(niriok_proxy::sptr drv_proxy, bool enable_errors = true): - x300_ctrl_iface(enable_errors), _drv_proxy(drv_proxy) + x300_ctrl_iface_pcie(niriok_proxy::sptr drv_proxy, bool enable_errors = true) + : x300_ctrl_iface(enable_errors), _drv_proxy(drv_proxy) { nirio_status status = 0; - nirio_status_chain(_drv_proxy->set_attribute(RIO_ADDRESS_SPACE, BUS_INTERFACE), status); + nirio_status_chain( + _drv_proxy->set_attribute(RIO_ADDRESS_SPACE, BUS_INTERFACE), status); - //Verify that the Ettus FPGA loaded in the device. This may not be true if the - //user is switching to UHD after using LabVIEW FPGA. + // Verify that the Ettus FPGA loaded in the device. This may not be true if the + // user is switching to UHD after using LabVIEW FPGA. uint32_t pcie_fpga_signature = 0; _drv_proxy->peek(FPGA_PCIE_SIG_REG, pcie_fpga_signature); if (pcie_fpga_signature != FPGA_X3xx_SIG_VALUE) - throw uhd::io_error("cannot create x300_ctrl_iface_pcie. incorrect/no fpga image"); + throw uhd::io_error( + "cannot create x300_ctrl_iface_pcie. incorrect/no fpga image"); - //Also, poll on the ZPU_STATUS bit to ensure all the state machines in the FPGA are - //ready to accept register transaction requests. + // Also, poll on the ZPU_STATUS bit to ensure all the state machines in the FPGA + // are ready to accept register transaction requests. uint32_t reg_data = 0xffffffff; - boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::local_time(); + boost::posix_time::ptime start_time = + boost::posix_time::microsec_clock::local_time(); boost::posix_time::time_duration elapsed; do { - std::this_thread::sleep_for(std::chrono::microseconds(500)); //Avoid flooding the bus + std::this_thread::sleep_for( + std::chrono::microseconds(500)); // Avoid flooding the bus elapsed = boost::posix_time::microsec_clock::local_time() - start_time; - nirio_status_chain(_drv_proxy->peek(PCIE_ZPU_STATUS_REG(0), reg_data), status); - } while ( - nirio_status_not_fatal(status) && - (reg_data & PCIE_ZPU_STATUS_SUSPENDED) && - elapsed.total_milliseconds() < INIT_TIMEOUT_IN_MS); + nirio_status_chain( + _drv_proxy->peek(PCIE_ZPU_STATUS_REG(0), reg_data), status); + } while (nirio_status_not_fatal(status) && (reg_data & PCIE_ZPU_STATUS_SUSPENDED) + && elapsed.total_milliseconds() < INIT_TIMEOUT_IN_MS); nirio_status_to_exception(status, "Could not initialize x300_ctrl_iface_pcie."); - try - { + try { this->peek32(0); + } catch (...) { } - catch(...){} } protected: virtual void __poke32(const wb_addr_type addr, const uint32_t data) { nirio_status status = 0; - uint32_t reg_data = 0xffffffff; - boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::local_time(); + uint32_t reg_data = 0xffffffff; + boost::posix_time::ptime start_time = + boost::posix_time::microsec_clock::local_time(); boost::posix_time::time_duration elapsed; nirio_status_chain(_drv_proxy->poke(PCIE_ZPU_DATA_REG(addr), data), status); if (nirio_status_not_fatal(status)) { do { - std::this_thread::sleep_for(std::chrono::microseconds(50)); //Avoid flooding the bus + std::this_thread::sleep_for( + std::chrono::microseconds(50)); // Avoid flooding the bus elapsed = boost::posix_time::microsec_clock::local_time() - start_time; - nirio_status_chain(_drv_proxy->peek(PCIE_ZPU_STATUS_REG(addr), reg_data), status); + nirio_status_chain( + _drv_proxy->peek(PCIE_ZPU_STATUS_REG(addr), reg_data), status); } while ( - nirio_status_not_fatal(status) && - ((reg_data & (PCIE_ZPU_STATUS_BUSY | PCIE_ZPU_STATUS_SUSPENDED)) != 0) && - elapsed.total_milliseconds() < READ_TIMEOUT_IN_MS); + nirio_status_not_fatal(status) + && ((reg_data & (PCIE_ZPU_STATUS_BUSY | PCIE_ZPU_STATUS_SUSPENDED)) != 0) + && elapsed.total_milliseconds() < READ_TIMEOUT_IN_MS); } if (nirio_status_fatal(status)) @@ -257,20 +264,24 @@ protected: virtual uint32_t __peek32(const wb_addr_type addr) { nirio_status status = 0; - uint32_t reg_data = 0xffffffff; - boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::local_time(); + uint32_t reg_data = 0xffffffff; + boost::posix_time::ptime start_time = + boost::posix_time::microsec_clock::local_time(); boost::posix_time::time_duration elapsed; - nirio_status_chain(_drv_proxy->poke(PCIE_ZPU_READ_REG(addr), PCIE_ZPU_READ_START), status); + nirio_status_chain( + _drv_proxy->poke(PCIE_ZPU_READ_REG(addr), PCIE_ZPU_READ_START), status); if (nirio_status_not_fatal(status)) { do { - std::this_thread::sleep_for(std::chrono::microseconds(50)); //Avoid flooding the bus + std::this_thread::sleep_for( + std::chrono::microseconds(50)); // Avoid flooding the bus elapsed = boost::posix_time::microsec_clock::local_time() - start_time; - nirio_status_chain(_drv_proxy->peek(PCIE_ZPU_STATUS_REG(addr), reg_data), status); + nirio_status_chain( + _drv_proxy->peek(PCIE_ZPU_STATUS_REG(addr), reg_data), status); } while ( - nirio_status_not_fatal(status) && - ((reg_data & (PCIE_ZPU_STATUS_BUSY | PCIE_ZPU_STATUS_SUSPENDED)) != 0) && - elapsed.total_milliseconds() < READ_TIMEOUT_IN_MS); + nirio_status_not_fatal(status) + && ((reg_data & (PCIE_ZPU_STATUS_BUSY | PCIE_ZPU_STATUS_SUSPENDED)) != 0) + && elapsed.total_milliseconds() < READ_TIMEOUT_IN_MS); } nirio_status_chain(_drv_proxy->peek(PCIE_ZPU_DATA_REG(addr), reg_data), status); @@ -298,12 +309,14 @@ private: static const uint32_t INIT_TIMEOUT_IN_MS = 5000; }; -wb_iface::sptr x300_make_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors = true) +wb_iface::sptr x300_make_ctrl_iface_enet( + uhd::transport::udp_simple::sptr udp, bool enable_errors = true) { return wb_iface::sptr(new x300_ctrl_iface_enet(udp, enable_errors)); } -wb_iface::sptr x300_make_ctrl_iface_pcie(niriok_proxy::sptr drv_proxy, bool enable_errors = true) +wb_iface::sptr x300_make_ctrl_iface_pcie( + niriok_proxy::sptr drv_proxy, bool enable_errors = true) { return wb_iface::sptr(new x300_ctrl_iface_pcie(drv_proxy, enable_errors)); } diff --git a/host/lib/usrp/x300/x300_fw_uart.cpp b/host/lib/usrp/x300/x300_fw_uart.cpp index 912d977ed..0dde87da5 100644 --- a/host/lib/usrp/x300/x300_fw_uart.cpp +++ b/host/lib/usrp/x300/x300_fw_uart.cpp @@ -6,11 +6,11 @@ // #include "x300_impl.hpp" -#include <uhd/types/wb_iface.hpp> #include "x300_regs.hpp" -#include <uhd/utils/log.hpp> -#include <uhd/types/serial.hpp> #include <uhd/exception.hpp> +#include <uhd/types/serial.hpp> +#include <uhd/types/wb_iface.hpp> +#include <uhd/utils/log.hpp> #include <boost/format.hpp> #include <chrono> @@ -18,44 +18,42 @@ using namespace uhd; struct x300_uart_iface : uart_iface { - x300_uart_iface(wb_iface::sptr iface): - _iface(iface), - rxoffset(0), - txword32(0), - _last_device_rxoffset(0) + x300_uart_iface(wb_iface::sptr iface) + : _iface(iface), rxoffset(0), txword32(0), _last_device_rxoffset(0) { - txoffset = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_INDEX)); + txoffset = + _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_INDEX)); rxpool = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_ADDR)); txpool = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_ADDR)); - poolsize = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_WORDS32)); + poolsize = + _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_WORDS32)); _rxcache.resize(poolsize); - //this->write_uart("HELLO UART\n"); - //this->read_uart(0.1); + // this->write_uart("HELLO UART\n"); + // this->read_uart(0.1); } void putchar(const char ch) { - const int shift = ((txoffset%4) * 8); - if (shift == 0) txword32 = 0; + const int shift = ((txoffset % 4) * 8); + if (shift == 0) + txword32 = 0; txword32 |= uint32_t(ch) << shift; // Write out full 32 bit words or whatever we have if end of string - if (txoffset % 4 == 3 or ch == '\n') - { - _iface->poke32(SR_ADDR(txpool, txoffset/4), txword32); + if (txoffset % 4 == 3 or ch == '\n') { + _iface->poke32(SR_ADDR(txpool, txoffset / 4), txword32); } - txoffset = (txoffset + 1) % (poolsize*4); - if (ch == '\n') - { + txoffset = (txoffset + 1) % (poolsize * 4); + if (ch == '\n') { // Tell the X300 to write the string - _iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_INDEX), txoffset); + _iface->poke32( + SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_INDEX), txoffset); } } - void write_uart(const std::string &buff) + void write_uart(const std::string& buff) { boost::mutex::scoped_lock lock(_write_mutex); - for(const char ch: buff) - { + for (const char ch : buff) { this->putchar(ch); } } @@ -65,60 +63,57 @@ struct x300_uart_iface : uart_iface if (rxoffset == _last_device_rxoffset) return -1; - int ret = static_cast<int>(_rxcache[((rxoffset)/4) % poolsize] >> ((rxoffset%4)*8) & 0xFF); + int ret = static_cast<int>( + _rxcache[((rxoffset) / 4) % poolsize] >> ((rxoffset % 4) * 8) & 0xFF); rxoffset++; return ret; } void update_cache(void) { - uint32_t device_rxoffset = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)); + uint32_t device_rxoffset = + _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)); uint32_t delta = device_rxoffset - rxoffset; - while (delta) - { - if (delta >= poolsize*4) - { + while (delta) { + if (delta >= poolsize * 4) { // all the data is new - reload the entire cache - for (uint32_t i = 0; i < poolsize; i++) - { + for (uint32_t i = 0; i < poolsize; i++) { _rxcache[i] = _iface->peek32(SR_ADDR(rxpool, i)); } // set the head to the same character as the current device // offset (tail) one loop earlier - rxoffset = device_rxoffset - (poolsize*4); + rxoffset = device_rxoffset - (poolsize * 4); // set the tail to the current device offset _last_device_rxoffset = device_rxoffset; // the string at the head is a partial, so skip it - for (int c = getchar(); c != '\n' and c != -1; c = getchar()) {} + for (int c = getchar(); c != '\n' and c != -1; c = getchar()) { + } // clear the partial string in the buffer, if any _rxbuff.clear(); - } - else if (rxoffset == _last_device_rxoffset) - { + } else if (rxoffset == _last_device_rxoffset) { // new data was added - refresh the portion of the cache that was updated - for (uint32_t i = (_last_device_rxoffset/4) % poolsize; - i != ((device_rxoffset/4)+1) % poolsize; - i = (i+1) % poolsize) - { + for (uint32_t i = (_last_device_rxoffset / 4) % poolsize; + i != ((device_rxoffset / 4) + 1) % poolsize; + i = (i + 1) % poolsize) { _rxcache[i] = _iface->peek32(SR_ADDR(rxpool, i)); } // set the tail to the current device offset _last_device_rxoffset = device_rxoffset; - } - else - { - // there is new data, but we aren't done with what we have - check back later + } else { + // there is new data, but we aren't done with what we have - check back + // later break; } // check again to see if anything changed while we were updating the cache - device_rxoffset = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)); + device_rxoffset = + _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)); delta = device_rxoffset - rxoffset; } } @@ -126,26 +121,22 @@ struct x300_uart_iface : uart_iface std::string read_uart(double timeout) { boost::mutex::scoped_lock lock(_read_mutex); - const auto exit_time = - std::chrono::steady_clock::now() - + std::chrono::microseconds(int64_t(timeout*1e6)); + const auto exit_time = std::chrono::steady_clock::now() + + std::chrono::microseconds(int64_t(timeout * 1e6)); std::string buff; - while (true) - { + while (true) { // Update cache this->update_cache(); // Get available characters - for (int ch = this->getchar(); ch != -1; ch = this->getchar()) - { + for (int ch = this->getchar(); ch != -1; ch = this->getchar()) { // store character to buffer _rxbuff.append(1, ch); // newline found - return string - if (ch == '\n') - { + if (ch == '\n') { buff.swap(_rxbuff); return buff; } diff --git a/host/lib/usrp/x300/x300_image_loader.cpp b/host/lib/usrp/x300/x300_image_loader.cpp index 4e2c9e580..5cb1f1b85 100644 --- a/host/lib/usrp/x300/x300_image_loader.cpp +++ b/host/lib/usrp/x300/x300_image_loader.cpp @@ -5,28 +5,25 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include <fstream> -#include <vector> - -#include <boost/algorithm/string.hpp> -#include <boost/filesystem.hpp> -#include <boost/property_tree/ptree.hpp> -#include <boost/property_tree/xml_parser.hpp> - +#include "cdecode.h" +#include "x300_fw_common.h" +#include "x300_impl.hpp" #include <uhd/config.hpp> #include <uhd/device.hpp> -#include <uhd/image_loader.hpp> #include <uhd/exception.hpp> -#include <uhd/transport/udp_simple.hpp> +#include <uhd/image_loader.hpp> #include <uhd/transport/nirio/niusrprio_session.h> #include <uhd/transport/nirio/status.h> +#include <uhd/transport/udp_simple.hpp> #include <uhd/utils/byteswap.hpp> #include <uhd/utils/paths.hpp> #include <uhd/utils/static.hpp> - -#include "x300_impl.hpp" -#include "x300_fw_common.h" -#include "cdecode.h" +#include <boost/algorithm/string.hpp> +#include <boost/filesystem.hpp> +#include <boost/property_tree/ptree.hpp> +#include <boost/property_tree/xml_parser.hpp> +#include <fstream> +#include <vector> namespace fs = boost::filesystem; @@ -50,65 +47,81 @@ using namespace uhd::transport; /* * Bitstream header pattern */ -static const uint8_t X300_FPGA_BIT_HEADER[] = -{ - 0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, - 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61, 0x00 -}; +static const uint8_t X300_FPGA_BIT_HEADER[] = {0x00, + 0x09, + 0x0f, + 0xf0, + 0x0f, + 0xf0, + 0x0f, + 0xf0, + 0x0f, + 0xf0, + 0x00, + 0x00, + 0x01, + 0x61, + 0x00}; /* * Packet structure */ -typedef struct { +typedef struct +{ uint32_t flags; uint32_t sector; uint32_t index; uint32_t size; union { - uint8_t data8[X300_PACKET_SIZE_BYTES]; - uint16_t data16[X300_PACKET_SIZE_BYTES/2]; + uint8_t data8[X300_PACKET_SIZE_BYTES]; + uint16_t data16[X300_PACKET_SIZE_BYTES / 2]; }; } x300_fpga_update_data_t; /* * X-Series burn session */ -typedef struct { - bool found; - bool ethernet; - bool configure; // Reload FPGA after burning to flash (Ethernet only) - bool verify; // Device will verify the download along the way (Ethernet only) - bool download; // Host will read the FPGA image on the device to a file - bool lvbitx; - uhd::device_addr_t dev_addr; - std::string ip_addr; - std::string fpga_type; - std::string resource; - std::string filepath; - std::string outpath; - std::string rpc_port; - udp_simple::sptr write_xport; - udp_simple::sptr read_xport; - size_t size; - uint8_t data_in[udp_simple::mtu]; - std::vector<char> bitstream; // .bin image extracted from .lvbitx file +typedef struct +{ + bool found; + bool ethernet; + bool configure; // Reload FPGA after burning to flash (Ethernet only) + bool verify; // Device will verify the download along the way (Ethernet only) + bool download; // Host will read the FPGA image on the device to a file + bool lvbitx; + uhd::device_addr_t dev_addr; + std::string ip_addr; + std::string fpga_type; + std::string resource; + std::string filepath; + std::string outpath; + std::string rpc_port; + udp_simple::sptr write_xport; + udp_simple::sptr read_xport; + size_t size; + uint8_t data_in[udp_simple::mtu]; + std::vector<char> bitstream; // .bin image extracted from .lvbitx file } x300_session_t; /* * Extract the .bin image from the given LVBITX file. */ -static void extract_from_lvbitx(x300_session_t &session){ - boost::property_tree::ptree pt; - boost::property_tree::xml_parser::read_xml(session.filepath.c_str(), pt, - boost::property_tree::xml_parser::no_comments | - boost::property_tree::xml_parser::trim_whitespace); +static void extract_from_lvbitx(x300_session_t& session) +{ + boost::property_tree::ptree pt; + boost::property_tree::xml_parser::read_xml(session.filepath.c_str(), + pt, + boost::property_tree::xml_parser::no_comments + | boost::property_tree::xml_parser::trim_whitespace); const std::string encoded_bitstream(pt.get<std::string>("Bitfile.Bitstream")); std::vector<char> decoded_bitstream(encoded_bitstream.size()); base64_decodestate decode_state; base64_init_decodestate(&decode_state); const size_t decoded_size = base64_decode_block(encoded_bitstream.c_str(), - encoded_bitstream.size(), &decoded_bitstream.front(), &decode_state); + encoded_bitstream.size(), + &decoded_bitstream.front(), + &decode_state); decoded_bitstream.resize(decoded_size); session.bitstream.swap(decoded_bitstream); @@ -118,118 +131,122 @@ static void extract_from_lvbitx(x300_session_t &session){ /* * Validate X300 image and extract if LVBITX. */ -static void x300_validate_image(x300_session_t &session){ - if(not fs::exists(session.filepath)){ - throw uhd::runtime_error(str(boost::format("Could not find image at path \"%s\".") - % session.filepath)); +static void x300_validate_image(x300_session_t& session) +{ + if (not fs::exists(session.filepath)) { + throw uhd::runtime_error(str( + boost::format("Could not find image at path \"%s\".") % session.filepath)); } std::string extension = fs::extension(session.filepath); - session.lvbitx = (extension == ".lvbitx"); + session.lvbitx = (extension == ".lvbitx"); - if(session.lvbitx){ + if (session.lvbitx) { extract_from_lvbitx(session); - if(session.size > X300_FPGA_BIN_SIZE_BYTES){ - throw uhd::runtime_error(str(boost::format("The specified FPGA image is too large: %d vs. %d") - % session.size % X300_FPGA_BIN_SIZE_BYTES)); + if (session.size > X300_FPGA_BIN_SIZE_BYTES) { + throw uhd::runtime_error( + str(boost::format("The specified FPGA image is too large: %d vs. %d") + % session.size % X300_FPGA_BIN_SIZE_BYTES)); } /* * PCIe burning just takes a filepath, even for a .lvbitx file, * so just extract it to validate the size. */ - if(!session.ethernet) session.bitstream.clear(); - } - else if(extension == ".bin" or extension == ".bit"){ + if (!session.ethernet) + session.bitstream.clear(); + } else if (extension == ".bin" or extension == ".bit") { uint32_t max_size = (extension == ".bin") ? X300_FPGA_BIN_SIZE_BYTES - : X300_FPGA_BIT_SIZE_BYTES; + : X300_FPGA_BIT_SIZE_BYTES; session.size = fs::file_size(session.filepath); - if(session.size > max_size){ - throw uhd::runtime_error(str(boost::format("The specified FPGA image is too large: %d vs. %d") - % session.size % max_size)); + if (session.size > max_size) { + throw uhd::runtime_error( + str(boost::format("The specified FPGA image is too large: %d vs. %d") + % session.size % max_size)); return; } - } - else{ - throw uhd::runtime_error(str(boost::format("Invalid extension \"%s\". Extension must be .bin, .bit, or .lvbitx.") - % extension)); + } else { + throw uhd::runtime_error( + str(boost::format( + "Invalid extension \"%s\". Extension must be .bin, .bit, or .lvbitx.") + % extension)); } } -static void x300_setup_session(x300_session_t &session, - const device_addr_t &args, - const std::string &filepath, - const std::string &outpath){ +static void x300_setup_session(x300_session_t& session, + const device_addr_t& args, + const std::string& filepath, + const std::string& outpath) +{ device_addrs_t devs = x300_find(args); - if(devs.size() == 0){ + if (devs.size() == 0) { session.found = false; return; - } - else if(devs.size() > 1){ - std::string err_msg = "Could not resolve given args to a single X-Series device.\n" - "Applicable devices:\n"; - - for(const uhd::device_addr_t &dev: devs){ - std::string identifier = dev.has_key("addr") ? "addr" - : "resource"; - - err_msg += str(boost::format(" * %s (%s=%s)\n") - % dev.get("product", "X3XX") - % identifier - % dev.get(identifier)); + } else if (devs.size() > 1) { + std::string err_msg = + "Could not resolve given args to a single X-Series device.\n" + "Applicable devices:\n"; + + for (const uhd::device_addr_t& dev : devs) { + std::string identifier = dev.has_key("addr") ? "addr" : "resource"; + + err_msg += str(boost::format(" * %s (%s=%s)\n") % dev.get("product", "X3XX") + % identifier % dev.get(identifier)); } - err_msg += "\nSpecify one of these devices with the given args to load an image onto it."; + err_msg += "\nSpecify one of these devices with the given args to load an image " + "onto it."; throw uhd::runtime_error(err_msg); } - session.found = true; + session.found = true; session.dev_addr = devs[0]; session.ethernet = session.dev_addr.has_key("addr"); - if(session.ethernet){ - session.ip_addr = session.dev_addr["addr"]; - session.configure = args.has_key("configure"); - session.write_xport = udp_simple::make_connected(session.ip_addr, - BOOST_STRINGIZE(X300_FPGA_PROG_UDP_PORT)); - session.read_xport = udp_simple::make_connected(session.ip_addr, - BOOST_STRINGIZE(X300_FPGA_READ_UDP_PORT)); - session.verify = args.has_key("verify"); + if (session.ethernet) { + session.ip_addr = session.dev_addr["addr"]; + session.configure = args.has_key("configure"); + session.write_xport = udp_simple::make_connected( + session.ip_addr, BOOST_STRINGIZE(X300_FPGA_PROG_UDP_PORT)); + session.read_xport = udp_simple::make_connected( + session.ip_addr, BOOST_STRINGIZE(X300_FPGA_READ_UDP_PORT)); + session.verify = args.has_key("verify"); session.download = args.has_key("download"); - } - else{ + } else { session.resource = session.dev_addr["resource"]; session.rpc_port = args.get("rpc-port", "5444"); } /* - * The user can specify an FPGA type (1G, HGS, XGS), rather than a filename. If the user - * does not specify one, this will default to the type currently on the device. If this - * cannot be determined, then the user is forced to specify a filename. + * The user can specify an FPGA type (1G, HGS, XGS), rather than a filename. If the + * user does not specify one, this will default to the type currently on the device. + * If this cannot be determined, then the user is forced to specify a filename. */ session.fpga_type = args.get("fpga", session.dev_addr.get("fpga", "")); - if(filepath == ""){ - if(!session.dev_addr.has_key("product") or session.fpga_type == ""){ - throw uhd::runtime_error("Found a device but could not auto-generate an image filename."); - } - else session.filepath = find_image_path(str(boost::format("usrp_%s_fpga_%s.bit") - % (to_lower_copy(session.dev_addr["product"])) - % session.fpga_type)); - } - else session.filepath = filepath; + if (filepath == "") { + if (!session.dev_addr.has_key("product") or session.fpga_type == "") { + throw uhd::runtime_error( + "Found a device but could not auto-generate an image filename."); + } else + session.filepath = find_image_path( + str(boost::format("usrp_%s_fpga_%s.bit") + % (to_lower_copy(session.dev_addr["product"])) % session.fpga_type)); + } else + session.filepath = filepath; /* * The user can specify an output image path, or UHD will use the * system temporary path by default */ - if(outpath == ""){ - if(!session.dev_addr.has_key("product") or session.fpga_type == ""){ - throw uhd::runtime_error("Found a device but could not auto-generate an image filename."); + if (outpath == "") { + if (!session.dev_addr.has_key("product") or session.fpga_type == "") { + throw uhd::runtime_error( + "Found a device but could not auto-generate an image filename."); } - std::string filename = str(boost::format("usrp_%s_fpga_%s") - % (to_lower_copy(session.dev_addr["product"])) - % session.fpga_type); + std::string filename = + str(boost::format("usrp_%s_fpga_%s") + % (to_lower_copy(session.dev_addr["product"])) % session.fpga_type); session.outpath = get_tmp_path() + "/" + filename; } else { @@ -244,172 +261,180 @@ static void x300_setup_session(x300_session_t &session, * Ethernet communication functions */ static UHD_INLINE size_t x300_send_and_recv(udp_simple::sptr xport, - uint32_t pkt_code, - x300_fpga_update_data_t *pkt_out, - uint8_t* data){ + uint32_t pkt_code, + x300_fpga_update_data_t* pkt_out, + uint8_t* data) +{ pkt_out->flags = uhd::htonx<uint32_t>(pkt_code); xport->send(boost::asio::buffer(pkt_out, sizeof(*pkt_out))); return xport->recv(boost::asio::buffer(data, udp_simple::mtu), UDP_TIMEOUT); } -static UHD_INLINE bool x300_recv_ok(const x300_fpga_update_data_t *pkt_in, - size_t len){ - return (len > 0 and - ((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR) != X300_FPGA_PROG_FLAGS_ERROR)); +static UHD_INLINE bool x300_recv_ok(const x300_fpga_update_data_t* pkt_in, size_t len) +{ + return (len > 0 + and ((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR) + != X300_FPGA_PROG_FLAGS_ERROR)); } // Image data needs to be bitswapped -static UHD_INLINE void x300_bitswap(uint8_t *num){ +static UHD_INLINE void x300_bitswap(uint8_t* num) +{ *num = ((*num & 0xF0) >> 4) | ((*num & 0x0F) << 4); *num = ((*num & 0xCC) >> 2) | ((*num & 0x33) << 2); *num = ((*num & 0xAA) >> 1) | ((*num & 0x55) << 1); } -static void x300_ethernet_load(x300_session_t &session){ - +static void x300_ethernet_load(x300_session_t& session) +{ // UDP receive buffer x300_fpga_update_data_t pkt_out; - const x300_fpga_update_data_t *pkt_in = reinterpret_cast<const x300_fpga_update_data_t*>(session.data_in); + const x300_fpga_update_data_t* pkt_in = + reinterpret_cast<const x300_fpga_update_data_t*>(session.data_in); // Initialize write session uint32_t flags = X300_FPGA_PROG_FLAGS_ACK | X300_FPGA_PROG_FLAGS_INIT; - size_t len = x300_send_and_recv(session.write_xport, flags, &pkt_out, session.data_in); - if(x300_recv_ok(pkt_in, len)){ + size_t len = + x300_send_and_recv(session.write_xport, flags, &pkt_out, session.data_in); + if (x300_recv_ok(pkt_in, len)) { std::cout << "-- Initializing FPGA loading..." << std::flush; - } - else if(len == 0){ + } else if (len == 0) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else{ + } else { std::cout << "failed." << std::endl; throw uhd::runtime_error("Device reported an error during initialization."); } std::cout << "successful." << std::endl; - if(session.verify){ - std::cout << "-- NOTE: Device is verifying the image it is receiving, increasing the loading time." << std::endl; + if (session.verify) { + std::cout << "-- NOTE: Device is verifying the image it is receiving, increasing " + "the loading time." + << std::endl; } size_t current_pos = 0; - size_t sectors = (session.size / X300_FLASH_SECTOR_SIZE); + size_t sectors = (session.size / X300_FLASH_SECTOR_SIZE); std::ifstream image(session.filepath.c_str(), std::ios::binary); // Each sector - for(size_t i = 0; i < session.size; i += X300_FLASH_SECTOR_SIZE){ - + for (size_t i = 0; i < session.size; i += X300_FLASH_SECTOR_SIZE) { // Print progress percentage at beginning of each sector std::cout << boost::format("\r-- Loading %s FPGA image: %d%% (%d/%d sectors)") - % session.fpga_type - % (int(double(i) / double(session.size) * 100.0)) - % (i / X300_FLASH_SECTOR_SIZE) - % sectors - << std::flush; + % session.fpga_type + % (int(double(i) / double(session.size) * 100.0)) + % (i / X300_FLASH_SECTOR_SIZE) % sectors + << std::flush; // Each packet - for(size_t j = i; (j < session.size and j < (i+X300_FLASH_SECTOR_SIZE)); j += X300_PACKET_SIZE_BYTES){ + for (size_t j = i; (j < session.size and j < (i + X300_FLASH_SECTOR_SIZE)); + j += X300_PACKET_SIZE_BYTES) { flags = X300_FPGA_PROG_FLAGS_ACK; - if(j == i) flags |= X300_FPGA_PROG_FLAGS_ERASE; // Erase at beginning of sector - if(session.verify) flags |= X300_FPGA_PROG_FLAGS_VERIFY; + if (j == i) + flags |= X300_FPGA_PROG_FLAGS_ERASE; // Erase at beginning of sector + if (session.verify) + flags |= X300_FPGA_PROG_FLAGS_VERIFY; // Set burn location - pkt_out.sector = htonx<uint32_t>(X300_FPGA_SECTOR_START + (i/X300_FLASH_SECTOR_SIZE)); - pkt_out.index = htonx<uint32_t>((j % X300_FLASH_SECTOR_SIZE) / 2); - pkt_out.size = htonx<uint32_t>(X300_PACKET_SIZE_BYTES / 2); + pkt_out.sector = + htonx<uint32_t>(X300_FPGA_SECTOR_START + (i / X300_FLASH_SECTOR_SIZE)); + pkt_out.index = htonx<uint32_t>((j % X300_FLASH_SECTOR_SIZE) / 2); + pkt_out.size = htonx<uint32_t>(X300_PACKET_SIZE_BYTES / 2); // Read next piece of image memset(pkt_out.data8, 0, X300_PACKET_SIZE_BYTES); - if(session.lvbitx){ - memcpy(pkt_out.data8, &session.bitstream[current_pos], X300_PACKET_SIZE_BYTES); + if (session.lvbitx) { + memcpy(pkt_out.data8, + &session.bitstream[current_pos], + X300_PACKET_SIZE_BYTES); current_pos += X300_PACKET_SIZE_BYTES; - } - else{ + } else { image.read((char*)pkt_out.data8, X300_PACKET_SIZE_BYTES); } // Data must be bitswapped and byteswapped - for(size_t k = 0; k < X300_PACKET_SIZE_BYTES; k++){ + for (size_t k = 0; k < X300_PACKET_SIZE_BYTES; k++) { x300_bitswap(&pkt_out.data8[k]); } - for(size_t k = 0; k < (X300_PACKET_SIZE_BYTES/2); k++){ + for (size_t k = 0; k < (X300_PACKET_SIZE_BYTES / 2); k++) { pkt_out.data16[k] = htonx<uint16_t>(pkt_out.data16[k]); } - len = x300_send_and_recv(session.write_xport, flags, &pkt_out, session.data_in); - if(len == 0){ - if(!session.lvbitx) image.close(); + len = + x300_send_and_recv(session.write_xport, flags, &pkt_out, session.data_in); + if (len == 0) { + if (!session.lvbitx) + image.close(); throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR)){ - if(!session.lvbitx) image.close(); + } else if ((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR)) { + if (!session.lvbitx) + image.close(); throw uhd::runtime_error("Device reported an error."); } } } - if(!session.lvbitx){ + if (!session.lvbitx) { image.close(); } std::cout << boost::format("\r-- Loading %s FPGA image: 100%% (%d/%d sectors)") - % session.fpga_type - % sectors - % sectors - << std::endl; + % session.fpga_type % sectors % sectors + << std::endl; // Cleanup - if(!session.lvbitx) image.close(); - flags = (X300_FPGA_PROG_FLAGS_CLEANUP | X300_FPGA_PROG_FLAGS_ACK); + if (!session.lvbitx) + image.close(); + flags = (X300_FPGA_PROG_FLAGS_CLEANUP | X300_FPGA_PROG_FLAGS_ACK); pkt_out.sector = pkt_out.index = pkt_out.size = 0; memset(pkt_out.data8, 0, X300_PACKET_SIZE_BYTES); std::cout << "-- Finalizing image load..." << std::flush; len = x300_send_and_recv(session.write_xport, flags, &pkt_out, session.data_in); - if(len == 0){ + if (len == 0) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR)){ + } else if ((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR)) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Device reported an error during cleanup."); - } - else std::cout << "successful." << std::endl; + } else + std::cout << "successful." << std::endl; // Save new FPGA image (if option set) - if(session.configure){ + if (session.configure) { flags = (X300_FPGA_PROG_CONFIGURE | X300_FPGA_PROG_FLAGS_ACK); x300_send_and_recv(session.write_xport, flags, &pkt_out, session.data_in); std::cout << "-- Saving image onto device..." << std::flush; - if(len == 0){ + if (len == 0) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR)){ + } else if ((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR)) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Device reported an error while saving the image."); - } - else std::cout << "successful." << std::endl; + } else + std::cout << "successful." << std::endl; } - std::cout << str(boost::format("Power-cycle the USRP %s to use the new image.") % session.dev_addr.get("product", "")) << std::endl; + std::cout << str(boost::format("Power-cycle the USRP %s to use the new image.") + % session.dev_addr.get("product", "")) + << std::endl; } -static void x300_ethernet_read(x300_session_t &session){ - +static void x300_ethernet_read(x300_session_t& session) +{ // UDP receive buffer x300_fpga_update_data_t pkt_out; memset(pkt_out.data8, 0, X300_PACKET_SIZE_BYTES); - x300_fpga_update_data_t *pkt_in = reinterpret_cast<x300_fpga_update_data_t*>(session.data_in); + x300_fpga_update_data_t* pkt_in = + reinterpret_cast<x300_fpga_update_data_t*>(session.data_in); // Initialize read session uint32_t flags = X300_FPGA_READ_FLAGS_ACK | X300_FPGA_READ_FLAGS_INIT; size_t len = x300_send_and_recv(session.read_xport, flags, &pkt_out, session.data_in); - if(x300_recv_ok(pkt_in, len)){ + if (x300_recv_ok(pkt_in, len)) { std::cout << "-- Initializing FPGA reading..." << std::flush; - } - else if(len == 0){ + } else if (len == 0) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else{ + } else { std::cout << "failed." << std::endl; throw uhd::runtime_error("Device reported an error during initialization."); } @@ -426,83 +451,79 @@ static void x300_ethernet_read(x300_session_t &session){ pkt_out.size = htonx<uint32_t>(X300_PACKET_SIZE_BYTES / 2); len = x300_send_and_recv(session.read_xport, flags, &pkt_out, session.data_in); - if(len == 0){ + if (len == 0) { throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if((ntohl(pkt_in->flags) & X300_FPGA_READ_FLAGS_ERROR)){ + } else if ((ntohl(pkt_in->flags) & X300_FPGA_READ_FLAGS_ERROR)) { throw uhd::runtime_error("Device reported an error."); } // Data must be bitswapped and byteswapped - for(size_t k = 0; k < X300_PACKET_SIZE_BYTES; k++){ + for (size_t k = 0; k < X300_PACKET_SIZE_BYTES; k++) { x300_bitswap(&pkt_in->data8[k]); } - for(size_t k = 0; k < (X300_PACKET_SIZE_BYTES/2); k++){ + for (size_t k = 0; k < (X300_PACKET_SIZE_BYTES / 2); k++) { pkt_in->data16[k] = htonx<uint16_t>(pkt_in->data16[k]); } // Assume the largest size first size_t image_size = X300_FPGA_BIT_SIZE_BYTES; - size_t sectors = (image_size / X300_FLASH_SECTOR_SIZE); + size_t sectors = (image_size / X300_FLASH_SECTOR_SIZE); std::string extension(".bit"); // Check for the beginning header sequence to determine // the total amount of data (.bit vs .bin) on the flash // The .bit file format includes header information not part of a .bin - for (size_t i = 0; i < sizeof(X300_FPGA_BIT_HEADER); i++) - { - if (pkt_in->data8[i] != X300_FPGA_BIT_HEADER[i]) - { - std::cout << "-- No *.bit header detected, FPGA image is a raw stream (*.bin)!" << std::endl; + for (size_t i = 0; i < sizeof(X300_FPGA_BIT_HEADER); i++) { + if (pkt_in->data8[i] != X300_FPGA_BIT_HEADER[i]) { + std::cout + << "-- No *.bit header detected, FPGA image is a raw stream (*.bin)!" + << std::endl; image_size = X300_FPGA_BIN_SIZE_BYTES; - sectors = (image_size / X300_FLASH_SECTOR_SIZE); - extension = std::string(".bin"); + sectors = (image_size / X300_FLASH_SECTOR_SIZE); + extension = std::string(".bin"); break; } } session.outpath += extension; std::ofstream image(session.outpath.c_str(), std::ios::binary); - std::cout << boost::format("-- Output FPGA file: %s\n") - % session.outpath; + std::cout << boost::format("-- Output FPGA file: %s\n") % session.outpath; // Write the first packet image.write((char*)pkt_in->data8, X300_PACKET_SIZE_BYTES); // Each sector size_t pkt_count = X300_PACKET_SIZE_BYTES; - for(size_t i = 0; i < image_size; i += X300_FLASH_SECTOR_SIZE){ - + for (size_t i = 0; i < image_size; i += X300_FLASH_SECTOR_SIZE) { // Once we determine the image size, print the progress percentage std::cout << boost::format("\r-- Reading %s FPGA image: %d%% (%d/%d sectors)") - % session.fpga_type - % (int(double(i) / double(image_size) * 100.0)) - % (i / X300_FLASH_SECTOR_SIZE) - % sectors + % session.fpga_type + % (int(double(i) / double(image_size) * 100.0)) + % (i / X300_FLASH_SECTOR_SIZE) % sectors << std::flush; // Each packet - while (pkt_count < image_size and pkt_count < (i + X300_FLASH_SECTOR_SIZE)) - { + while (pkt_count < image_size and pkt_count < (i + X300_FLASH_SECTOR_SIZE)) { // Set burn location - pkt_out.sector = htonx<uint32_t>(X300_FPGA_SECTOR_START + (i/X300_FLASH_SECTOR_SIZE)); - pkt_out.index = htonx<uint32_t>((pkt_count % X300_FLASH_SECTOR_SIZE) / 2); + pkt_out.sector = + htonx<uint32_t>(X300_FPGA_SECTOR_START + (i / X300_FLASH_SECTOR_SIZE)); + pkt_out.index = htonx<uint32_t>((pkt_count % X300_FLASH_SECTOR_SIZE) / 2); - len = x300_send_and_recv(session.read_xport, flags, &pkt_out, session.data_in); - if(len == 0){ + len = + x300_send_and_recv(session.read_xport, flags, &pkt_out, session.data_in); + if (len == 0) { image.close(); throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if((ntohl(pkt_in->flags) & X300_FPGA_READ_FLAGS_ERROR)){ + } else if ((ntohl(pkt_in->flags) & X300_FPGA_READ_FLAGS_ERROR)) { image.close(); throw uhd::runtime_error("Device reported an error."); } // Data must be bitswapped and byteswapped - for(size_t k = 0; k < X300_PACKET_SIZE_BYTES; k++){ + for (size_t k = 0; k < X300_PACKET_SIZE_BYTES; k++) { x300_bitswap(&pkt_in->data8[k]); } - for(size_t k = 0; k < (X300_PACKET_SIZE_BYTES/2); k++){ + for (size_t k = 0; k < (X300_PACKET_SIZE_BYTES / 2); k++) { pkt_in->data16[k] = htonx<uint16_t>(pkt_in->data16[k]); } @@ -510,8 +531,7 @@ static void x300_ethernet_read(x300_session_t &session){ // If this is the last packet, get rid of the extra zero padding // due to packet size size_t nbytes = X300_PACKET_SIZE_BYTES; - if (pkt_count > (image_size - X300_PACKET_SIZE_BYTES)) - { + if (pkt_count > (image_size - X300_PACKET_SIZE_BYTES)) { nbytes = (image_size - pkt_count); } @@ -526,85 +546,94 @@ static void x300_ethernet_read(x300_session_t &session){ } std::cout << boost::format("\r-- Reading %s FPGA image: 100%% (%d/%d sectors)") - % session.fpga_type - % sectors - % sectors + % session.fpga_type % sectors % sectors << std::endl; // Cleanup image.close(); - flags = (X300_FPGA_READ_FLAGS_CLEANUP | X300_FPGA_READ_FLAGS_ACK); + flags = (X300_FPGA_READ_FLAGS_CLEANUP | X300_FPGA_READ_FLAGS_ACK); pkt_out.sector = pkt_out.index = pkt_out.size = 0; memset(pkt_out.data8, 0, X300_PACKET_SIZE_BYTES); std::cout << "-- Finalizing image read for verification..." << std::flush; len = x300_send_and_recv(session.read_xport, flags, &pkt_out, session.data_in); - if(len == 0){ + if (len == 0) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if((ntohl(pkt_in->flags) & X300_FPGA_READ_FLAGS_ERROR)){ + } else if ((ntohl(pkt_in->flags) & X300_FPGA_READ_FLAGS_ERROR)) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Device reported an error during cleanup."); - } - else std::cout << "successful image read." << std::endl; + } else + std::cout << "successful image read." << std::endl; } -static void x300_pcie_load(x300_session_t &session){ - - std::cout << boost::format("\r-- Loading %s FPGA image (this will take 5-10 minutes)...") - % session.fpga_type - << std::flush; +static void x300_pcie_load(x300_session_t& session) +{ + std::cout << boost::format( + "\r-- Loading %s FPGA image (this will take 5-10 minutes)...") + % session.fpga_type + << std::flush; nirio_status status = NiRio_Status_Success; niusrprio::niusrprio_session fpga_session(session.resource, session.rpc_port); - nirio_status_chain(fpga_session.download_bitstream_to_flash(session.filepath), status); + nirio_status_chain( + fpga_session.download_bitstream_to_flash(session.filepath), status); - if(nirio_status_fatal(status)){ + if (nirio_status_fatal(status)) { std::cout << "failed." << std::endl; - niusrprio::nirio_status_to_exception(status, "NI-RIO reported the following error:"); - } - else std::cout << "successful." << std::endl; - std::cout << str(boost::format("Power-cycle the USRP %s to use the new image.") % session.dev_addr.get("product", "")) << std::endl; + niusrprio::nirio_status_to_exception( + status, "NI-RIO reported the following error:"); + } else + std::cout << "successful." << std::endl; + std::cout << str(boost::format("Power-cycle the USRP %s to use the new image.") + % session.dev_addr.get("product", "")) + << std::endl; } -static bool x300_image_loader(const image_loader::image_loader_args_t &image_loader_args){ +static bool x300_image_loader(const image_loader::image_loader_args_t& image_loader_args) +{ // See if any X3x0 with the given args is found device_addrs_t devs = x300_find(image_loader_args.args); - if (devs.size() == 0) return false; + if (devs.size() == 0) + return false; x300_session_t session; x300_setup_session(session, - image_loader_args.args, - image_loader_args.fpga_path, - image_loader_args.out_path); + image_loader_args.args, + image_loader_args.fpga_path, + image_loader_args.out_path); - if(!session.found) return false; + if (!session.found) + return false; std::cout << boost::format("Unit: USRP %s (%s, %s)\nFPGA Image: %s\n") - % session.dev_addr["product"] - % session.dev_addr["serial"] - % session.dev_addr[session.ethernet ? "addr" : "resource"] - % session.filepath; + % session.dev_addr["product"] % session.dev_addr["serial"] + % session.dev_addr[session.ethernet ? "addr" : "resource"] + % session.filepath; // Download the FPGA image to a file - if(image_loader_args.download) { + if (image_loader_args.download) { std::cout << "Attempting to download the FPGA image ..." << std::endl; x300_ethernet_read(session); } - if (not image_loader_args.load_fpga) return true; + if (not image_loader_args.load_fpga) + return true; - if (session.ethernet) x300_ethernet_load(session); - else x300_pcie_load(session); + if (session.ethernet) + x300_ethernet_load(session); + else + x300_pcie_load(session); return true; } -UHD_STATIC_BLOCK(register_x300_image_loader){ - std::string recovery_instructions = "Aborting. Your USRP X-Series device will likely be unusable. Visit\n" - "http://files.ettus.com/manual/page_usrp_x3x0.html#x3x0_load_fpga_imgs_jtag\n" - "for details on restoring your device."; +UHD_STATIC_BLOCK(register_x300_image_loader) +{ + std::string recovery_instructions = + "Aborting. Your USRP X-Series device will likely be unusable. Visit\n" + "http://files.ettus.com/manual/page_usrp_x3x0.html#x3x0_load_fpga_imgs_jtag\n" + "for details on restoring your device."; image_loader::register_image_loader("x300", x300_image_loader, recovery_instructions); } diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 7d2ce6b28..ed6678761 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -7,29 +7,28 @@ #include "x300_impl.hpp" #include "x300_lvbitx.hpp" -#include "x310_lvbitx.hpp" #include "x300_mb_eeprom_iface.hpp" -#include <uhdlib/usrp/common/apply_corrections.hpp> -#include <uhd/utils/static.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/utils/paths.hpp> -#include <uhd/utils/safe_call.hpp> -#include <uhd/usrp/subdev_spec.hpp> +#include "x310_lvbitx.hpp" #include <uhd/transport/if_addrs.hpp> -#include <uhd/transport/udp_zero_copy.hpp> +#include <uhd/transport/nirio/niusrprio_session.h> +#include <uhd/transport/nirio_zero_copy.hpp> #include <uhd/transport/udp_constants.hpp> +#include <uhd/transport/udp_zero_copy.hpp> #include <uhd/transport/zero_copy_recv_offload.hpp> -#include <uhd/transport/nirio_zero_copy.hpp> -#include <uhd/transport/nirio/niusrprio_session.h> -#include <uhd/utils/platform.hpp> #include <uhd/types/sid.hpp> +#include <uhd/usrp/subdev_spec.hpp> +#include <uhd/utils/log.hpp> #include <uhd/utils/math.hpp> - +#include <uhd/utils/paths.hpp> +#include <uhd/utils/platform.hpp> +#include <uhd/utils/safe_call.hpp> +#include <uhd/utils/static.hpp> +#include <uhdlib/usrp/common/apply_corrections.hpp> #include <boost/algorithm/string.hpp> #include <boost/asio.hpp> #include <boost/make_shared.hpp> -#include <fstream> #include <chrono> +#include <fstream> #include <thread> using namespace uhd; @@ -45,27 +44,28 @@ namespace asio = boost::asio; /****************************************************************************** * Helpers *****************************************************************************/ -static std::string get_fpga_option(wb_iface::sptr zpu_ctrl) { - //Possible options: - //1G = {0:1G, 1:1G} w/ DRAM, HG = {0:1G, 1:10G} w/ DRAM, XG = {0:10G, 1:10G} w/ DRAM - //HA = {0:1G, 1:Aurora} w/ DRAM, XA = {0:10G, 1:Aurora} w/ DRAM +static std::string get_fpga_option(wb_iface::sptr zpu_ctrl) +{ + // Possible options: + // 1G = {0:1G, 1:1G} w/ DRAM, HG = {0:1G, 1:10G} w/ DRAM, XG = {0:10G, 1:10G} w/ + // DRAM HA = {0:1G, 1:Aurora} w/ DRAM, XA = {0:10G, 1:Aurora} w/ DRAM std::string option; uint32_t sfp0_type = zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_SFP0_TYPE)); uint32_t sfp1_type = zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_SFP1_TYPE)); - if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_1G_ETH) { + if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_1G_ETH) { option = "1G"; - } else if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_10G_ETH) { + } else if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_10G_ETH) { option = "HG"; - } else if (sfp0_type == RB_SFP_10G_ETH and sfp1_type == RB_SFP_10G_ETH) { + } else if (sfp0_type == RB_SFP_10G_ETH and sfp1_type == RB_SFP_10G_ETH) { option = "XG"; - } else if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_AURORA) { + } else if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_AURORA) { option = "HA"; - } else if (sfp0_type == RB_SFP_10G_ETH and sfp1_type == RB_SFP_AURORA) { + } else if (sfp0_type == RB_SFP_10G_ETH and sfp1_type == RB_SFP_AURORA) { option = "XA"; } else { - option = "HG"; //Default + option = "HG"; // Default } return option; } @@ -73,153 +73,150 @@ static std::string get_fpga_option(wb_iface::sptr zpu_ctrl) { namespace { - /*! Return the correct motherboard type for a given product ID - * - * Note: In previous versions, we had two different mappings for PCIe and - * Ethernet in case the PIDs would conflict, but they never did and it was - * thus consolidated into one. - */ - x300_impl::x300_mboard_t map_pid_to_mb_type(const uint32_t pid) - { - switch (pid) { - case X300_USRP_PCIE_SSID_ADC_33: - case X300_USRP_PCIE_SSID_ADC_18: - return x300_impl::USRP_X300_MB; - case X310_USRP_PCIE_SSID_ADC_33: - case X310_2940R_40MHz_PCIE_SSID_ADC_33: - case X310_2940R_120MHz_PCIE_SSID_ADC_33: - case X310_2942R_40MHz_PCIE_SSID_ADC_33: - case X310_2942R_120MHz_PCIE_SSID_ADC_33: - case X310_2943R_40MHz_PCIE_SSID_ADC_33: - case X310_2943R_120MHz_PCIE_SSID_ADC_33: - case X310_2944R_40MHz_PCIE_SSID_ADC_33: - case X310_2950R_40MHz_PCIE_SSID_ADC_33: - case X310_2950R_120MHz_PCIE_SSID_ADC_33: - case X310_2952R_40MHz_PCIE_SSID_ADC_33: - case X310_2952R_120MHz_PCIE_SSID_ADC_33: - case X310_2953R_40MHz_PCIE_SSID_ADC_33: - case X310_2953R_120MHz_PCIE_SSID_ADC_33: - case X310_2954R_40MHz_PCIE_SSID_ADC_33: - case X310_USRP_PCIE_SSID_ADC_18: - case X310_2940R_40MHz_PCIE_SSID_ADC_18: - case X310_2940R_120MHz_PCIE_SSID_ADC_18: - case X310_2942R_40MHz_PCIE_SSID_ADC_18: - case X310_2942R_120MHz_PCIE_SSID_ADC_18: - case X310_2943R_40MHz_PCIE_SSID_ADC_18: - case X310_2943R_120MHz_PCIE_SSID_ADC_18: - case X310_2944R_40MHz_PCIE_SSID_ADC_18: - case X310_2945R_PCIE_SSID_ADC_18: - case X310_2950R_40MHz_PCIE_SSID_ADC_18: - case X310_2950R_120MHz_PCIE_SSID_ADC_18: - case X310_2952R_40MHz_PCIE_SSID_ADC_18: - case X310_2952R_120MHz_PCIE_SSID_ADC_18: - case X310_2953R_40MHz_PCIE_SSID_ADC_18: - case X310_2953R_120MHz_PCIE_SSID_ADC_18: - case X310_2954R_40MHz_PCIE_SSID_ADC_18: - case X310_2955R_PCIE_SSID_ADC_18: - return x300_impl::USRP_X310_MB; - case X310_2974_PCIE_SSID_ADC_18: - return x300_impl::USRP_X310_MB_NI_2974; - default: - return x300_impl::UNKNOWN; - } - UHD_THROW_INVALID_CODE_PATH(); +/*! Return the correct motherboard type for a given product ID + * + * Note: In previous versions, we had two different mappings for PCIe and + * Ethernet in case the PIDs would conflict, but they never did and it was + * thus consolidated into one. + */ +x300_impl::x300_mboard_t map_pid_to_mb_type(const uint32_t pid) +{ + switch (pid) { + case X300_USRP_PCIE_SSID_ADC_33: + case X300_USRP_PCIE_SSID_ADC_18: + return x300_impl::USRP_X300_MB; + case X310_USRP_PCIE_SSID_ADC_33: + case X310_2940R_40MHz_PCIE_SSID_ADC_33: + case X310_2940R_120MHz_PCIE_SSID_ADC_33: + case X310_2942R_40MHz_PCIE_SSID_ADC_33: + case X310_2942R_120MHz_PCIE_SSID_ADC_33: + case X310_2943R_40MHz_PCIE_SSID_ADC_33: + case X310_2943R_120MHz_PCIE_SSID_ADC_33: + case X310_2944R_40MHz_PCIE_SSID_ADC_33: + case X310_2950R_40MHz_PCIE_SSID_ADC_33: + case X310_2950R_120MHz_PCIE_SSID_ADC_33: + case X310_2952R_40MHz_PCIE_SSID_ADC_33: + case X310_2952R_120MHz_PCIE_SSID_ADC_33: + case X310_2953R_40MHz_PCIE_SSID_ADC_33: + case X310_2953R_120MHz_PCIE_SSID_ADC_33: + case X310_2954R_40MHz_PCIE_SSID_ADC_33: + case X310_USRP_PCIE_SSID_ADC_18: + case X310_2940R_40MHz_PCIE_SSID_ADC_18: + case X310_2940R_120MHz_PCIE_SSID_ADC_18: + case X310_2942R_40MHz_PCIE_SSID_ADC_18: + case X310_2942R_120MHz_PCIE_SSID_ADC_18: + case X310_2943R_40MHz_PCIE_SSID_ADC_18: + case X310_2943R_120MHz_PCIE_SSID_ADC_18: + case X310_2944R_40MHz_PCIE_SSID_ADC_18: + case X310_2945R_PCIE_SSID_ADC_18: + case X310_2950R_40MHz_PCIE_SSID_ADC_18: + case X310_2950R_120MHz_PCIE_SSID_ADC_18: + case X310_2952R_40MHz_PCIE_SSID_ADC_18: + case X310_2952R_120MHz_PCIE_SSID_ADC_18: + case X310_2953R_40MHz_PCIE_SSID_ADC_18: + case X310_2953R_120MHz_PCIE_SSID_ADC_18: + case X310_2954R_40MHz_PCIE_SSID_ADC_18: + case X310_2955R_PCIE_SSID_ADC_18: + return x300_impl::USRP_X310_MB; + case X310_2974_PCIE_SSID_ADC_18: + return x300_impl::USRP_X310_MB_NI_2974; + default: + return x300_impl::UNKNOWN; } + UHD_THROW_INVALID_CODE_PATH(); +} - /*! Map the motherboard type to a product name - */ - std::string map_mb_type_to_product_name( - const x300_impl::x300_mboard_t mb_type, - const std::string& default_name="") - { - switch (mb_type) { - case x300_impl::USRP_X300_MB: - return "X300"; - case x300_impl::USRP_X310_MB: - return "X310"; - case x300_impl::USRP_X310_MB_NI_2974: - return "NI-2974"; - default: - return default_name; - } +/*! Map the motherboard type to a product name + */ +std::string map_mb_type_to_product_name( + const x300_impl::x300_mboard_t mb_type, const std::string& default_name = "") +{ + switch (mb_type) { + case x300_impl::USRP_X300_MB: + return "X300"; + case x300_impl::USRP_X310_MB: + return "X310"; + case x300_impl::USRP_X310_MB_NI_2974: + return "NI-2974"; + default: + return default_name; } +} -} /* namespace anon */ +} // namespace /*********************************************************************** * Discovery over the udp and pcie transport **********************************************************************/ //@TODO: Refactor the find functions to collapse common code for ethernet and PCIe -static device_addrs_t x300_find_with_addr(const device_addr_t &hint) +static device_addrs_t x300_find_with_addr(const device_addr_t& hint) { - udp_simple::sptr comm = udp_simple::make_broadcast( - hint["addr"], BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)); + udp_simple::sptr comm = + udp_simple::make_broadcast(hint["addr"], BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)); - //load request struct + // load request struct x300_fw_comms_t request = x300_fw_comms_t(); - request.flags = uhd::htonx<uint32_t>(X300_FW_COMMS_FLAGS_ACK); - request.sequence = uhd::htonx<uint32_t>(std::rand()); + request.flags = uhd::htonx<uint32_t>(X300_FW_COMMS_FLAGS_ACK); + request.sequence = uhd::htonx<uint32_t>(std::rand()); - //send request + // send request comm->send(asio::buffer(&request, sizeof(request))); - //loop for replies until timeout + // loop for replies until timeout device_addrs_t addrs; - while (true) - { + while (true) { char buff[X300_FW_COMMS_MTU] = {}; - const size_t nbytes = comm->recv(asio::buffer(buff), 0.050); - if (nbytes == 0) break; - const x300_fw_comms_t *reply = (const x300_fw_comms_t *)buff; - if (request.flags != reply->flags) continue; - if (request.sequence != reply->sequence) continue; + const size_t nbytes = comm->recv(asio::buffer(buff), 0.050); + if (nbytes == 0) + break; + const x300_fw_comms_t* reply = (const x300_fw_comms_t*)buff; + if (request.flags != reply->flags) + continue; + if (request.sequence != reply->sequence) + continue; device_addr_t new_addr; new_addr["type"] = "x300"; new_addr["addr"] = comm->get_recv_addr(); - //Attempt to read the name from the EEPROM and perform filtering. - //This operation can throw due to compatibility mismatch. - try - { + // Attempt to read the name from the EEPROM and perform filtering. + // This operation can throw due to compatibility mismatch. + try { wb_iface::sptr zpu_ctrl = x300_make_ctrl_iface_enet( - udp_simple::make_connected(new_addr["addr"], - BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)), + udp_simple::make_connected( + new_addr["addr"], BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)), false /* Suppress timeout errors */ ); new_addr["fpga"] = get_fpga_option(zpu_ctrl); - i2c_core_100_wb32::sptr zpu_i2c = i2c_core_100_wb32::make(zpu_ctrl, I2C1_BASE); - x300_mb_eeprom_iface::sptr eeprom_iface = x300_mb_eeprom_iface::make(zpu_ctrl, zpu_i2c); - const mboard_eeprom_t mb_eeprom = - x300_impl::get_mb_eeprom(eeprom_iface); - if (mb_eeprom.size() == 0 or x300_impl::claim_status(zpu_ctrl) == x300_impl::CLAIMED_BY_OTHER) - { + i2c_core_100_wb32::sptr zpu_i2c = + i2c_core_100_wb32::make(zpu_ctrl, I2C1_BASE); + x300_mb_eeprom_iface::sptr eeprom_iface = + x300_mb_eeprom_iface::make(zpu_ctrl, zpu_i2c); + const mboard_eeprom_t mb_eeprom = x300_impl::get_mb_eeprom(eeprom_iface); + if (mb_eeprom.size() == 0 + or x300_impl::claim_status(zpu_ctrl) == x300_impl::CLAIMED_BY_OTHER) { // Skip device claimed by another process continue; } - new_addr["name"] = mb_eeprom["name"]; - new_addr["serial"] = mb_eeprom["serial"]; + new_addr["name"] = mb_eeprom["name"]; + new_addr["serial"] = mb_eeprom["serial"]; const std::string product_name = map_mb_type_to_product_name( x300_impl::get_mb_type_from_eeprom(mb_eeprom)); if (!product_name.empty()) { new_addr["product"] = product_name; } - } - catch(const std::exception &) - { - //set these values as empty string so the device may still be found - //and the filter's below can still operate on the discovered device - new_addr["name"] = ""; + } catch (const std::exception&) { + // set these values as empty string so the device may still be found + // and the filter's below can still operate on the discovered device + new_addr["name"] = ""; new_addr["serial"] = ""; } - //filter the discovered device below by matching optional keys - if ( - (not hint.has_key("name") or hint["name"] == new_addr["name"]) and - (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]) and - (not hint.has_key("product") or hint["product"] == new_addr["product"]) - ){ + // filter the discovered device below by matching optional keys + if ((not hint.has_key("name") or hint["name"] == new_addr["name"]) + and (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]) + and (not hint.has_key("product") or hint["product"] == new_addr["product"])) { addrs.push_back(new_addr); } } @@ -228,13 +225,13 @@ static device_addrs_t x300_find_with_addr(const device_addr_t &hint) } -//We need a zpu xport registry to ensure synchronization between the static finder method -//and the instances of the x300_impl class. -typedef uhd::dict< std::string, boost::weak_ptr<wb_iface> > pcie_zpu_iface_registry_t; +// We need a zpu xport registry to ensure synchronization between the static finder method +// and the instances of the x300_impl class. +typedef uhd::dict<std::string, boost::weak_ptr<wb_iface>> pcie_zpu_iface_registry_t; UHD_SINGLETON_FCN(pcie_zpu_iface_registry_t, get_pcie_zpu_iface_registry) static boost::mutex pcie_zpu_iface_registry_mutex; -static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_query) +static device_addrs_t x300_find_pcie(const device_addr_t& hint, bool explicit_query) { std::string rpc_port_name(std::to_string(NIUSRPRIO_DEFAULT_RPC_PORT)); if (hint.has_key("niusrpriorpc_port")) { @@ -244,12 +241,13 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu device_addrs_t addrs; niusrprio_session::device_info_vtr dev_info_vtr; nirio_status status = niusrprio_session::enumerate(rpc_port_name, dev_info_vtr); - if (explicit_query) nirio_status_to_exception(status, "x300_find_pcie: Error enumerating NI-RIO devices."); + if (explicit_query) + nirio_status_to_exception( + status, "x300_find_pcie: Error enumerating NI-RIO devices."); - for(niusrprio_session::device_info &dev_info: dev_info_vtr) - { + for (niusrprio_session::device_info& dev_info : dev_info_vtr) { device_addr_t new_addr; - new_addr["type"] = "x300"; + new_addr["type"] = "x300"; new_addr["resource"] = dev_info.resource_name; std::string resource_d(dev_info.resource_name); boost::to_upper(resource_d); @@ -262,157 +260,154 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu new_addr["product"] = product_name; } - niriok_proxy::sptr kernel_proxy = niriok_proxy::make_and_open(dev_info.interface_path); + niriok_proxy::sptr kernel_proxy = + niriok_proxy::make_and_open(dev_info.interface_path); - //Attempt to read the name from the EEPROM and perform filtering. - //This operation can throw due to compatibility mismatch. - try - { - //This block could throw an exception if the user is switching to using UHD - //after LabVIEW FPGA. In that case, skip reading the name and serial and pick - //a default FPGA flavor. During make, a new image will be loaded and everything - //will be OK + // Attempt to read the name from the EEPROM and perform filtering. + // This operation can throw due to compatibility mismatch. + try { + // This block could throw an exception if the user is switching to using UHD + // after LabVIEW FPGA. In that case, skip reading the name and serial and pick + // a default FPGA flavor. During make, a new image will be loaded and + // everything will be OK wb_iface::sptr zpu_ctrl; - //Hold on to the registry mutex as long as zpu_ctrl is alive - //to prevent any use by different threads while enumerating + // Hold on to the registry mutex as long as zpu_ctrl is alive + // to prevent any use by different threads while enumerating boost::mutex::scoped_lock lock(pcie_zpu_iface_registry_mutex); if (get_pcie_zpu_iface_registry().has_key(resource_d)) { zpu_ctrl = get_pcie_zpu_iface_registry()[resource_d].lock(); - if (!zpu_ctrl) - { + if (!zpu_ctrl) { get_pcie_zpu_iface_registry().pop(resource_d); } } // if the registry didn't have a key OR that key was an orphaned weak_ptr - if (!zpu_ctrl) - { - zpu_ctrl = x300_make_ctrl_iface_pcie(kernel_proxy, false /* suppress timeout errors */); - //We don't put this zpu_ctrl in the registry because we need - //a persistent niriok_proxy associated with the object + if (!zpu_ctrl) { + zpu_ctrl = x300_make_ctrl_iface_pcie( + kernel_proxy, false /* suppress timeout errors */); + // We don't put this zpu_ctrl in the registry because we need + // a persistent niriok_proxy associated with the object } - //Attempt to autodetect the FPGA type + // Attempt to autodetect the FPGA type if (not hint.has_key("fpga")) { new_addr["fpga"] = get_fpga_option(zpu_ctrl); } - i2c_core_100_wb32::sptr zpu_i2c = i2c_core_100_wb32::make(zpu_ctrl, I2C1_BASE); - x300_mb_eeprom_iface::sptr eeprom_iface = x300_mb_eeprom_iface::make(zpu_ctrl, zpu_i2c); - const mboard_eeprom_t mb_eeprom = - x300_impl::get_mb_eeprom(eeprom_iface); - if (mb_eeprom.size() == 0 or x300_impl::claim_status(zpu_ctrl) == x300_impl::CLAIMED_BY_OTHER) - { + i2c_core_100_wb32::sptr zpu_i2c = + i2c_core_100_wb32::make(zpu_ctrl, I2C1_BASE); + x300_mb_eeprom_iface::sptr eeprom_iface = + x300_mb_eeprom_iface::make(zpu_ctrl, zpu_i2c); + const mboard_eeprom_t mb_eeprom = x300_impl::get_mb_eeprom(eeprom_iface); + if (mb_eeprom.size() == 0 + or x300_impl::claim_status(zpu_ctrl) == x300_impl::CLAIMED_BY_OTHER) { // Skip device claimed by another process continue; } - new_addr["name"] = mb_eeprom["name"]; + new_addr["name"] = mb_eeprom["name"]; new_addr["serial"] = mb_eeprom["serial"]; - } - catch(const std::exception &) - { - //set these values as empty string so the device may still be found - //and the filter's below can still operate on the discovered device + } catch (const std::exception&) { + // set these values as empty string so the device may still be found + // and the filter's below can still operate on the discovered device if (not hint.has_key("fpga")) { new_addr["fpga"] = "HG"; } - new_addr["name"] = ""; + new_addr["name"] = ""; new_addr["serial"] = ""; } - //filter the discovered device below by matching optional keys + // filter the discovered device below by matching optional keys std::string resource_i = hint.has_key("resource") ? hint["resource"] : ""; boost::to_upper(resource_i); - if ( - (not hint.has_key("resource") or resource_i == resource_d) and - (not hint.has_key("name") or hint["name"] == new_addr["name"]) and - (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]) and - (not hint.has_key("product") or hint["product"] == new_addr["product"]) - ){ + if ((not hint.has_key("resource") or resource_i == resource_d) + and (not hint.has_key("name") or hint["name"] == new_addr["name"]) + and (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]) + and (not hint.has_key("product") or hint["product"] == new_addr["product"])) { addrs.push_back(new_addr); } } return addrs; } -device_addrs_t x300_find(const device_addr_t &hint_) +device_addrs_t x300_find(const device_addr_t& hint_) { - //handle the multi-device discovery + // handle the multi-device discovery device_addrs_t hints = separate_device_addr(hint_); - if (hints.size() > 1) - { + if (hints.size() > 1) { device_addrs_t found_devices; std::string error_msg; - for(const device_addr_t &hint_i: hints) - { + for (const device_addr_t& hint_i : hints) { device_addrs_t found_devices_i = x300_find(hint_i); - if (found_devices_i.size() != 1) error_msg += str(boost::format( - "Could not resolve device hint \"%s\" to a single device." - ) % hint_i.to_string()); - else found_devices.push_back(found_devices_i[0]); + if (found_devices_i.size() != 1) + error_msg += + str(boost::format( + "Could not resolve device hint \"%s\" to a single device.") + % hint_i.to_string()); + else + found_devices.push_back(found_devices_i[0]); } - if (found_devices.empty()) return device_addrs_t(); - if (not error_msg.empty()) throw uhd::value_error(error_msg); + if (found_devices.empty()) + return device_addrs_t(); + if (not error_msg.empty()) + throw uhd::value_error(error_msg); return device_addrs_t(1, combine_device_addrs(found_devices)); } - //initialize the hint for a single device case + // initialize the hint for a single device case UHD_ASSERT_THROW(hints.size() <= 1); - hints.resize(1); //in case it was empty + hints.resize(1); // in case it was empty device_addr_t hint = hints[0]; device_addrs_t addrs; - if (hint.has_key("type") and hint["type"] != "x300") return addrs; + if (hint.has_key("type") and hint["type"] != "x300") + return addrs; - //use the address given - if (hint.has_key("addr")) - { + // use the address given + if (hint.has_key("addr")) { device_addrs_t reply_addrs; - try - { + try { reply_addrs = x300_find_with_addr(hint); - } - catch(const std::exception &ex) - { - UHD_LOGGER_ERROR("X300") << "X300 Network discovery error " << ex.what() ; - } - catch(...) - { - UHD_LOGGER_ERROR("X300") << "X300 Network discovery unknown error " ; + } catch (const std::exception& ex) { + UHD_LOGGER_ERROR("X300") << "X300 Network discovery error " << ex.what(); + } catch (...) { + UHD_LOGGER_ERROR("X300") << "X300 Network discovery unknown error "; } return reply_addrs; } - if (!hint.has_key("resource")) - { - //otherwise, no address was specified, send a broadcast on each interface - for(const if_addrs_t &if_addrs: get_if_addrs()) - { - //avoid the loopback device - if (if_addrs.inet == asio::ip::address_v4::loopback().to_string()) continue; + if (!hint.has_key("resource")) { + // otherwise, no address was specified, send a broadcast on each interface + for (const if_addrs_t& if_addrs : get_if_addrs()) { + // avoid the loopback device + if (if_addrs.inet == asio::ip::address_v4::loopback().to_string()) + continue; - //create a new hint with this broadcast address + // create a new hint with this broadcast address device_addr_t new_hint = hint; - new_hint["addr"] = if_addrs.bcast; + new_hint["addr"] = if_addrs.bcast; - //call discover with the new hint and append results + // call discover with the new hint and append results device_addrs_t new_addrs = x300_find(new_hint); - //if we are looking for a serial, only add the one device with a matching serial + // if we are looking for a serial, only add the one device with a matching + // serial if (hint.has_key("serial")) { - bool found_serial = false; //signal to break out of the interface loop - for (device_addrs_t::iterator new_addr_it=new_addrs.begin(); new_addr_it != new_addrs.end(); new_addr_it++) { + bool found_serial = false; // signal to break out of the interface loop + for (device_addrs_t::iterator new_addr_it = new_addrs.begin(); + new_addr_it != new_addrs.end(); + new_addr_it++) { if ((*new_addr_it)["serial"] == hint["serial"]) { addrs.insert(addrs.begin(), *new_addr_it); found_serial = true; break; } } - if (found_serial) break; + if (found_serial) + break; } else { // Otherwise, add all devices we find addrs.insert(addrs.begin(), new_addrs.begin(), new_addrs.end()); @@ -421,7 +416,8 @@ device_addrs_t x300_find(const device_addr_t &hint_) } device_addrs_t pcie_addrs = x300_find_pcie(hint, hint.has_key("resource")); - if (not pcie_addrs.empty()) addrs.insert(addrs.end(), pcie_addrs.begin(), pcie_addrs.end()); + if (not pcie_addrs.empty()) + addrs.insert(addrs.end(), pcie_addrs.begin(), pcie_addrs.end()); return addrs; } @@ -429,7 +425,7 @@ device_addrs_t x300_find(const device_addr_t &hint_) /*********************************************************************** * Make **********************************************************************/ -static device::sptr x300_make(const device_addr_t &device_addr) +static device::sptr x300_make(const device_addr_t& device_addr) { return device::sptr(new x300_impl(device_addr)); } @@ -439,33 +435,33 @@ UHD_STATIC_BLOCK(register_x300_device) device::register_device(&x300_find, &x300_make, device::USRP); } -static void x300_load_fw(wb_iface::sptr fw_reg_ctrl, const std::string &file_name) +static void x300_load_fw(wb_iface::sptr fw_reg_ctrl, const std::string& file_name) { UHD_LOGGER_INFO("X300") << "Loading firmware " << file_name; - //load file into memory + // load file into memory std::ifstream fw_file(file_name.c_str()); - uint32_t fw_file_buff[X300_FW_NUM_BYTES/sizeof(uint32_t)]; - fw_file.read((char *)fw_file_buff, sizeof(fw_file_buff)); + uint32_t fw_file_buff[X300_FW_NUM_BYTES / sizeof(uint32_t)]; + fw_file.read((char*)fw_file_buff, sizeof(fw_file_buff)); fw_file.close(); - //Poke the fw words into the WB boot loader + // Poke the fw words into the WB boot loader fw_reg_ctrl->poke32(SR_ADDR(BOOT_LDR_BASE, BL_ADDRESS), 0); - for (size_t i = 0; i < X300_FW_NUM_BYTES; i+=sizeof(uint32_t)) - { - //@TODO: FIXME: Since x300_ctrl_iface acks each write and traps exceptions, the first try for the last word - // written will print an error because it triggers a FW reload and fails to reply. - fw_reg_ctrl->poke32(SR_ADDR(BOOT_LDR_BASE, BL_DATA), uhd::byteswap(fw_file_buff[i/sizeof(uint32_t)])); + for (size_t i = 0; i < X300_FW_NUM_BYTES; i += sizeof(uint32_t)) { + //@TODO: FIXME: Since x300_ctrl_iface acks each write and traps exceptions, the + // first try for the last word + // written will print an error because it triggers a FW reload and + // fails to reply. + fw_reg_ctrl->poke32(SR_ADDR(BOOT_LDR_BASE, BL_DATA), + uhd::byteswap(fw_file_buff[i / sizeof(uint32_t)])); } - //Wait for fimrware to reboot. 3s is an upper bound + // Wait for fimrware to reboot. 3s is an upper bound std::this_thread::sleep_for(std::chrono::milliseconds(3000)); - UHD_LOGGER_INFO("X300") << "Firmware loaded!" ; + UHD_LOGGER_INFO("X300") << "Firmware loaded!"; } -x300_impl::x300_impl(const uhd::device_addr_t &dev_addr) - : device3_impl() - , _sid_framer(0) +x300_impl::x300_impl(const uhd::device_addr_t& dev_addr) : device3_impl(), _sid_framer(0) { UHD_LOGGER_INFO("X300") << "X300 initialization sequence..."; _tree->create<std::string>("/name").set("X-Series Device"); @@ -475,8 +471,7 @@ x300_impl::x300_impl(const uhd::device_addr_t &dev_addr) // Serialize the initialization process if (dev_addr.has_key("serialize_init") or device_args.size() == 1) { - for (size_t i = 0; i < device_args.size(); i++) - { + for (size_t i = 0; i < device_args.size(); i++) { this->setup_mb(i, device_args[i]); } return; @@ -486,26 +481,22 @@ x300_impl::x300_impl(const uhd::device_addr_t &dev_addr) // Initialize groups of USRPs in parallel size_t total_usrps = device_args.size(); size_t num_usrps = 0; - while (num_usrps < total_usrps) - { + while (num_usrps < total_usrps) { size_t init_usrps = std::min(total_usrps - num_usrps, x300::MAX_INIT_THREADS); boost::thread_group setup_threads; - for (size_t i = 0; i < init_usrps; i++) - { + for (size_t i = 0; i < init_usrps; i++) { const size_t index = num_usrps + i; - setup_threads.create_thread([this, index, device_args](){ + setup_threads.create_thread([this, index, device_args]() { this->setup_mb(index, device_args[index]); }); } setup_threads.join_all(); num_usrps += init_usrps; } - } void x300_impl::mboard_members_t::discover_eth( - const mboard_eeprom_t mb_eeprom, - const std::vector<std::string> &ip_addrs) + const mboard_eeprom_t mb_eeprom, const std::vector<std::string>& ip_addrs) { // Clear any previous addresses added eth_conns.clear(); @@ -517,16 +508,19 @@ void x300_impl::mboard_members_t::discover_eth( const std::string key = "ip-addr" + boost::to_string(i); // Show a warning if there exists duplicate addresses in the mboard eeprom - if (std::find(mb_eeprom_addrs.begin(), mb_eeprom_addrs.end(), mb_eeprom[key]) != mb_eeprom_addrs.end()) { - UHD_LOGGER_WARNING("X300") << str(boost::format( - "Duplicate IP address %s found in mboard EEPROM. " - "Device may not function properly. View and reprogram the values " - "using the usrp_burn_mb_eeprom utility.") % mb_eeprom[key]); + if (std::find(mb_eeprom_addrs.begin(), mb_eeprom_addrs.end(), mb_eeprom[key]) + != mb_eeprom_addrs.end()) { + UHD_LOGGER_WARNING("X300") << str( + boost::format( + "Duplicate IP address %s found in mboard EEPROM. " + "Device may not function properly. View and reprogram the values " + "using the usrp_burn_mb_eeprom utility.") + % mb_eeprom[key]); } mb_eeprom_addrs.push_back(mb_eeprom[key]); } - for(const std::string& addr: ip_addrs) { + for (const std::string& addr : ip_addrs) { x300_eth_conn_t conn_iface; conn_iface.addr = addr; conn_iface.type = X300_IFACE_NONE; @@ -537,10 +531,12 @@ void x300_impl::mboard_members_t::discover_eth( if (addr == mb_eeprom_addrs[i]) { // Choose the interface based on the index parity if (i % 2 == 0) { - conn_iface.type = X300_IFACE_ETH0; - conn_iface.link_rate = loaded_fpga_image == "HG" ? x300::MAX_RATE_1GIGE : x300::MAX_RATE_10GIGE; + conn_iface.type = X300_IFACE_ETH0; + conn_iface.link_rate = loaded_fpga_image == "HG" + ? x300::MAX_RATE_1GIGE + : x300::MAX_RATE_10GIGE; } else { - conn_iface.type = X300_IFACE_ETH1; + conn_iface.type = X300_IFACE_ETH1; conn_iface.link_rate = x300::MAX_RATE_10GIGE; } break; @@ -550,45 +546,49 @@ void x300_impl::mboard_members_t::discover_eth( // Check default IP addresses if we couldn't // determine the IP from the mboard eeprom if (conn_iface.type == X300_IFACE_NONE) { - UHD_LOGGER_WARNING("X300") << str(boost::format( - "Address %s not found in mboard EEPROM. Address may be wrong or " - "the EEPROM may be corrupt. Attempting to continue with default " - "IP addresses.") % conn_iface.addr - ); - - if (addr == boost::asio::ip::address_v4( - uint32_t(X300_DEFAULT_IP_ETH0_1G)).to_string()) { - conn_iface.type = X300_IFACE_ETH0; + UHD_LOGGER_WARNING("X300") << str( + boost::format( + "Address %s not found in mboard EEPROM. Address may be wrong or " + "the EEPROM may be corrupt. Attempting to continue with default " + "IP addresses.") + % conn_iface.addr); + + if (addr + == boost::asio::ip::address_v4(uint32_t(X300_DEFAULT_IP_ETH0_1G)) + .to_string()) { + conn_iface.type = X300_IFACE_ETH0; conn_iface.link_rate = x300::MAX_RATE_1GIGE; - } else if (addr == boost::asio::ip::address_v4( - uint32_t(X300_DEFAULT_IP_ETH1_1G)).to_string()) { - conn_iface.type = X300_IFACE_ETH1; + } else if (addr + == boost::asio::ip::address_v4(uint32_t(X300_DEFAULT_IP_ETH1_1G)) + .to_string()) { + conn_iface.type = X300_IFACE_ETH1; conn_iface.link_rate = x300::MAX_RATE_1GIGE; - } else if (addr == boost::asio::ip::address_v4( - uint32_t(X300_DEFAULT_IP_ETH0_10G)).to_string()) { - conn_iface.type = X300_IFACE_ETH0; + } else if (addr + == boost::asio::ip::address_v4(uint32_t(X300_DEFAULT_IP_ETH0_10G)) + .to_string()) { + conn_iface.type = X300_IFACE_ETH0; conn_iface.link_rate = x300::MAX_RATE_10GIGE; - } else if (addr == boost::asio::ip::address_v4( - uint32_t(X300_DEFAULT_IP_ETH1_10G)).to_string()) { - conn_iface.type = X300_IFACE_ETH1; + } else if (addr + == boost::asio::ip::address_v4(uint32_t(X300_DEFAULT_IP_ETH1_10G)) + .to_string()) { + conn_iface.type = X300_IFACE_ETH1; conn_iface.link_rate = x300::MAX_RATE_10GIGE; } else { - throw uhd::assertion_error(str(boost::format( - "X300 Initialization Error: Failed to match address %s with " - "any addresses for the device. Please check the address.") - % conn_iface.addr - )); + throw uhd::assertion_error( + str(boost::format( + "X300 Initialization Error: Failed to match address %s with " + "any addresses for the device. Please check the address.") + % conn_iface.addr)); } } // Save to a vector of connections if (conn_iface.type != X300_IFACE_NONE) { // Check the address before we add it - try - { + try { wb_iface::sptr zpu_ctrl = x300_make_ctrl_iface_enet( - udp_simple::make_connected(conn_iface.addr, - BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)), + udp_simple::make_connected( + conn_iface.addr, BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)), false /* Suppress timeout errors */ ); @@ -597,42 +597,40 @@ void x300_impl::mboard_members_t::discover_eth( } // If the address does not work, throw an error - catch(std::exception &) - { - throw uhd::io_error(str(boost::format( - "X300 Initialization Error: Invalid address %s") - % conn_iface.addr)); + catch (std::exception&) { + throw uhd::io_error( + str(boost::format("X300 Initialization Error: Invalid address %s") + % conn_iface.addr)); } eth_conns.push_back(conn_iface); } } if (eth_conns.size() == 0) - throw uhd::assertion_error("X300 Initialization Error: No ethernet interfaces specified."); + throw uhd::assertion_error( + "X300 Initialization Error: No ethernet interfaces specified."); } -void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) +void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t& dev_addr) { - const fs_path mb_path = fs_path("/mboards") / mb_i; - mboard_members_t &mb = _mb[mb_i]; + const fs_path mb_path = fs_path("/mboards") / mb_i; + mboard_members_t& mb = _mb[mb_i]; mb.initialization_done = false; const std::string thread_id( - boost::lexical_cast<std::string>(boost::this_thread::get_id()) - ); + boost::lexical_cast<std::string>(boost::this_thread::get_id())); const std::string thread_msg( - "Thread ID " + thread_id + " for motherboard " - + std::to_string(mb_i) - ); + "Thread ID " + thread_id + " for motherboard " + std::to_string(mb_i)); mb.args.parse(dev_addr); std::vector<std::string> eth_addrs; // Not choosing eth0 based on resource might cause user issues - std::string eth0_addr = dev_addr.has_key("resource") ? dev_addr["resource"] : dev_addr["addr"]; + std::string eth0_addr = dev_addr.has_key("resource") ? dev_addr["resource"] + : dev_addr["addr"]; eth_addrs.push_back(eth0_addr); - mb.next_src_addr = 0; //Host source address for blocks + mb.next_src_addr = 0; // Host source address for blocks mb.next_tx_src_addr = 0; mb.next_rx_src_addr = 0; if (not mb.args.get_second_addr().empty()) { @@ -649,19 +647,18 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) init.addr = eth_addrs[0]; mb.eth_conns.push_back(init); - mb.xport_path = dev_addr.has_key("resource") ? "nirio" : "eth"; + mb.xport_path = dev_addr.has_key("resource") ? "nirio" : "eth"; mb.if_pkt_is_big_endian = mb.xport_path != "nirio"; - if (mb.xport_path == "nirio") - { + if (mb.xport_path == "nirio") { nirio_status status = 0; const std::string rpc_port_name = mb.args.get_niusrprio_rpc_port(); UHD_LOGGER_INFO("X300") << boost::format("Connecting to niusrpriorpc at localhost:%s...") - % rpc_port_name; + % rpc_port_name; - //Instantiate the correct lvbitx object + // Instantiate the correct lvbitx object nifpga_lvbitx::sptr lvbitx; switch (get_mb_type_from_pcie(mb.args.get_resource(), rpc_port_name)) { case USRP_X300_MB: @@ -672,85 +669,95 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) lvbitx.reset(new x310_lvbitx(dev_addr["fpga"])); break; default: - nirio_status_to_exception(status, "Motherboard detection error. Please ensure that you \ + nirio_status_to_exception( + status, "Motherboard detection error. Please ensure that you \ have a valid USRP X3x0, NI USRP-294xR, NI USRP-295xR or NI USRP-2974 device and that all the device \ drivers have loaded successfully."); } - //Load the lvbitx onto the device - UHD_LOGGER_INFO("X300") << boost::format("Using LVBITX bitfile %s...") % lvbitx->get_bitfile_path(); - mb.rio_fpga_interface.reset(new niusrprio_session(dev_addr["resource"], rpc_port_name)); - nirio_status_chain(mb.rio_fpga_interface->open(lvbitx, dev_addr.has_key("download-fpga")), status); + // Load the lvbitx onto the device + UHD_LOGGER_INFO("X300") + << boost::format("Using LVBITX bitfile %s...") % lvbitx->get_bitfile_path(); + mb.rio_fpga_interface.reset( + new niusrprio_session(dev_addr["resource"], rpc_port_name)); + nirio_status_chain( + mb.rio_fpga_interface->open(lvbitx, dev_addr.has_key("download-fpga")), + status); nirio_status_to_exception(status, "x300_impl: Could not initialize RIO session."); - //Tell the quirks object which FIFOs carry TX stream data - const uint32_t tx_data_fifos[2] = {x300::RADIO_DEST_PREFIX_TX, x300::RADIO_DEST_PREFIX_TX + 3}; - mb.rio_fpga_interface->get_kernel_proxy()->get_rio_quirks().register_tx_streams(tx_data_fifos, 2); + // Tell the quirks object which FIFOs carry TX stream data + const uint32_t tx_data_fifos[2] = { + x300::RADIO_DEST_PREFIX_TX, x300::RADIO_DEST_PREFIX_TX + 3}; + mb.rio_fpga_interface->get_kernel_proxy()->get_rio_quirks().register_tx_streams( + tx_data_fifos, 2); _tree->create<size_t>(mb_path / "mtu/recv").set(x300::PCIE_RX_DATA_FRAME_SIZE); _tree->create<size_t>(mb_path / "mtu/send").set(x300::PCIE_TX_DATA_FRAME_SIZE); _tree->create<double>(mb_path / "link_max_rate").set(x300::MAX_RATE_PCIE); } - for(const std::string &key: dev_addr.keys()) - { - if (key.find("recv") != std::string::npos) mb.recv_args[key] = dev_addr[key]; - if (key.find("send") != std::string::npos) mb.send_args[key] = dev_addr[key]; + for (const std::string& key : dev_addr.keys()) { + if (key.find("recv") != std::string::npos) + mb.recv_args[key] = dev_addr[key]; + if (key.find("send") != std::string::npos) + mb.send_args[key] = dev_addr[key]; } - //create basic communication + // create basic communication UHD_LOGGER_DEBUG("X300") << "Setting up basic communication..."; if (mb.xport_path == "nirio") { boost::mutex::scoped_lock lock(pcie_zpu_iface_registry_mutex); if (get_pcie_zpu_iface_registry().has_key(mb.get_pri_eth().addr)) { - throw uhd::assertion_error("Someone else has a ZPU transport to the device open. Internal error!"); + throw uhd::assertion_error( + "Someone else has a ZPU transport to the device open. Internal error!"); } else { - mb.zpu_ctrl = x300_make_ctrl_iface_pcie(mb.rio_fpga_interface->get_kernel_proxy()); - get_pcie_zpu_iface_registry()[mb.get_pri_eth().addr] = boost::weak_ptr<wb_iface>(mb.zpu_ctrl); + mb.zpu_ctrl = + x300_make_ctrl_iface_pcie(mb.rio_fpga_interface->get_kernel_proxy()); + get_pcie_zpu_iface_registry()[mb.get_pri_eth().addr] = + boost::weak_ptr<wb_iface>(mb.zpu_ctrl); } } else { mb.zpu_ctrl = x300_make_ctrl_iface_enet(udp_simple::make_connected( - mb.get_pri_eth().addr, BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT))); + mb.get_pri_eth().addr, BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT))); } // Claim device if (not try_to_claim(mb.zpu_ctrl)) { throw uhd::runtime_error("Failed to claim device"); } - mb.claimer_task = uhd::task::make([this, mb](){ - this->claimer_loop(mb.zpu_ctrl); - }, "x300_claimer"); + mb.claimer_task = uhd::task::make( + [this, mb]() { this->claimer_loop(mb.zpu_ctrl); }, "x300_claimer"); - //extract the FW path for the X300 - //and live load fw over ethernet link + // extract the FW path for the X300 + // and live load fw over ethernet link if (mb.args.has_fw_file()) { - const std::string x300_fw_image = - find_image_path(mb.args.get_fw_file()); + const std::string x300_fw_image = find_image_path(mb.args.get_fw_file()); x300_load_fw(mb.zpu_ctrl, x300_fw_image); } - //check compat numbers - //check fpga compat before fw compat because the fw is a subset of the fpga image + // check compat numbers + // check fpga compat before fw compat because the fw is a subset of the fpga image this->check_fpga_compat(mb_path, mb); this->check_fw_compat(mb_path, mb); mb.fw_regmap = boost::make_shared<fw_regmap_t>(); mb.fw_regmap->initialize(*mb.zpu_ctrl.get(), true); - //store which FPGA image is loaded + // store which FPGA image is loaded mb.loaded_fpga_image = get_fpga_option(mb.zpu_ctrl); - //low speed perif access - mb.zpu_spi = spi_core_3000::make(mb.zpu_ctrl, SR_ADDR(SET0_BASE, ZPU_SR_SPI), - SR_ADDR(SET0_BASE, ZPU_RB_SPI)); + // low speed perif access + mb.zpu_spi = spi_core_3000::make( + mb.zpu_ctrl, SR_ADDR(SET0_BASE, ZPU_SR_SPI), SR_ADDR(SET0_BASE, ZPU_RB_SPI)); mb.zpu_i2c = i2c_core_100_wb32::make(mb.zpu_ctrl, I2C1_BASE); - mb.zpu_i2c->set_clock_rate(x300::BUS_CLOCK_RATE/2); + mb.zpu_i2c->set_clock_rate(x300::BUS_CLOCK_RATE / 2); //////////////////////////////////////////////////////////////////// // print network routes mapping //////////////////////////////////////////////////////////////////// /* - const uint32_t routes_addr = mb.zpu_ctrl->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_ROUTE_MAP_ADDR)); - const uint32_t routes_len = mb.zpu_ctrl->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_ROUTE_MAP_LEN)); + const uint32_t routes_addr = mb.zpu_ctrl->peek32(SR_ADDR(X300_FW_SHMEM_BASE, + X300_FW_SHMEM_ROUTE_MAP_ADDR)); const uint32_t routes_len = + mb.zpu_ctrl->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_ROUTE_MAP_LEN)); UHD_VAR(routes_len); for (size_t i = 0; i < routes_len; i+=1) { @@ -778,29 +785,28 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) } const mboard_eeprom_t mb_eeprom = get_mb_eeprom(eeprom16); - _tree->create<mboard_eeprom_t>(mb_path / "eeprom") + _tree + ->create<mboard_eeprom_t>(mb_path / "eeprom") // Initialize the property with a current copy of the EEPROM contents .set(mb_eeprom) // Whenever this property is written, update the chip - .add_coerced_subscriber( - [this, eeprom16](const mboard_eeprom_t &mb_eeprom){ - this->set_mb_eeprom(eeprom16, mb_eeprom); - } - ) - ; + .add_coerced_subscriber([this, eeprom16](const mboard_eeprom_t& mb_eeprom) { + this->set_mb_eeprom(eeprom16, mb_eeprom); + }); if (mb.args.get_recover_mb_eeprom()) { - UHD_LOGGER_WARNING("X300") << "UHD is operating in EEPROM Recovery Mode which disables hardware version " - "checks.\nOperating in this mode may cause hardware damage and unstable " - "radio performance!"; + UHD_LOGGER_WARNING("X300") + << "UHD is operating in EEPROM Recovery Mode which disables hardware version " + "checks.\nOperating in this mode may cause hardware damage and unstable " + "radio performance!"; return; } //////////////////////////////////////////////////////////////////// // parse the product number //////////////////////////////////////////////////////////////////// - const std::string product_name = map_mb_type_to_product_name( - get_mb_type_from_eeprom(mb_eeprom), "X300?"); + const std::string product_name = + map_mb_type_to_product_name(get_mb_type_from_eeprom(mb_eeprom), "X300?"); if (product_name == "X300?") { if (not mb.args.get_recover_mb_eeprom()) { throw uhd::runtime_error( @@ -818,7 +824,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) //////////////////////////////////////////////////////////////////// // discover ethernet interfaces, frame sizes, and link rates //////////////////////////////////////////////////////////////////// - if (mb.xport_path == "eth" ) { + if (mb.xport_path == "eth") { double link_max_rate = 0.0; // Discover ethernet interfaces @@ -836,101 +842,104 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) * multiple transmission units - this is why the limits passed into the * 'determine_max_frame_size' function are actually frame sizes. */ frame_size_t req_max_frame_size; - req_max_frame_size.recv_frame_size = (mb.recv_args.has_key("recv_frame_size")) \ - ? boost::lexical_cast<size_t>(mb.recv_args["recv_frame_size"]) \ - : x300::DATA_FRAME_MAX_SIZE; - req_max_frame_size.send_frame_size = (mb.send_args.has_key("send_frame_size")) \ - ? boost::lexical_cast<size_t>(mb.send_args["send_frame_size"]) \ - : x300::DATA_FRAME_MAX_SIZE; - - #if defined UHD_PLATFORM_LINUX - const std::string mtu_tool("ip link"); - #elif defined UHD_PLATFORM_WIN32 - const std::string mtu_tool("netsh"); - #else - const std::string mtu_tool("ifconfig"); - #endif + req_max_frame_size.recv_frame_size = + (mb.recv_args.has_key("recv_frame_size")) + ? boost::lexical_cast<size_t>(mb.recv_args["recv_frame_size"]) + : x300::DATA_FRAME_MAX_SIZE; + req_max_frame_size.send_frame_size = + (mb.send_args.has_key("send_frame_size")) + ? boost::lexical_cast<size_t>(mb.send_args["send_frame_size"]) + : x300::DATA_FRAME_MAX_SIZE; + +#if defined UHD_PLATFORM_LINUX + const std::string mtu_tool("ip link"); +#elif defined UHD_PLATFORM_WIN32 + const std::string mtu_tool("netsh"); +#else + const std::string mtu_tool("ifconfig"); +#endif // Detect the frame size on the path to the USRP try { - frame_size_t pri_frame_sizes = determine_max_frame_size( - eth_addrs.at(0), req_max_frame_size - ); + frame_size_t pri_frame_sizes = + determine_max_frame_size(eth_addrs.at(0), req_max_frame_size); _max_frame_sizes = pri_frame_sizes; if (eth_addrs.size() > 1) { - frame_size_t sec_frame_sizes = determine_max_frame_size( - eth_addrs.at(1), req_max_frame_size - ); + frame_size_t sec_frame_sizes = + determine_max_frame_size(eth_addrs.at(1), req_max_frame_size); // Choose the minimum of the max frame sizes // to ensure we don't exceed any one of the links' MTU _max_frame_sizes.recv_frame_size = std::min( - pri_frame_sizes.recv_frame_size, - sec_frame_sizes.recv_frame_size - ); + pri_frame_sizes.recv_frame_size, sec_frame_sizes.recv_frame_size); _max_frame_sizes.send_frame_size = std::min( - pri_frame_sizes.send_frame_size, - sec_frame_sizes.send_frame_size - ); + pri_frame_sizes.send_frame_size, sec_frame_sizes.send_frame_size); } - } catch(std::exception &e) { - UHD_LOGGER_ERROR("X300") << e.what() ; + } catch (std::exception& e) { + UHD_LOGGER_ERROR("X300") << e.what(); } if ((mb.recv_args.has_key("recv_frame_size")) - && (req_max_frame_size.recv_frame_size > _max_frame_sizes.recv_frame_size)) { + && (req_max_frame_size.recv_frame_size > _max_frame_sizes.recv_frame_size)) { UHD_LOGGER_WARNING("X300") - << boost::format("You requested a receive frame size of (%lu) but your NIC's max frame size is (%lu).") - % req_max_frame_size.recv_frame_size - % _max_frame_sizes.recv_frame_size - << boost::format("Please verify your NIC's MTU setting using '%s' or set the recv_frame_size argument appropriately.") - % mtu_tool - << "UHD will use the auto-detected max frame size for this connection." - ; + << boost::format("You requested a receive frame size of (%lu) but your " + "NIC's max frame size is (%lu).") + % req_max_frame_size.recv_frame_size + % _max_frame_sizes.recv_frame_size + << boost::format("Please verify your NIC's MTU setting using '%s' or set " + "the recv_frame_size argument appropriately.") + % mtu_tool + << "UHD will use the auto-detected max frame size for this connection."; } if ((mb.send_args.has_key("send_frame_size")) - && (req_max_frame_size.send_frame_size > _max_frame_sizes.send_frame_size)) { + && (req_max_frame_size.send_frame_size > _max_frame_sizes.send_frame_size)) { UHD_LOGGER_WARNING("X300") - << boost::format("You requested a send frame size of (%lu) but your NIC's max frame size is (%lu).") - % req_max_frame_size.send_frame_size - % _max_frame_sizes.send_frame_size - << boost::format("Please verify your NIC's MTU setting using '%s' or set the send_frame_size argument appropriately.") - % mtu_tool - << "UHD will use the auto-detected max frame size for this connection." - ; + << boost::format("You requested a send frame size of (%lu) but your " + "NIC's max frame size is (%lu).") + % req_max_frame_size.send_frame_size + % _max_frame_sizes.send_frame_size + << boost::format("Please verify your NIC's MTU setting using '%s' or set " + "the send_frame_size argument appropriately.") + % mtu_tool + << "UHD will use the auto-detected max frame size for this connection."; } // Check frame sizes - for (auto conn : mb.eth_conns) - { + for (auto conn : mb.eth_conns) { link_max_rate += conn.link_rate; - size_t rec_send_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE ? x300::GE_DATA_FRAME_SEND_SIZE : x300::XGE_DATA_FRAME_SEND_SIZE; - size_t rec_recv_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE ? x300::GE_DATA_FRAME_RECV_SIZE : x300::XGE_DATA_FRAME_RECV_SIZE; + size_t rec_send_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE + ? x300::GE_DATA_FRAME_SEND_SIZE + : x300::XGE_DATA_FRAME_SEND_SIZE; + size_t rec_recv_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE + ? x300::GE_DATA_FRAME_RECV_SIZE + : x300::XGE_DATA_FRAME_RECV_SIZE; - if (_max_frame_sizes.send_frame_size < rec_send_frame_size) - { + if (_max_frame_sizes.send_frame_size < rec_send_frame_size) { UHD_LOGGER_WARNING("X300") - << boost::format("For the %s connection, UHD recommends a send frame size of at least %lu for best\nperformance, but your configuration will only allow %lu.") - % conn.addr - % rec_send_frame_size - % _max_frame_sizes.send_frame_size - << "This may negatively impact your maximum achievable sample rate.\nCheck the MTU on the interface and/or the send_frame_size argument." - ; + << boost::format("For the %s connection, UHD recommends a send frame " + "size of at least %lu for best\nperformance, but " + "your configuration will only allow %lu.") + % conn.addr % rec_send_frame_size + % _max_frame_sizes.send_frame_size + << "This may negatively impact your maximum achievable sample " + "rate.\nCheck the MTU on the interface and/or the send_frame_size " + "argument."; } - if (_max_frame_sizes.recv_frame_size < rec_recv_frame_size) - { + if (_max_frame_sizes.recv_frame_size < rec_recv_frame_size) { UHD_LOGGER_WARNING("X300") - << boost::format("For the %s connection, UHD recommends a receive frame size of at least %lu for best\nperformance, but your configuration will only allow %lu.") - % conn.addr - % rec_recv_frame_size - % _max_frame_sizes.recv_frame_size - << "This may negatively impact your maximum achievable sample rate.\nCheck the MTU on the interface and/or the recv_frame_size argument." - ; + << boost::format("For the %s connection, UHD recommends a receive " + "frame size of at least %lu for best\nperformance, " + "but your configuration will only allow %lu.") + % conn.addr % rec_recv_frame_size + % _max_frame_sizes.recv_frame_size + << "This may negatively impact your maximum achievable sample " + "rate.\nCheck the MTU on the interface and/or the recv_frame_size " + "argument."; } } @@ -943,40 +952,48 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) // read hardware revision and compatibility number //////////////////////////////////////////////////////////////////// mb.hw_rev = 0; - if(mb_eeprom.has_key("revision") and not mb_eeprom["revision"].empty()) { + if (mb_eeprom.has_key("revision") and not mb_eeprom["revision"].empty()) { try { mb.hw_rev = boost::lexical_cast<size_t>(mb_eeprom["revision"]); - } catch(...) { - throw uhd::runtime_error("Revision in EEPROM is invalid! Please reprogram your EEPROM."); + } catch (...) { + throw uhd::runtime_error( + "Revision in EEPROM is invalid! Please reprogram your EEPROM."); } } else { throw uhd::runtime_error("No revision detected. MB EEPROM must be reprogrammed!"); } size_t hw_rev_compat = 0; - if (mb.hw_rev >= 7) { //Revision compat was added with revision 7 - if (mb_eeprom.has_key("revision_compat") and not mb_eeprom["revision_compat"].empty()) { + if (mb.hw_rev >= 7) { // Revision compat was added with revision 7 + if (mb_eeprom.has_key("revision_compat") + and not mb_eeprom["revision_compat"].empty()) { try { hw_rev_compat = boost::lexical_cast<size_t>(mb_eeprom["revision_compat"]); - } catch(...) { - throw uhd::runtime_error("Revision compat in EEPROM is invalid! Please reprogram your EEPROM."); + } catch (...) { + throw uhd::runtime_error("Revision compat in EEPROM is invalid! Please " + "reprogram your EEPROM."); } } else { - throw uhd::runtime_error("No revision compat detected. MB EEPROM must be reprogrammed!"); + throw uhd::runtime_error( + "No revision compat detected. MB EEPROM must be reprogrammed!"); } } else { - //For older HW just assume that revision_compat = revision + // For older HW just assume that revision_compat = revision hw_rev_compat = mb.hw_rev; } if (hw_rev_compat > X300_REVISION_COMPAT) { - throw uhd::runtime_error(str(boost::format( - "Hardware is too new for this software. Please upgrade to a driver that supports hardware revision %d.") - % mb.hw_rev)); - } else if (mb.hw_rev < X300_REVISION_MIN) { //Compare min against the revision (and not compat) to give us more leeway for partial support for a compat - throw uhd::runtime_error(str(boost::format( - "Software is too new for this hardware. Please downgrade to a driver that supports hardware revision %d.") - % mb.hw_rev)); + throw uhd::runtime_error( + str(boost::format("Hardware is too new for this software. Please upgrade to " + "a driver that supports hardware revision %d.") + % mb.hw_rev)); + } else if (mb.hw_rev < X300_REVISION_MIN) { // Compare min against the revision (and + // not compat) to give us more leeway for + // partial support for a compat + throw uhd::runtime_error( + str(boost::format("Software is too new for this hardware. Please downgrade " + "to a driver that supports hardware revision %d.") + % mb.hw_rev)); } //////////////////////////////////////////////////////////////////// @@ -984,63 +1001,55 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) //////////////////////////////////////////////////////////////////// UHD_LOGGER_DEBUG("X300") << "Setting up RF frontend clocking..."; - //Initialize clock control registers. NOTE: This does not configure the LMK yet. + // Initialize clock control registers. NOTE: This does not configure the LMK yet. mb.clock = x300_clock_ctrl::make(mb.zpu_spi, 1 /*slaveno*/, mb.hw_rev, mb.args.get_master_clock_rate(), mb.args.get_dboard_clock_rate(), - mb.args.get_system_ref_rate() - ); + mb.args.get_system_ref_rate()); mb.fw_regmap->ref_freq_reg.write( - fw_regmap_t::ref_freq_reg_t::REF_FREQ, - uint32_t(mb.args.get_system_ref_rate()) - ); + fw_regmap_t::ref_freq_reg_t::REF_FREQ, uint32_t(mb.args.get_system_ref_rate())); - //Initialize clock source to use internal reference and generate - //a valid radio clock. This may change after configuration is done. - //This will configure the LMK and wait for lock + // Initialize clock source to use internal reference and generate + // a valid radio clock. This may change after configuration is done. + // This will configure the LMK and wait for lock update_clock_source(mb, mb.args.get_clock_source()); //////////////////////////////////////////////////////////////////// // create clock properties //////////////////////////////////////////////////////////////////// - _tree->create<double>(mb_path / "master_clock_rate") - .set_publisher([mb](){ return mb.clock->get_master_clock_rate(); }) - ; + _tree->create<double>(mb_path / "master_clock_rate").set_publisher([mb]() { + return mb.clock->get_master_clock_rate(); + }); - UHD_LOGGER_INFO("X300") - << "Radio 1x clock: " << (mb.clock->get_master_clock_rate()/1e6) - << " MHz"; + UHD_LOGGER_INFO("X300") << "Radio 1x clock: " + << (mb.clock->get_master_clock_rate() / 1e6) << " MHz"; //////////////////////////////////////////////////////////////////// // Create the GPSDO control //////////////////////////////////////////////////////////////////// static const uint32_t dont_look_for_gpsdo = 0x1234abcdul; - //otherwise if not disabled, look for the internal GPSDO - if (mb.zpu_ctrl->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_GPSDO_STATUS)) != dont_look_for_gpsdo) - { + // otherwise if not disabled, look for the internal GPSDO + if (mb.zpu_ctrl->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_GPSDO_STATUS)) + != dont_look_for_gpsdo) { UHD_LOG_DEBUG("X300", "Detecting internal GPSDO...."); try { // gps_ctrl will print its own log statements if a GPSDO was found mb.gps = gps_ctrl::make(x300_make_uart_iface(mb.zpu_ctrl)); - } - catch(std::exception &e) { + } catch (std::exception& e) { UHD_LOGGER_ERROR("X300") << "An error occurred making GPSDO control: " << e.what(); } if (mb.gps and mb.gps->gps_detected()) { - for(const std::string& name : mb.gps->get_sensors()) { + for (const std::string& name : mb.gps->get_sensors()) { _tree->create<sensor_value_t>(mb_path / "sensors" / name) - .set_publisher([&mb, name](){ - return mb.gps->get_sensor(name); - }) - ; + .set_publisher([&mb, name]() { return mb.gps->get_sensor(name); }); } - } - else { - mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_GPSDO_STATUS), dont_look_for_gpsdo); + } else { + mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_GPSDO_STATUS), + dont_look_for_gpsdo); } } @@ -1049,97 +1058,88 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) //////////////////////////////////////////////////////////////////// _tree->create<std::string>(mb_path / "time_source" / "value") .set(mb.args.get_time_source()) - .add_coerced_subscriber([this, &mb](const std::string& time_source){ + .add_coerced_subscriber([this, &mb](const std::string& time_source) { this->update_time_source(mb, time_source); - }) - ; - static const std::vector<std::string> time_sources = - {"internal", "external", "gpsdo"}; + }); + static const std::vector<std::string> time_sources = { + "internal", "external", "gpsdo"}; _tree->create<std::vector<std::string>>(mb_path / "time_source" / "options") .set(time_sources); - //setup the time output, default to ON + // setup the time output, default to ON _tree->create<bool>(mb_path / "time_source" / "output") - .add_coerced_subscriber([this, &mb](const bool time_output){ + .add_coerced_subscriber([this, &mb](const bool time_output) { this->set_time_source_out(mb, time_output); }) - .set(true) - ; + .set(true); //////////////////////////////////////////////////////////////////// // setup clock sources and properties //////////////////////////////////////////////////////////////////// _tree->create<std::string>(mb_path / "clock_source" / "value") .set(mb.args.get_clock_source()) - .add_coerced_subscriber([this, &mb](const std::string& clock_source){ + .add_coerced_subscriber([this, &mb](const std::string& clock_source) { this->update_clock_source(mb, clock_source); - }) - ; - static const std::vector<std::string> clock_source_options = - {"internal", "external", "gpsdo"}; + }); + static const std::vector<std::string> clock_source_options = { + "internal", "external", "gpsdo"}; _tree->create<std::vector<std::string>>(mb_path / "clock_source" / "options") .set(clock_source_options); - //setup external reference options. default to 10 MHz input reference + // setup external reference options. default to 10 MHz input reference _tree->create<std::string>(mb_path / "clock_source" / "external"); - _tree->create<std::vector<double>>(mb_path / "clock_source" / "external" / "freq" / "options") + _tree + ->create<std::vector<double>>( + mb_path / "clock_source" / "external" / "freq" / "options") .set(x300::EXTERNAL_FREQ_OPTIONS); _tree->create<double>(mb_path / "clock_source" / "external" / "value") .set(mb.clock->get_sysref_clock_rate()); // FIXME the external clock source settings need to be more robust - //setup the clock output, default to ON + // setup the clock output, default to ON _tree->create<bool>(mb_path / "clock_source" / "output") - .add_coerced_subscriber([&mb](const bool clock_output){ - mb.clock->set_ref_out(clock_output); - }) - ; + .add_coerced_subscriber( + [&mb](const bool clock_output) { mb.clock->set_ref_out(clock_output); }); // Initialize tick rate (must be done before setting time) // Note: The master tick rate can't be changed at runtime! const double master_clock_rate = mb.clock->get_master_clock_rate(); _tree->create<double>(mb_path / "tick_rate") - .set_coercer([master_clock_rate](const double rate){ + .set_coercer([master_clock_rate](const double rate) { // The contract of multi_usrp::set_master_clock_rate() is to coerce // and not throw, so we'll follow that behaviour here. if (!uhd::math::frequencies_are_equal(rate, master_clock_rate)) { - UHD_LOGGER_WARNING("X300") << - "Cannot update master clock rate! X300 Series does not " - "allow changing the clock rate during runtime." - ; + UHD_LOGGER_WARNING("X300") + << "Cannot update master clock rate! X300 Series does not " + "allow changing the clock rate during runtime."; } return master_clock_rate; }) - .add_coerced_subscriber([this](const double rate){ - this->update_tx_streamers(rate); - }) - .add_coerced_subscriber([this](const double rate){ - this->update_rx_streamers(rate); - }) - .set(master_clock_rate) - ; + .add_coerced_subscriber( + [this](const double rate) { this->update_tx_streamers(rate); }) + .add_coerced_subscriber( + [this](const double rate) { this->update_rx_streamers(rate); }) + .set(master_clock_rate); //////////////////////////////////////////////////////////////////// // and do the misc mboard sensors //////////////////////////////////////////////////////////////////// _tree->create<sensor_value_t>(mb_path / "sensors" / "ref_locked") - .set_publisher([this, &mb](){ return this->get_ref_locked(mb); }); + .set_publisher([this, &mb]() { return this->get_ref_locked(mb); }); //////////////// RFNOC ///////////////// const size_t n_rfnoc_blocks = mb.zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_NUM_CE)); - enumerate_rfnoc_blocks( - mb_i, + enumerate_rfnoc_blocks(mb_i, n_rfnoc_blocks, x300::XB_DST_PCI + 1, /* base port */ uhd::sid_t(x300::SRC_ADDR0, 0, x300::DST_ADDR + mb_i, 0), - dev_addr - ); + dev_addr); //////////////// RFNOC ///////////////// // If we have a radio, we must configure its codec control: const std::string radio_blockid_hint = str(boost::format("%d/Radio") % mb_i); std::vector<rfnoc::block_id_t> radio_ids = - find_blocks<rfnoc::x300_radio_ctrl_impl>(radio_blockid_hint); + find_blocks<rfnoc::x300_radio_ctrl_impl>(radio_blockid_hint); if (not radio_ids.empty()) { if (radio_ids.size() > 2) { UHD_LOGGER_WARNING("X300") @@ -1147,33 +1147,31 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) radio_ids.resize(2); } - for(const rfnoc::block_id_t &id: radio_ids) { - rfnoc::x300_radio_ctrl_impl::sptr radio(get_block_ctrl<rfnoc::x300_radio_ctrl_impl>(id)); + for (const rfnoc::block_id_t& id : radio_ids) { + rfnoc::x300_radio_ctrl_impl::sptr radio( + get_block_ctrl<rfnoc::x300_radio_ctrl_impl>(id)); mb.radios.push_back(radio); - radio->setup_radio( - mb.zpu_i2c, - mb.clock, - mb.args.get_ignore_cal_file(), - mb.args.get_self_cal_adc_delay() - ); + radio->setup_radio(mb.zpu_i2c, + mb.clock, + mb.args.get_ignore_cal_file(), + mb.args.get_self_cal_adc_delay()); } //////////////////////////////////////////////////////////////////// // ADC test and cal //////////////////////////////////////////////////////////////////// if (mb.args.get_self_cal_adc_delay()) { - rfnoc::x300_radio_ctrl_impl::self_cal_adc_xfer_delay( - mb.radios, mb.clock, - [this, &mb](const double timeout){ - return this->wait_for_clk_locked(mb, fw_regmap_t::clk_status_reg_t::LMK_LOCK, timeout); + rfnoc::x300_radio_ctrl_impl::self_cal_adc_xfer_delay(mb.radios, + mb.clock, + [this, &mb](const double timeout) { + return this->wait_for_clk_locked( + mb, fw_regmap_t::clk_status_reg_t::LMK_LOCK, timeout); }, true /* Apply ADC delay */); } if (mb.args.get_ext_adc_self_test()) { rfnoc::x300_radio_ctrl_impl::extended_adc_test( - mb.radios, - mb.args.get_ext_adc_self_test_duration() - ); + mb.radios, mb.args.get_ext_adc_self_test_duration()); } else { for (size_t i = 0; i < mb.radios.size(); i++) { mb.radios.at(i)->self_test_adc(); @@ -1188,8 +1186,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) } } else { - UHD_LOGGER_INFO("X300") - << "No Radio Block found. Assuming radio-less operation."; + UHD_LOGGER_INFO("X300") << "No Radio Block found. Assuming radio-less operation."; } /* end of radio block(s) initialization */ mb.initialization_done = true; @@ -1197,30 +1194,27 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) x300_impl::~x300_impl(void) { - try - { - for(mboard_members_t &mb: _mb) - { - //kill the claimer task and unclaim the device + try { + for (mboard_members_t& mb : _mb) { + // kill the claimer task and unclaim the device mb.claimer_task.reset(); - { //Critical section + { // Critical section boost::mutex::scoped_lock lock(pcie_zpu_iface_registry_mutex); release(mb.zpu_ctrl); - //If the process is killed, the entire registry will disappear so we - //don't need to worry about unclean shutdowns here. + // If the process is killed, the entire registry will disappear so we + // don't need to worry about unclean shutdowns here. if (get_pcie_zpu_iface_registry().has_key(mb.get_pri_eth().addr)) { get_pcie_zpu_iface_registry().pop(mb.get_pri_eth().addr); } } } - } - catch(...) - { + } catch (...) { UHD_SAFE_CALL(throw;) } } -uint32_t x300_impl::mboard_members_t::allocate_pcie_dma_chan(const uhd::sid_t &tx_sid, const xport_type_t xport_type) +uint32_t x300_impl::mboard_members_t::allocate_pcie_dma_chan( + const uhd::sid_t& tx_sid, const xport_type_t xport_type) { static const uint32_t CTRL_CHANNEL = 0; static const uint32_t ASYNC_MSG_CHANNEL = 1; @@ -1236,28 +1230,29 @@ uint32_t x300_impl::mboard_members_t::allocate_pcie_dma_chan(const uhd::sid_t &t if (_dma_chan_pool.count(raw_sid) == 0) { size_t channel = _dma_chan_pool.size() + FIRST_DATA_CHANNEL; if (channel > x300::PCIE_MAX_CHANNELS) { - throw uhd::runtime_error("Trying to allocate more DMA channels than are available"); + throw uhd::runtime_error( + "Trying to allocate more DMA channels than are available"); } _dma_chan_pool[raw_sid] = channel; UHD_LOGGER_DEBUG("X300") - << "Assigning PCIe DMA channel " << _dma_chan_pool[raw_sid] - << " to SID " << tx_sid.to_pp_string_hex(); + << "Assigning PCIe DMA channel " << _dma_chan_pool[raw_sid] << " to SID " + << tx_sid.to_pp_string_hex(); } return _dma_chan_pool[raw_sid]; } } -static uint32_t extract_sid_from_pkt(void* pkt, size_t) { +static uint32_t extract_sid_from_pkt(void* pkt, size_t) +{ return uhd::sid_t(uhd::wtohx(static_cast<const uint32_t*>(pkt)[1])).get_dst(); } -static uhd::transport::muxed_zero_copy_if::sptr make_muxed_pcie_msg_xport -( +static uhd::transport::muxed_zero_copy_if::sptr make_muxed_pcie_msg_xport( uhd::niusrprio::niusrprio_session::sptr rio_fpga_interface, uint32_t dma_channel_num, - size_t max_muxed_ports -) { + size_t max_muxed_ports) +{ zero_copy_xport_params buff_args; buff_args.send_frame_size = x300::PCIE_MSG_FRAME_SIZE; buff_args.recv_frame_size = x300::PCIE_MSG_FRAME_SIZE; @@ -1265,77 +1260,70 @@ static uhd::transport::muxed_zero_copy_if::sptr make_muxed_pcie_msg_xport buff_args.num_recv_frames = x300::PCIE_MSG_NUM_FRAMES * max_muxed_ports; zero_copy_if::sptr base_xport = nirio_zero_copy::make( - rio_fpga_interface, dma_channel_num, - buff_args, uhd::device_addr_t()); + rio_fpga_interface, dma_channel_num, buff_args, uhd::device_addr_t()); return muxed_zero_copy_if::make(base_xport, extract_sid_from_pkt, max_muxed_ports); } -uhd::both_xports_t x300_impl::make_transport( - const uhd::sid_t &address, +uhd::both_xports_t x300_impl::make_transport(const uhd::sid_t& address, const xport_type_t xport_type, - const uhd::device_addr_t& args -) { - const size_t mb_index = address.get_dst_addr() - x300::DST_ADDR; - mboard_members_t &mb = _mb[mb_index]; - const uhd::device_addr_t& xport_args = (xport_type == CTRL) ? uhd::device_addr_t() : args; + const uhd::device_addr_t& args) +{ + const size_t mb_index = address.get_dst_addr() - x300::DST_ADDR; + mboard_members_t& mb = _mb[mb_index]; + const uhd::device_addr_t& xport_args = (xport_type == CTRL) ? uhd::device_addr_t() + : args; zero_copy_xport_params default_buff_args; both_xports_t xports; xports.endianness = mb.if_pkt_is_big_endian ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; if (mb.xport_path == "nirio") { - xports.send_sid = this->allocate_sid(mb, address, x300::SRC_ADDR0, x300::XB_DST_PCI); + xports.send_sid = + this->allocate_sid(mb, address, x300::SRC_ADDR0, x300::XB_DST_PCI); xports.recv_sid = xports.send_sid.reversed(); uint32_t dma_channel_num = mb.allocate_pcie_dma_chan(xports.send_sid, xport_type); if (xport_type == CTRL) { - //Transport for control stream + // Transport for control stream if (not mb.ctrl_dma_xport) { - //One underlying DMA channel will handle - //all control traffic - mb.ctrl_dma_xport = make_muxed_pcie_msg_xport( - mb.rio_fpga_interface, + // One underlying DMA channel will handle + // all control traffic + mb.ctrl_dma_xport = make_muxed_pcie_msg_xport(mb.rio_fpga_interface, dma_channel_num, x300::PCIE_MAX_MUXED_CTRL_XPORTS); } - //Create a virtual control transport + // Create a virtual control transport xports.recv = mb.ctrl_dma_xport->make_stream(xports.recv_sid.get_dst()); } else if (xport_type == ASYNC_MSG) { - //Transport for async message stream + // Transport for async message stream if (not mb.async_msg_dma_xport) { - //One underlying DMA channel will handle - //all async message traffic - mb.async_msg_dma_xport = make_muxed_pcie_msg_xport( - mb.rio_fpga_interface, + // One underlying DMA channel will handle + // all async message traffic + mb.async_msg_dma_xport = make_muxed_pcie_msg_xport(mb.rio_fpga_interface, dma_channel_num, x300::PCIE_MAX_MUXED_ASYNC_XPORTS); } - //Create a virtual async message transport + // Create a virtual async message transport xports.recv = mb.async_msg_dma_xport->make_stream(xports.recv_sid.get_dst()); } else { - //Transport for data stream - default_buff_args.send_frame_size = - (xport_type == TX_DATA) - ? x300::PCIE_TX_DATA_FRAME_SIZE - : x300::PCIE_MSG_FRAME_SIZE; - - default_buff_args.recv_frame_size = - (xport_type == RX_DATA) - ? x300::PCIE_RX_DATA_FRAME_SIZE - : x300::PCIE_MSG_FRAME_SIZE; - - default_buff_args.num_send_frames = - (xport_type == TX_DATA) - ? x300::PCIE_TX_DATA_NUM_FRAMES - : x300::PCIE_MSG_NUM_FRAMES; + // Transport for data stream + default_buff_args.send_frame_size = (xport_type == TX_DATA) + ? x300::PCIE_TX_DATA_FRAME_SIZE + : x300::PCIE_MSG_FRAME_SIZE; - default_buff_args.num_recv_frames = - (xport_type == RX_DATA) - ? x300::PCIE_RX_DATA_NUM_FRAMES - : x300::PCIE_MSG_NUM_FRAMES; + default_buff_args.recv_frame_size = (xport_type == RX_DATA) + ? x300::PCIE_RX_DATA_FRAME_SIZE + : x300::PCIE_MSG_FRAME_SIZE; + + default_buff_args.num_send_frames = (xport_type == TX_DATA) + ? x300::PCIE_TX_DATA_NUM_FRAMES + : x300::PCIE_MSG_NUM_FRAMES; + + default_buff_args.num_recv_frames = (xport_type == RX_DATA) + ? x300::PCIE_RX_DATA_NUM_FRAMES + : x300::PCIE_MSG_NUM_FRAMES; xports.recv = nirio_zero_copy::make( - mb.rio_fpga_interface, dma_channel_num, - default_buff_args, xport_args); + mb.rio_fpga_interface, dma_channel_num, default_buff_args, xport_args); } xports.send = xports.recv; @@ -1344,23 +1332,27 @@ uhd::both_xports_t x300_impl::make_transport( // - Upper 16 bits: Destination address (e.g. 0.0) // - Lower 16 bits: DMA channel uint32_t router_config_word = (xports.recv_sid.get_dst() << 16) | dma_channel_num; - mb.rio_fpga_interface->get_kernel_proxy()->poke(PCIE_ROUTER_REG(0), router_config_word); + mb.rio_fpga_interface->get_kernel_proxy()->poke( + PCIE_ROUTER_REG(0), router_config_word); - //For the nirio transport, buffer size is depends on the frame size and num frames - xports.recv_buff_size = xports.recv->get_num_recv_frames() * xports.recv->get_recv_frame_size(); - xports.send_buff_size = xports.send->get_num_send_frames() * xports.send->get_send_frame_size(); + // For the nirio transport, buffer size is depends on the frame size and num + // frames + xports.recv_buff_size = + xports.recv->get_num_recv_frames() * xports.recv->get_recv_frame_size(); + xports.send_buff_size = + xports.send->get_num_send_frames() * xports.send->get_send_frame_size(); } else if (mb.xport_path == "eth") { // Decide on the IP/Interface pair based on the endpoint index - size_t &next_src_addr = - xport_type == TX_DATA ? mb.next_tx_src_addr : - xport_type == RX_DATA ? mb.next_rx_src_addr : - mb.next_src_addr; - x300_eth_conn_t conn = mb.eth_conns[next_src_addr]; - const uint32_t xbar_src_addr = - next_src_addr==0 ? x300::SRC_ADDR0 : x300::SRC_ADDR1; - const uint32_t xbar_src_dst = - conn.type==X300_IFACE_ETH0 ? x300::XB_DST_E0 : x300::XB_DST_E1; + size_t& next_src_addr = xport_type == TX_DATA + ? mb.next_tx_src_addr + : xport_type == RX_DATA ? mb.next_rx_src_addr + : mb.next_src_addr; + x300_eth_conn_t conn = mb.eth_conns[next_src_addr]; + const uint32_t xbar_src_addr = next_src_addr == 0 ? x300::SRC_ADDR0 + : x300::SRC_ADDR1; + const uint32_t xbar_src_dst = conn.type == X300_IFACE_ETH0 ? x300::XB_DST_E0 + : x300::XB_DST_E1; // Do not increment src addr for tx_data by default, using dual ethernet // with the DMA FIFO causes sequence errors to DMA FIFO bandwidth @@ -1373,119 +1365,125 @@ uhd::both_xports_t x300_impl::make_transport( xports.recv_sid = xports.send_sid.reversed(); // Set size and number of frames - size_t system_max_send_frame_size = (size_t) _max_frame_sizes.send_frame_size; - size_t system_max_recv_frame_size = (size_t) _max_frame_sizes.recv_frame_size; - default_buff_args.send_frame_size = std::min(system_max_send_frame_size, x300::ETH_MSG_FRAME_SIZE); - default_buff_args.recv_frame_size = std::min(system_max_recv_frame_size, x300::ETH_MSG_FRAME_SIZE); + size_t system_max_send_frame_size = (size_t)_max_frame_sizes.send_frame_size; + size_t system_max_recv_frame_size = (size_t)_max_frame_sizes.recv_frame_size; + default_buff_args.send_frame_size = + std::min(system_max_send_frame_size, x300::ETH_MSG_FRAME_SIZE); + default_buff_args.recv_frame_size = + std::min(system_max_recv_frame_size, x300::ETH_MSG_FRAME_SIZE); default_buff_args.send_buff_size = conn.link_rate / 50; // 20ms - default_buff_args.recv_buff_size = std::max(conn.link_rate / 50, x300::ETH_MSG_NUM_FRAMES * x300::ETH_MSG_FRAME_SIZE); // enough to hold greater of 20ms or number of msg frames - if (xport_type == TX_DATA) - { - size_t default_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE ? x300::GE_DATA_FRAME_SEND_SIZE : x300::XGE_DATA_FRAME_SEND_SIZE; - default_buff_args.send_frame_size = args.cast<size_t>("send_frame_size", std::min(default_frame_size, system_max_send_frame_size)); - if (default_buff_args.send_frame_size > system_max_send_frame_size) - { + default_buff_args.recv_buff_size = std::max(conn.link_rate / 50, + x300::ETH_MSG_NUM_FRAMES + * x300::ETH_MSG_FRAME_SIZE); // enough to hold greater of 20ms or number + // of msg frames + if (xport_type == TX_DATA) { + size_t default_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE + ? x300::GE_DATA_FRAME_SEND_SIZE + : x300::XGE_DATA_FRAME_SEND_SIZE; + default_buff_args.send_frame_size = args.cast<size_t>("send_frame_size", + std::min(default_frame_size, system_max_send_frame_size)); + if (default_buff_args.send_frame_size > system_max_send_frame_size) { UHD_LOGGER_WARNING("X300") - << boost::format("Requested send_frame_size of %d exceeds the maximum allowed on the %s connection. Using %d.") - % default_buff_args.send_frame_size - % conn.addr - % system_max_send_frame_size - ; + << boost::format("Requested send_frame_size of %d exceeds the " + "maximum allowed on the %s connection. Using %d.") + % default_buff_args.send_frame_size % conn.addr + % system_max_send_frame_size; default_buff_args.send_frame_size = system_max_send_frame_size; } - } - else if (xport_type == RX_DATA) - { - size_t default_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE ? x300::GE_DATA_FRAME_RECV_SIZE : x300::XGE_DATA_FRAME_RECV_SIZE; - default_buff_args.recv_frame_size = args.cast<size_t>("recv_frame_size", std::min(default_frame_size, system_max_recv_frame_size)); - if (default_buff_args.recv_frame_size > system_max_recv_frame_size) - { + } else if (xport_type == RX_DATA) { + size_t default_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE + ? x300::GE_DATA_FRAME_RECV_SIZE + : x300::XGE_DATA_FRAME_RECV_SIZE; + default_buff_args.recv_frame_size = args.cast<size_t>("recv_frame_size", + std::min(default_frame_size, system_max_recv_frame_size)); + if (default_buff_args.recv_frame_size > system_max_recv_frame_size) { UHD_LOGGER_WARNING("X300") - << boost::format("Requested recv_frame_size of %d exceeds the maximum allowed on the %s connection. Using %d.") - % default_buff_args.recv_frame_size - % conn.addr - % system_max_recv_frame_size - ; + << boost::format("Requested recv_frame_size of %d exceeds the " + "maximum allowed on the %s connection. Using %d.") + % default_buff_args.recv_frame_size % conn.addr + % system_max_recv_frame_size; default_buff_args.recv_frame_size = system_max_recv_frame_size; } - default_buff_args.num_recv_frames = 2; // set some buffers so the offload thread actually offloads the socket I/O + default_buff_args.num_recv_frames = + 2; // set some buffers so the offload thread actually offloads the socket + // I/O } - //make a new transport - fpga has no idea how to talk to us on this yet + // make a new transport - fpga has no idea how to talk to us on this yet udp_zero_copy::buff_params buff_params; - xports.recv = udp_zero_copy::make( - conn.addr, - BOOST_STRINGIZE(X300_VITA_UDP_PORT), - default_buff_args, - buff_params, - xport_args); + xports.recv = udp_zero_copy::make(conn.addr, + BOOST_STRINGIZE(X300_VITA_UDP_PORT), + default_buff_args, + buff_params, + xport_args); // Create a threaded transport for the receive chain only // Note that this shouldn't affect PCIe if (xport_type == RX_DATA) { xports.recv = zero_copy_recv_offload::make( - xports.recv, - x300::RECV_OFFLOAD_BUFFER_TIMEOUT - ); + xports.recv, x300::RECV_OFFLOAD_BUFFER_TIMEOUT); } xports.send = xports.recv; - //For the UDP transport the buffer size is the size of the socket buffer - //in the kernel + // For the UDP transport the buffer size is the size of the socket buffer + // in the kernel xports.recv_buff_size = buff_params.recv_buff_size; xports.send_buff_size = buff_params.send_buff_size; - //clear the ethernet dispatcher's udp port - //NOT clearing this, the dispatcher is now intelligent + // clear the ethernet dispatcher's udp port + // NOT clearing this, the dispatcher is now intelligent //_zpu_ctrl->poke32(SR_ADDR(SET0_BASE, (ZPU_SR_ETHINT0+8+3)), 0); - //send a mini packet with SID into the ZPU - //ZPU will reprogram the ethernet framer - UHD_LOGGER_DEBUG("X300") << "programming packet for new xport on " - << conn.addr << " sid " << xports.send_sid ; - //YES, get a __send__ buffer from the __recv__ socket + // send a mini packet with SID into the ZPU + // ZPU will reprogram the ethernet framer + UHD_LOGGER_DEBUG("X300") << "programming packet for new xport on " << conn.addr + << " sid " << xports.send_sid; + // YES, get a __send__ buffer from the __recv__ socket //-- this is the only way to program the framer for recv: managed_send_buffer::sptr buff = xports.recv->get_send_buff(); - buff->cast<uint32_t *>()[0] = 0; //eth dispatch looks for != 0 - buff->cast<uint32_t *>()[1] = uhd::htonx(xports.send_sid.get()); + buff->cast<uint32_t*>()[0] = 0; // eth dispatch looks for != 0 + buff->cast<uint32_t*>()[1] = uhd::htonx(xports.send_sid.get()); buff->commit(8); buff.reset(); - //reprogram the ethernet dispatcher's udp port (should be safe to always set) - UHD_LOGGER_TRACE("X300") - << "reprogram the ethernet dispatcher's udp port" ; - mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, (ZPU_SR_ETHINT0+8+3)), X300_VITA_UDP_PORT); - mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, (ZPU_SR_ETHINT1+8+3)), X300_VITA_UDP_PORT); + // reprogram the ethernet dispatcher's udp port (should be safe to always set) + UHD_LOGGER_TRACE("X300") << "reprogram the ethernet dispatcher's udp port"; + mb.zpu_ctrl->poke32( + SR_ADDR(SET0_BASE, (ZPU_SR_ETHINT0 + 8 + 3)), X300_VITA_UDP_PORT); + mb.zpu_ctrl->poke32( + SR_ADDR(SET0_BASE, (ZPU_SR_ETHINT1 + 8 + 3)), X300_VITA_UDP_PORT); - //Do a peek to an arbitrary address to guarantee that the - //ethernet framer has been programmed before we return. + // Do a peek to an arbitrary address to guarantee that the + // ethernet framer has been programmed before we return. mb.zpu_ctrl->peek32(0); } return xports; } -uhd::sid_t x300_impl::allocate_sid( - mboard_members_t &mb, - const uhd::sid_t &address, - const uint32_t src_addr, - const uint32_t src_dst -) { +uhd::sid_t x300_impl::allocate_sid(mboard_members_t& mb, + const uhd::sid_t& address, + const uint32_t src_addr, + const uint32_t src_dst) +{ uhd::sid_t sid = address; sid.set_src_addr(src_addr); - sid.set_src_endpoint(_sid_framer++); //increment for next setup + sid.set_src_endpoint(_sid_framer++); // increment for next setup // TODO Move all of this setup_mb() // Program the X300 to recognise it's own local address. mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_XB_LOCAL), address.get_dst_addr()); - // Program CAM entry for outgoing packets matching a X300 resource (for example a Radio) - // This type of packet matches the XB_LOCAL address and is looked up in the upper half of the CAM - mb.zpu_ctrl->poke32(SR_ADDR(SETXB_BASE, 256 + address.get_dst_endpoint()), address.get_dst_xbarport()); + // Program CAM entry for outgoing packets matching a X300 resource (for example a + // Radio) This type of packet matches the XB_LOCAL address and is looked up in the + // upper half of the CAM + mb.zpu_ctrl->poke32(SR_ADDR(SETXB_BASE, 256 + address.get_dst_endpoint()), + address.get_dst_xbarport()); // Program CAM entry for returning packets to us (for example GR host via Eth0) - // This type of packet does not match the XB_LOCAL address and is looked up in the lower half of the CAM + // This type of packet does not match the XB_LOCAL address and is looked up in the + // lower half of the CAM mb.zpu_ctrl->poke32(SR_ADDR(SETXB_BASE, 0 + src_addr), src_dst); - UHD_LOGGER_TRACE("X300") << "done router config for sid " << sid ; + UHD_LOGGER_TRACE("X300") << "done router config for sid " << sid; return sid; } @@ -1493,95 +1491,123 @@ uhd::sid_t x300_impl::allocate_sid( /*********************************************************************** * clock and time control logic **********************************************************************/ -void x300_impl::set_time_source_out(mboard_members_t &mb, const bool enb) +void x300_impl::set_time_source_out(mboard_members_t& mb, const bool enb) { - mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_OUT_EN, enb?1:0); + mb.fw_regmap->clock_ctrl_reg.write( + fw_regmap_t::clk_ctrl_reg_t::PPS_OUT_EN, enb ? 1 : 0); } -void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &source) +void x300_impl::update_clock_source(mboard_members_t& mb, const std::string& source) { - //Optimize for the case when the current source is internal and we are trying - //to set it to internal. This is the only case where we are guaranteed that - //the clock has not gone away so we can skip setting the MUX and reseting the LMK. - const bool reconfigure_clks = (mb.current_refclk_src != "internal") or (source != "internal"); + // Optimize for the case when the current source is internal and we are trying + // to set it to internal. This is the only case where we are guaranteed that + // the clock has not gone away so we can skip setting the MUX and reseting the LMK. + const bool reconfigure_clks = (mb.current_refclk_src != "internal") + or (source != "internal"); if (reconfigure_clks) { - //Update the clock MUX on the motherboard to select the requested source + // Update the clock MUX on the motherboard to select the requested source if (source == "internal") { - mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, fw_regmap_t::clk_ctrl_reg_t::SRC_INTERNAL); + mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, + fw_regmap_t::clk_ctrl_reg_t::SRC_INTERNAL); mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::TCXO_EN, 1); } else if (source == "external") { - mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, fw_regmap_t::clk_ctrl_reg_t::SRC_EXTERNAL); + mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, + fw_regmap_t::clk_ctrl_reg_t::SRC_EXTERNAL); mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::TCXO_EN, 0); } else if (source == "gpsdo") { - mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, fw_regmap_t::clk_ctrl_reg_t::SRC_GPSDO); + mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, + fw_regmap_t::clk_ctrl_reg_t::SRC_GPSDO); mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::TCXO_EN, 0); } else { throw uhd::key_error("update_clock_source: unknown source: " + source); } mb.fw_regmap->clock_ctrl_reg.flush(); - //Reset the LMK to make sure it re-locks to the new reference + // Reset the LMK to make sure it re-locks to the new reference mb.clock->reset_clocks(); } - //Wait for the LMK to lock (always, as a sanity check that the clock is useable) - //* Currently the LMK can take as long as 30 seconds to lock to a reference but we don't + // Wait for the LMK to lock (always, as a sanity check that the clock is useable) + //* Currently the LMK can take as long as 30 seconds to lock to a reference but we + // don't //* want to wait that long during initialization. - //TODO: Need to verify timeout and settings to make sure lock can be achieved in < 1.0 seconds + // TODO: Need to verify timeout and settings to make sure lock can be achieved in + // < 1.0 seconds double timeout = mb.initialization_done ? 30.0 : 1.0; - //The programming code in x300_clock_ctrl is not compatible with revs <= 4 and may - //lead to locking issues. So, disable the ref-locked check for older (unsupported) boards. + // The programming code in x300_clock_ctrl is not compatible with revs <= 4 and may + // lead to locking issues. So, disable the ref-locked check for older (unsupported) + // boards. if (mb.hw_rev > 4) { - if (not wait_for_clk_locked(mb, fw_regmap_t::clk_status_reg_t::LMK_LOCK, timeout)) { - //failed to lock on reference + if (not wait_for_clk_locked( + mb, fw_regmap_t::clk_status_reg_t::LMK_LOCK, timeout)) { + // failed to lock on reference if (mb.initialization_done) { - throw uhd::runtime_error((boost::format("Reference Clock PLL failed to lock to %s source.") % source).str()); + throw uhd::runtime_error( + (boost::format("Reference Clock PLL failed to lock to %s source.") + % source) + .str()); } else { - //TODO: Re-enable this warning when we figure out a reliable lock time - //UHD_LOGGER_WARNING("X300") << "Reference clock failed to lock to " + source + " during device initialization. " << - // "Check for the lock before operation or ignore this warning if using another clock source." ; + // TODO: Re-enable this warning when we figure out a reliable lock time + // UHD_LOGGER_WARNING("X300") << "Reference clock failed to lock to " + + // source + " during device initialization. " << + // "Check for the lock before operation or ignore this warning if using + // another clock source." ; } } } if (reconfigure_clks) { - //Reset the radio clock PLL in the FPGA - mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_SW_RST), ZPU_SR_SW_RST_RADIO_CLK_PLL); + // Reset the radio clock PLL in the FPGA + mb.zpu_ctrl->poke32( + SR_ADDR(SET0_BASE, ZPU_SR_SW_RST), ZPU_SR_SW_RST_RADIO_CLK_PLL); mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_SW_RST), 0); - //Wait for radio clock PLL to lock - if (not wait_for_clk_locked(mb, fw_regmap_t::clk_status_reg_t::RADIO_CLK_LOCK, 0.01)) { - throw uhd::runtime_error((boost::format("Reference Clock PLL in FPGA failed to lock to %s source.") % source).str()); + // Wait for radio clock PLL to lock + if (not wait_for_clk_locked( + mb, fw_regmap_t::clk_status_reg_t::RADIO_CLK_LOCK, 0.01)) { + throw uhd::runtime_error( + (boost::format("Reference Clock PLL in FPGA failed to lock to %s source.") + % source) + .str()); } - //Reset the IDELAYCTRL used to calibrate the data interface delays - mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_SW_RST), ZPU_SR_SW_RST_ADC_IDELAYCTRL); + // Reset the IDELAYCTRL used to calibrate the data interface delays + mb.zpu_ctrl->poke32( + SR_ADDR(SET0_BASE, ZPU_SR_SW_RST), ZPU_SR_SW_RST_ADC_IDELAYCTRL); mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_SW_RST), 0); - //Wait for the ADC IDELAYCTRL to be ready - if (not wait_for_clk_locked(mb, fw_regmap_t::clk_status_reg_t::IDELAYCTRL_LOCK, 0.01)) { - throw uhd::runtime_error((boost::format("ADC Calibration Clock in FPGA failed to lock to %s source.") % source).str()); + // Wait for the ADC IDELAYCTRL to be ready + if (not wait_for_clk_locked( + mb, fw_regmap_t::clk_status_reg_t::IDELAYCTRL_LOCK, 0.01)) { + throw uhd::runtime_error( + (boost::format( + "ADC Calibration Clock in FPGA failed to lock to %s source.") + % source) + .str()); } // Reset ADCs and DACs - for(rfnoc::x300_radio_ctrl_impl::sptr r: mb.radios) { + for (rfnoc::x300_radio_ctrl_impl::sptr r : mb.radios) { r->reset_codec(); } } - //Update cache value + // Update cache value mb.current_refclk_src = source; } -void x300_impl::update_time_source(mboard_members_t &mb, const std::string &source) +void x300_impl::update_time_source(mboard_members_t& mb, const std::string& source) { if (source == "internal") { - mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, fw_regmap_t::clk_ctrl_reg_t::SRC_INTERNAL); + mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, + fw_regmap_t::clk_ctrl_reg_t::SRC_INTERNAL); } else if (source == "external") { - mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, fw_regmap_t::clk_ctrl_reg_t::SRC_EXTERNAL); + mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, + fw_regmap_t::clk_ctrl_reg_t::SRC_EXTERNAL); } else if (source == "gpsdo") { - mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, fw_regmap_t::clk_ctrl_reg_t::SRC_GPSDO); + mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, + fw_regmap_t::clk_ctrl_reg_t::SRC_GPSDO); } else { throw uhd::key_error("update_time_source: unknown source: " + source); } @@ -1589,15 +1615,17 @@ void x300_impl::update_time_source(mboard_members_t &mb, const std::string &sour /* TODO - Implement intelligent PPS detection //check for valid pps if (!is_pps_present(mb)) { - throw uhd::runtime_error((boost::format("The %d PPS was not detected. Please check the PPS source and try again.") % source).str()); + throw uhd::runtime_error((boost::format("The %d PPS was not detected. Please + check the PPS source and try again.") % source).str()); } */ } -void x300_impl::sync_times(mboard_members_t &mb, const uhd::time_spec_t& t) +void x300_impl::sync_times(mboard_members_t& mb, const uhd::time_spec_t& t) { - std::vector<rfnoc::block_id_t> radio_ids = find_blocks<rfnoc::x300_radio_ctrl_impl>("Radio"); - for(const rfnoc::block_id_t &id: radio_ids) { + std::vector<rfnoc::block_id_t> radio_ids = + find_blocks<rfnoc::x300_radio_ctrl_impl>("Radio"); + for (const rfnoc::block_id_t& id : radio_ids) { get_block_ctrl<rfnoc::x300_radio_ctrl_impl>(id)->set_time_sync(t); } @@ -1608,9 +1636,8 @@ void x300_impl::sync_times(mboard_members_t &mb, const uhd::time_spec_t& t) bool x300_impl::wait_for_clk_locked(mboard_members_t& mb, uint32_t which, double timeout) { - const auto timeout_time = - std::chrono::steady_clock::now() - + std::chrono::milliseconds(int64_t(timeout * 1000)); + const auto timeout_time = std::chrono::steady_clock::now() + + std::chrono::milliseconds(int64_t(timeout * 1000)); do { if (mb.fw_regmap->clock_status_reg.read(which) == 1) { return true; @@ -1618,16 +1645,21 @@ bool x300_impl::wait_for_clk_locked(mboard_members_t& mb, uint32_t which, double std::this_thread::sleep_for(std::chrono::milliseconds(1)); } while (std::chrono::steady_clock::now() < timeout_time); - //Check one last time - return (mb.fw_regmap->clock_status_reg.read(which)==1); + // Check one last time + return (mb.fw_regmap->clock_status_reg.read(which) == 1); } sensor_value_t x300_impl::get_ref_locked(mboard_members_t& mb) { mb.fw_regmap->clock_status_reg.refresh(); - const bool lock = (mb.fw_regmap->clock_status_reg.get(fw_regmap_t::clk_status_reg_t::LMK_LOCK)==1) && - (mb.fw_regmap->clock_status_reg.get(fw_regmap_t::clk_status_reg_t::RADIO_CLK_LOCK)==1) && - (mb.fw_regmap->clock_status_reg.get(fw_regmap_t::clk_status_reg_t::IDELAYCTRL_LOCK)==1); + const bool lock = + (mb.fw_regmap->clock_status_reg.get(fw_regmap_t::clk_status_reg_t::LMK_LOCK) == 1) + && (mb.fw_regmap->clock_status_reg.get( + fw_regmap_t::clk_status_reg_t::RADIO_CLK_LOCK) + == 1) + && (mb.fw_regmap->clock_status_reg.get( + fw_regmap_t::clk_status_reg_t::IDELAYCTRL_LOCK) + == 1); return sensor_value_t("Ref", lock, "locked", "unlocked"); } @@ -1635,11 +1667,13 @@ bool x300_impl::is_pps_present(mboard_members_t& mb) { // The ZPU_RB_CLK_STATUS_PPS_DETECT bit toggles with each rising edge of the PPS. // We monitor it for up to 1.5 seconds looking for it to toggle. - uint32_t pps_detect = mb.fw_regmap->clock_status_reg.read(fw_regmap_t::clk_status_reg_t::PPS_DETECT); - for (int i = 0; i < 15; i++) - { + uint32_t pps_detect = + mb.fw_regmap->clock_status_reg.read(fw_regmap_t::clk_status_reg_t::PPS_DETECT); + for (int i = 0; i < 15; i++) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); - if (pps_detect != mb.fw_regmap->clock_status_reg.read(fw_regmap_t::clk_status_reg_t::PPS_DETECT)) + if (pps_detect + != mb.fw_regmap->clock_status_reg.read( + fw_regmap_t::clk_status_reg_t::PPS_DETECT)) return true; } return false; @@ -1658,22 +1692,18 @@ void x300_impl::claimer_loop(wb_iface::sptr iface) x300_impl::claim_status_t x300_impl::claim_status(wb_iface::sptr iface) { claim_status_t claim_status = CLAIMED_BY_OTHER; // Default to most restrictive - auto timeout_time = - std::chrono::steady_clock::now() - + std::chrono::seconds(1); - while (std::chrono::steady_clock::now() < timeout_time) - { - //If timed out, then device is definitely unclaimed - if (iface->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_STATUS)) == 0) - { + auto timeout_time = std::chrono::steady_clock::now() + std::chrono::seconds(1); + while (std::chrono::steady_clock::now() < timeout_time) { + // If timed out, then device is definitely unclaimed + if (iface->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_STATUS)) == 0) { claim_status = UNCLAIMED; break; } - //otherwise check claim src to determine if another thread with the same src has claimed the device + // otherwise check claim src to determine if another thread with the same src has + // claimed the device uint32_t hash = iface->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_SRC)); - if (hash == 0) - { + if (hash == 0) { // A non-zero claim status and an empty hash means the claim might // be in the process of being released. This is possible because // older firmware takes a long time to update the status. Wait and @@ -1696,20 +1726,17 @@ void x300_impl::claim(wb_iface::sptr iface) bool x300_impl::try_to_claim(wb_iface::sptr iface, long timeout_ms) { const auto timeout_time = - std::chrono::steady_clock::now() - + std::chrono::milliseconds(timeout_ms); - while (1) - { + std::chrono::steady_clock::now() + std::chrono::milliseconds(timeout_ms); + while (1) { claim_status_t status = claim_status(iface); - if (status == UNCLAIMED) - { + if (status == UNCLAIMED) { claim(iface); - // It takes the claimer 10ms to update status, so wait 20ms before verifying claim + // It takes the claimer 10ms to update status, so wait 20ms before verifying + // claim std::this_thread::sleep_for(std::chrono::milliseconds(20)); continue; } - if (status == CLAIMED_BY_US) - { + if (status == CLAIMED_BY_US) { break; } if (std::chrono::steady_clock::now() > timeout_time) { @@ -1730,57 +1757,62 @@ void x300_impl::release(wb_iface::sptr iface) /*********************************************************************** * Frame size detection **********************************************************************/ -x300_impl::frame_size_t x300_impl::determine_max_frame_size(const std::string &addr, - const frame_size_t &user_frame_size) +x300_impl::frame_size_t x300_impl::determine_max_frame_size( + const std::string& addr, const frame_size_t& user_frame_size) { - udp_simple::sptr udp = udp_simple::make_connected(addr, - BOOST_STRINGIZE(X300_MTU_DETECT_UDP_PORT)); + udp_simple::sptr udp = + udp_simple::make_connected(addr, BOOST_STRINGIZE(X300_MTU_DETECT_UDP_PORT)); - std::vector<uint8_t> buffer(std::max(user_frame_size.recv_frame_size, user_frame_size.send_frame_size)); - x300_mtu_t *request = reinterpret_cast<x300_mtu_t *>(&buffer.front()); - static const double echo_timeout = 0.020; //20 ms + std::vector<uint8_t> buffer( + std::max(user_frame_size.recv_frame_size, user_frame_size.send_frame_size)); + x300_mtu_t* request = reinterpret_cast<x300_mtu_t*>(&buffer.front()); + static const double echo_timeout = 0.020; // 20 ms - //test holler - check if its supported in this fw version + // test holler - check if its supported in this fw version request->flags = uhd::htonx<uint32_t>(X300_MTU_DETECT_ECHO_REQUEST); - request->size = uhd::htonx<uint32_t>(sizeof(x300_mtu_t)); + request->size = uhd::htonx<uint32_t>(sizeof(x300_mtu_t)); udp->send(boost::asio::buffer(buffer, sizeof(x300_mtu_t))); udp->recv(boost::asio::buffer(buffer), echo_timeout); if (!(uhd::ntohx<uint32_t>(request->flags) & X300_MTU_DETECT_ECHO_REPLY)) throw uhd::not_implemented_error("Holler protocol not implemented"); - //Reducing range of (min,max) by setting max value to 10gig max_frame_size as larger sizes are not supported + // Reducing range of (min,max) by setting max value to 10gig max_frame_size as larger + // sizes are not supported size_t min_recv_frame_size = sizeof(x300_mtu_t); - size_t max_recv_frame_size = std::min(user_frame_size.recv_frame_size, x300::DATA_FRAME_MAX_SIZE) & size_t(~3); + size_t max_recv_frame_size = + std::min(user_frame_size.recv_frame_size, x300::DATA_FRAME_MAX_SIZE) & size_t(~3); size_t min_send_frame_size = sizeof(x300_mtu_t); - size_t max_send_frame_size = std::min(user_frame_size.send_frame_size, x300::DATA_FRAME_MAX_SIZE) & size_t(~3); + size_t max_send_frame_size = + std::min(user_frame_size.send_frame_size, x300::DATA_FRAME_MAX_SIZE) & size_t(~3); UHD_LOGGER_DEBUG("X300") << "Determining maximum frame size... "; - while (min_recv_frame_size < max_recv_frame_size) - { - size_t test_frame_size = (max_recv_frame_size/2 + min_recv_frame_size/2 + 3) & ~3; + while (min_recv_frame_size < max_recv_frame_size) { + size_t test_frame_size = (max_recv_frame_size / 2 + min_recv_frame_size / 2 + 3) + & ~3; - request->flags = uhd::htonx<uint32_t>(X300_MTU_DETECT_ECHO_REQUEST); - request->size = uhd::htonx<uint32_t>(test_frame_size); - udp->send(boost::asio::buffer(buffer, sizeof(x300_mtu_t))); + request->flags = uhd::htonx<uint32_t>(X300_MTU_DETECT_ECHO_REQUEST); + request->size = uhd::htonx<uint32_t>(test_frame_size); + udp->send(boost::asio::buffer(buffer, sizeof(x300_mtu_t))); - size_t len = udp->recv(boost::asio::buffer(buffer), echo_timeout); + size_t len = udp->recv(boost::asio::buffer(buffer), echo_timeout); - if (len >= test_frame_size) - min_recv_frame_size = test_frame_size; - else - max_recv_frame_size = test_frame_size - 4; + if (len >= test_frame_size) + min_recv_frame_size = test_frame_size; + else + max_recv_frame_size = test_frame_size - 4; } - if(min_recv_frame_size < IP_PROTOCOL_MIN_MTU_SIZE-IP_PROTOCOL_UDP_PLUS_IP_HEADER) { - throw uhd::runtime_error("System receive MTU size is less than the minimum required by the IP protocol."); + if (min_recv_frame_size < IP_PROTOCOL_MIN_MTU_SIZE - IP_PROTOCOL_UDP_PLUS_IP_HEADER) { + throw uhd::runtime_error("System receive MTU size is less than the minimum " + "required by the IP protocol."); } - while (min_send_frame_size < max_send_frame_size) - { - size_t test_frame_size = (max_send_frame_size/2 + min_send_frame_size/2 + 3) & ~3; + while (min_send_frame_size < max_send_frame_size) { + size_t test_frame_size = (max_send_frame_size / 2 + min_send_frame_size / 2 + 3) + & ~3; request->flags = uhd::htonx<uint32_t>(X300_MTU_DETECT_ECHO_REQUEST); - request->size = uhd::htonx<uint32_t>(sizeof(x300_mtu_t)); + request->size = uhd::htonx<uint32_t>(sizeof(x300_mtu_t)); udp->send(boost::asio::buffer(buffer, test_frame_size)); size_t len = udp->recv(boost::asio::buffer(buffer), echo_timeout); @@ -1793,8 +1825,9 @@ x300_impl::frame_size_t x300_impl::determine_max_frame_size(const std::string &a max_send_frame_size = test_frame_size - 4; } - if(min_send_frame_size < IP_PROTOCOL_MIN_MTU_SIZE-IP_PROTOCOL_UDP_PLUS_IP_HEADER) { - throw uhd::runtime_error("System send MTU size is less than the minimum required by the IP protocol."); + if (min_send_frame_size < IP_PROTOCOL_MIN_MTU_SIZE - IP_PROTOCOL_UDP_PLUS_IP_HEADER) { + throw uhd::runtime_error( + "System send MTU size is less than the minimum required by the IP protocol."); } frame_size_t frame_size; @@ -1803,8 +1836,8 @@ x300_impl::frame_size_t x300_impl::determine_max_frame_size(const std::string &a // of the recv and send frame sizes. frame_size.recv_frame_size = std::min(min_recv_frame_size, min_send_frame_size); frame_size.send_frame_size = std::min(min_recv_frame_size, min_send_frame_size); - UHD_LOGGER_INFO("X300") - << "Maximum frame size: " << frame_size.send_frame_size << " bytes."; + UHD_LOGGER_INFO("X300") << "Maximum frame size: " << frame_size.send_frame_size + << " bytes."; return frame_size; } @@ -1812,10 +1845,8 @@ x300_impl::frame_size_t x300_impl::determine_max_frame_size(const std::string &a * compat checks **********************************************************************/ -void x300_impl::check_fw_compat( - const fs_path &mb_path, - const mboard_members_t &members -) { +void x300_impl::check_fw_compat(const fs_path& mb_path, const mboard_members_t& members) +{ auto iface = members.zpu_ctrl; const uint32_t compat_num = iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_COMPAT_NUM)); @@ -1826,78 +1857,75 @@ void x300_impl::check_fw_compat( const std::string image_loader_path = (fs::path(uhd::get_pkg_path()) / "bin" / "uhd_image_loader").string(); const std::string image_loader_cmd = - str(boost::format("\"%s\" --args=\"type=x300,%s=%s\"") - % image_loader_path - % (members.xport_path == "eth" ? "addr" - : "resource") - % members.get_pri_eth().addr); - - throw uhd::runtime_error(str(boost::format( - "Expected firmware compatibility number %d, but got %d:\n" - "The FPGA/firmware image on your device is not compatible with this host code build.\n" - "Download the appropriate FPGA images for this version of UHD.\n" - "%s\n\n" - "Then burn a new image to the on-board flash storage of your\n" - "USRP X3xx device using the image loader utility. " - "Use this command:\n\n%s\n\n" - "For more information, refer to the UHD manual:\n\n" - " http://files.ettus.com/manual/page_usrp_x3x0.html#x3x0_flash" - ) % int(X300_FW_COMPAT_MAJOR) % compat_major - % print_utility_error("uhd_images_downloader.py") - % image_loader_cmd)); + str(boost::format("\"%s\" --args=\"type=x300,%s=%s\"") % image_loader_path + % (members.xport_path == "eth" ? "addr" : "resource") + % members.get_pri_eth().addr); + + throw uhd::runtime_error( + str(boost::format( + "Expected firmware compatibility number %d, but got %d:\n" + "The FPGA/firmware image on your device is not compatible with this " + "host code build.\n" + "Download the appropriate FPGA images for this version of UHD.\n" + "%s\n\n" + "Then burn a new image to the on-board flash storage of your\n" + "USRP X3xx device using the image loader utility. " + "Use this command:\n\n%s\n\n" + "For more information, refer to the UHD manual:\n\n" + " http://files.ettus.com/manual/page_usrp_x3x0.html#x3x0_flash") + % int(X300_FW_COMPAT_MAJOR) % compat_major + % print_utility_error("uhd_images_downloader.py") % image_loader_cmd)); } _tree->create<std::string>(mb_path / "fw_version") .set(str(boost::format("%u.%u") % compat_major % compat_minor)); } -void x300_impl::check_fpga_compat(const fs_path &mb_path, const mboard_members_t &members) +void x300_impl::check_fpga_compat(const fs_path& mb_path, const mboard_members_t& members) { uint32_t compat_num = members.zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_COMPAT_NUM)); uint32_t compat_major = (compat_num >> 16); uint32_t compat_minor = (compat_num & 0xffff); - if (compat_major != X300_FPGA_COMPAT_MAJOR) - { - std::string image_loader_path = (fs::path(uhd::get_pkg_path()) / "bin" / "uhd_image_loader").string(); - std::string image_loader_cmd = str(boost::format("\"%s\" --args=\"type=x300,%s=%s\"") - % image_loader_path - % (members.xport_path == "eth" ? "addr" - : "resource") - % members.get_pri_eth().addr); - - throw uhd::runtime_error(str(boost::format( - "Expected FPGA compatibility number %d, but got %d:\n" - "The FPGA image on your device is not compatible with this host code build.\n" - "Download the appropriate FPGA images for this version of UHD.\n" - "%s\n\n" - "Then burn a new image to the on-board flash storage of your\n" - "USRP X3xx device using the image loader utility. Use this command:\n\n%s\n\n" - "For more information, refer to the UHD manual:\n\n" - " http://files.ettus.com/manual/page_usrp_x3x0.html#x3x0_flash" - ) % int(X300_FPGA_COMPAT_MAJOR) % compat_major - % print_utility_error("uhd_images_downloader.py") - % image_loader_cmd)); + if (compat_major != X300_FPGA_COMPAT_MAJOR) { + std::string image_loader_path = + (fs::path(uhd::get_pkg_path()) / "bin" / "uhd_image_loader").string(); + std::string image_loader_cmd = + str(boost::format("\"%s\" --args=\"type=x300,%s=%s\"") % image_loader_path + % (members.xport_path == "eth" ? "addr" : "resource") + % members.get_pri_eth().addr); + + throw uhd::runtime_error( + str(boost::format( + "Expected FPGA compatibility number %d, but got %d:\n" + "The FPGA image on your device is not compatible with this host code " + "build.\n" + "Download the appropriate FPGA images for this version of UHD.\n" + "%s\n\n" + "Then burn a new image to the on-board flash storage of your\n" + "USRP X3xx device using the image loader utility. Use this " + "command:\n\n%s\n\n" + "For more information, refer to the UHD manual:\n\n" + " http://files.ettus.com/manual/page_usrp_x3x0.html#x3x0_flash") + % int(X300_FPGA_COMPAT_MAJOR) % compat_major + % print_utility_error("uhd_images_downloader.py") % image_loader_cmd)); } - _tree->create<std::string>(mb_path / "fpga_version").set(str(boost::format("%u.%u") - % compat_major % compat_minor)); - - const uint32_t git_hash = members.zpu_ctrl->peek32(SR_ADDR(SET0_BASE, - ZPU_RB_GIT_HASH)); - const std::string git_hash_str = str( - boost::format("%07x%s") - % (git_hash & 0x0FFFFFFF) - % ((git_hash & 0xF0000000) ? "-dirty" : "") - ); + _tree->create<std::string>(mb_path / "fpga_version") + .set(str(boost::format("%u.%u") % compat_major % compat_minor)); + + const uint32_t git_hash = + members.zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_GIT_HASH)); + const std::string git_hash_str = str(boost::format("%07x%s") % (git_hash & 0x0FFFFFFF) + % ((git_hash & 0xF0000000) ? "-dirty" : "")); _tree->create<std::string>(mb_path / "fpga_version_hash").set(git_hash_str); UHD_LOG_DEBUG("X300", "Using FPGA version: " << compat_major << "." << compat_minor - << " git hash: " << git_hash_str); + << " git hash: " << git_hash_str); } x300_impl::x300_mboard_t x300_impl::get_mb_type_from_pcie( - const std::string& resource, const std::string& rpc_port) + const std::string& resource, const std::string& rpc_port) { - //Detect the PCIe product ID to distinguish between X300 and X310 + // Detect the PCIe product ID to distinguish between X300 and X310 nirio_status status = NiRio_Status_Success; uint32_t pid; niriok_proxy::sptr discovery_proxy = @@ -1911,20 +1939,18 @@ x300_impl::x300_mboard_t x300_impl::get_mb_type_from_pcie( } } - UHD_LOGGER_WARNING("X300") << - "NI-RIO Error -- unable to determine motherboard type!"; + UHD_LOGGER_WARNING("X300") << "NI-RIO Error -- unable to determine motherboard type!"; return UNKNOWN; } x300_impl::x300_mboard_t x300_impl::get_mb_type_from_eeprom( - const uhd::usrp::mboard_eeprom_t& mb_eeprom) + const uhd::usrp::mboard_eeprom_t& mb_eeprom) { - if (not mb_eeprom["product"].empty()) - { + if (not mb_eeprom["product"].empty()) { uint16_t product_num = 0; try { product_num = boost::lexical_cast<uint16_t>(mb_eeprom["product"]); - } catch (const boost::bad_lexical_cast &) { + } catch (const boost::bad_lexical_cast&) { product_num = 0; } diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index 9de68a697..c58440d54 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -8,36 +8,34 @@ #ifndef INCLUDED_X300_IMPL_HPP #define INCLUDED_X300_IMPL_HPP -#include "x300_radio_ctrl_impl.hpp" +#include "../device3/device3_impl.hpp" #include "x300_clock_ctrl.hpp" -#include "x300_fw_common.h" -#include "x300_regs.hpp" #include "x300_defaults.hpp" #include "x300_device_args.hpp" - -#include "../device3/device3_impl.hpp" +#include "x300_fw_common.h" +#include "x300_radio_ctrl_impl.hpp" +#include "x300_regs.hpp" #include <uhd/property_tree.hpp> -#include <uhd/usrp/mboard_eeprom.hpp> -#include <uhd/usrp/subdev_spec.hpp> -#include <uhd/types/sensors.hpp> -#include <uhd/transport/udp_simple.hpp> //mtu -#include <uhd/usrp/gps_ctrl.hpp> +#include <uhd/transport/muxed_zero_copy_if.hpp> #include <uhd/transport/nirio/niusrprio_session.h> +#include <uhd/transport/udp_simple.hpp> //mtu #include <uhd/transport/vrt_if_packet.hpp> -#include <uhd/transport/muxed_zero_copy_if.hpp> +#include <uhd/types/sensors.hpp> +#include <uhd/usrp/gps_ctrl.hpp> +#include <uhd/usrp/mboard_eeprom.hpp> +#include <uhd/usrp/subdev_spec.hpp> ///////////// RFNOC ///////////////////// #include <uhd/rfnoc/block_ctrl.hpp> ///////////// RFNOC ///////////////////// -#include <uhdlib/usrp/cores/i2c_core_100_wb32.hpp> #include <uhdlib/usrp/common/recv_packet_demuxer_3000.hpp> +#include <uhdlib/usrp/cores/i2c_core_100_wb32.hpp> #include <boost/dynamic_bitset.hpp> #include <boost/weak_ptr.hpp> #include <atomic> // Ethernet ports -enum x300_eth_iface_t -{ +enum x300_eth_iface_t { X300_IFACE_NONE = 0, X300_IFACE_ETH0 = 1, X300_IFACE_ETH1 = 2, @@ -53,47 +51,46 @@ struct x300_eth_conn_t uhd::uart_iface::sptr x300_make_uart_iface(uhd::wb_iface::sptr iface); -uhd::wb_iface::sptr x300_make_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors = true); -uhd::wb_iface::sptr x300_make_ctrl_iface_pcie(uhd::niusrprio::niriok_proxy::sptr drv_proxy, bool enable_errors = true); +uhd::wb_iface::sptr x300_make_ctrl_iface_enet( + uhd::transport::udp_simple::sptr udp, bool enable_errors = true); +uhd::wb_iface::sptr x300_make_ctrl_iface_pcie( + uhd::niusrprio::niriok_proxy::sptr drv_proxy, bool enable_errors = true); -uhd::device_addrs_t x300_find(const uhd::device_addr_t &hint_); +uhd::device_addrs_t x300_find(const uhd::device_addr_t& hint_); class x300_impl : public uhd::usrp::device3_impl { public: - - x300_impl(const uhd::device_addr_t &); - void setup_mb(const size_t which, const uhd::device_addr_t &); + x300_impl(const uhd::device_addr_t&); + void setup_mb(const size_t which, const uhd::device_addr_t&); ~x300_impl(void); // device claim functions - enum claim_status_t {UNCLAIMED, CLAIMED_BY_US, CLAIMED_BY_OTHER}; + enum claim_status_t { UNCLAIMED, CLAIMED_BY_US, CLAIMED_BY_OTHER }; static claim_status_t claim_status(uhd::wb_iface::sptr iface); static void claim(uhd::wb_iface::sptr iface); static bool try_to_claim(uhd::wb_iface::sptr iface, long timeout = 2000); static void release(uhd::wb_iface::sptr iface); - enum x300_mboard_t { - USRP_X300_MB, USRP_X310_MB, USRP_X310_MB_NI_2974, UNKNOWN - }; - static x300_mboard_t get_mb_type_from_pcie(const std::string& resource, const std::string& rpc_port); - static x300_mboard_t get_mb_type_from_eeprom(const uhd::usrp::mboard_eeprom_t& mb_eeprom); + enum x300_mboard_t { USRP_X300_MB, USRP_X310_MB, USRP_X310_MB_NI_2974, UNKNOWN }; + static x300_mboard_t get_mb_type_from_pcie( + const std::string& resource, const std::string& rpc_port); + static x300_mboard_t get_mb_type_from_eeprom( + const uhd::usrp::mboard_eeprom_t& mb_eeprom); //! Read out the on-board EEPROM, convert to dict, and return static uhd::usrp::mboard_eeprom_t get_mb_eeprom(uhd::i2c_iface::sptr i2c); protected: - void subdev_to_blockid( - const uhd::usrp::subdev_spec_pair_t &spec, const size_t mb_i, - uhd::rfnoc::block_id_t &block_id, uhd::device_addr_t &block_args - ); + void subdev_to_blockid(const uhd::usrp::subdev_spec_pair_t& spec, + const size_t mb_i, + uhd::rfnoc::block_id_t& block_id, + uhd::device_addr_t& block_args); uhd::usrp::subdev_spec_pair_t blockid_to_subdev( - const uhd::rfnoc::block_id_t &blockid, const uhd::device_addr_t &block_args - ); + const uhd::rfnoc::block_id_t& blockid, const uhd::device_addr_t& block_args); private: - - //vector of member objects per motherboard + // vector of member objects per motherboard struct mboard_members_t { uhd::usrp::x300::x300_device_args_t args; @@ -109,7 +106,7 @@ private: // Discover the ethernet connections per motherboard void discover_eth(const uhd::usrp::mboard_eeprom_t mb_eeprom, - const std::vector<std::string> &ip_addrs); + const std::vector<std::string>& ip_addrs); // Get the primary ethernet connection inline const x300_eth_conn_t& get_pri_eth() const @@ -120,20 +117,20 @@ private: uhd::device_addr_t send_args; uhd::device_addr_t recv_args; bool if_pkt_is_big_endian; - uhd::niusrprio::niusrprio_session::sptr rio_fpga_interface; + uhd::niusrprio::niusrprio_session::sptr rio_fpga_interface; - //perifs in the zpu + // perifs in the zpu uhd::wb_iface::sptr zpu_ctrl; spi_core_3000::sptr zpu_spi; i2c_core_100_wb32::sptr zpu_i2c; - //other perifs on mboard + // other perifs on mboard x300_clock_ctrl::sptr clock; uhd::gps_ctrl::sptr gps; uhd::usrp::x300::fw_regmap_t::sptr fw_regmap; - //which FPGA image is loaded + // which FPGA image is loaded std::string loaded_fpga_image; size_t hw_rev; @@ -154,25 +151,23 @@ private: * * Note the SID is always the transmit SID (i.e. from host to device). */ - uint32_t allocate_pcie_dma_chan(const uhd::sid_t &tx_sid, const xport_type_t xport_type); + uint32_t allocate_pcie_dma_chan( + const uhd::sid_t& tx_sid, const xport_type_t xport_type); }; std::vector<mboard_members_t> _mb; - //task for periodically reclaiming the device from others + // task for periodically reclaiming the device from others void claimer_loop(uhd::wb_iface::sptr); std::atomic<size_t> _sid_framer; - uhd::sid_t allocate_sid( - mboard_members_t &mb, - const uhd::sid_t &address, + uhd::sid_t allocate_sid(mboard_members_t& mb, + const uhd::sid_t& address, const uint32_t src_addr, const uint32_t src_dst); - uhd::both_xports_t make_transport( - const uhd::sid_t &address, + uhd::both_xports_t make_transport(const uhd::sid_t& address, const xport_type_t xport_type, - const uhd::device_addr_t& args - ); + const uhd::device_addr_t& args); struct frame_size_t { @@ -186,24 +181,25 @@ private: * to the device and see which packet sizes actually work. This way, we can take * switches etc. into account which might live between the device and the host. */ - frame_size_t determine_max_frame_size(const std::string &addr, const frame_size_t &user_mtu); + frame_size_t determine_max_frame_size( + const std::string& addr, const frame_size_t& user_mtu); //////////////////////////////////////////////////////////////////// // - //Caching for transport interface re-use -- like sharing a DMA. - //The cache is optionally used by make_transport by use-case. - //The cache maps an ID string to a transport-ish object. - //The ID string identifies a purpose for the transport. + // Caching for transport interface re-use -- like sharing a DMA. + // The cache is optionally used by make_transport by use-case. + // The cache maps an ID string to a transport-ish object. + // The ID string identifies a purpose for the transport. // - //For recv, there is a demux cache, which maps a ID string - //to a recv demux object. When a demux is used, the underlying transport - //must never be used outside of the demux. Use demux->make_proxy(sid). + // For recv, there is a demux cache, which maps a ID string + // to a recv demux object. When a demux is used, the underlying transport + // must never be used outside of the demux. Use demux->make_proxy(sid). // uhd::dict<std::string, uhd::usrp::recv_packet_demuxer_3000::sptr> _demux_cache; // - //For send, there is a shared send xport, which maps an ID string - //to a transport capable of sending buffers. Send transports - //can be shared amongst multiple callers, unlike recv. + // For send, there is a shared send xport, which maps an ID string + // to a transport capable of sending buffers. Send transports + // can be shared amongst multiple callers, unlike recv. // uhd::dict<std::string, uhd::transport::zero_copy_if::sptr> _send_cache; // @@ -214,10 +210,10 @@ private: bool _ignore_cal_file; void update_clock_control(mboard_members_t&); - void initialize_clock_control(mboard_members_t &mb); + void initialize_clock_control(mboard_members_t& mb); void set_time_source_out(mboard_members_t&, const bool); - void update_clock_source(mboard_members_t&, const std::string &); - void update_time_source(mboard_members_t&, const std::string &); + void update_clock_source(mboard_members_t&, const std::string&); + void update_time_source(mboard_members_t&, const std::string&); void sync_times(mboard_members_t&, const uhd::time_spec_t&); uhd::sensor_value_t get_ref_locked(mboard_members_t& mb); @@ -225,13 +221,10 @@ private: bool is_pps_present(mboard_members_t& mb); //! Write the contents of an EEPROM dict to the on-board EEPROM - void set_mb_eeprom( - uhd::i2c_iface::sptr i2c, - const uhd::usrp::mboard_eeprom_t & - ); + void set_mb_eeprom(uhd::i2c_iface::sptr i2c, const uhd::usrp::mboard_eeprom_t&); - void check_fw_compat(const uhd::fs_path &mb_path, const mboard_members_t &members); - void check_fpga_compat(const uhd::fs_path &mb_path, const mboard_members_t &members); + void check_fw_compat(const uhd::fs_path& mb_path, const mboard_members_t& members); + void check_fpga_compat(const uhd::fs_path& mb_path, const mboard_members_t& members); /// More IO stuff uhd::device_addr_t get_tx_hints(size_t mb_index); diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp index d833b3715..07e93173a 100644 --- a/host/lib/usrp/x300/x300_io_impl.cpp +++ b/host/lib/usrp/x300/x300_io_impl.cpp @@ -5,8 +5,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include "x300_regs.hpp" #include "x300_impl.hpp" +#include "x300_regs.hpp" using namespace uhd; using namespace uhd::usrp; @@ -35,7 +35,7 @@ void x300_impl::post_streamer_hooks(direction_t dir) // Loop through all tx streamers. Find all radios connected to one // streamer. Sync those. - for(const boost::weak_ptr<uhd::tx_streamer> &streamer_w: _tx_streamers.vals()) { + for (const boost::weak_ptr<uhd::tx_streamer>& streamer_w : _tx_streamers.vals()) { const boost::shared_ptr<device3_send_packet_streamer> streamer = boost::dynamic_pointer_cast<device3_send_packet_streamer>(streamer_w.lock()); if (not streamer) { @@ -43,13 +43,15 @@ void x300_impl::post_streamer_hooks(direction_t dir) } std::vector<rfnoc::x300_radio_ctrl_impl::sptr> radio_ctrl_blks = - streamer->get_terminator()->find_downstream_node<rfnoc::x300_radio_ctrl_impl>(); + streamer->get_terminator() + ->find_downstream_node<rfnoc::x300_radio_ctrl_impl>(); try { - //UHD_LOGGER_INFO("X300") << "[X300] syncing " << radio_ctrl_blks.size() << " radios " ; + // UHD_LOGGER_INFO("X300") << "[X300] syncing " << radio_ctrl_blks.size() << " + // radios " ; rfnoc::x300_radio_ctrl_impl::synchronize_dacs(radio_ctrl_blks); - } - catch(const uhd::io_error &ex) { - throw uhd::io_error(str(boost::format("Failed to sync DACs! %s ") % ex.what())); + } catch (const uhd::io_error& ex) { + throw uhd::io_error( + str(boost::format("Failed to sync DACs! %s ") % ex.what())); } } } diff --git a/host/lib/usrp/x300/x300_mb_eeprom.cpp b/host/lib/usrp/x300/x300_mb_eeprom.cpp index b3ebf6101..663f4c9db 100644 --- a/host/lib/usrp/x300/x300_mb_eeprom.cpp +++ b/host/lib/usrp/x300/x300_mb_eeprom.cpp @@ -5,38 +5,38 @@ // #include "x300_impl.hpp" -#include <uhdlib/utils/eeprom_utils.hpp> -#include <uhd/usrp/mboard_eeprom.hpp> #include <uhd/types/serial.hpp> +#include <uhd/usrp/mboard_eeprom.hpp> +#include <uhdlib/utils/eeprom_utils.hpp> namespace { - const uint8_t X300_EEPROM_ADDR = 0x50; - - struct x300_eeprom_map - { - //identifying numbers - unsigned char revision[2]; - unsigned char product[2]; - unsigned char revision_compat[2]; - uint8_t _pad0[2]; - - //all the mac addrs - uint8_t mac_addr0[6]; - uint8_t _pad1[2]; - uint8_t mac_addr1[6]; - uint8_t _pad2[2]; - - //all the IP addrs - uint32_t gateway; - uint32_t subnet[4]; - uint32_t ip_addr[4]; - uint8_t _pad3[16]; - - //names and serials - unsigned char name[NAME_MAX_LEN]; - unsigned char serial[SERIAL_LEN]; - }; -} +const uint8_t X300_EEPROM_ADDR = 0x50; + +struct x300_eeprom_map +{ + // identifying numbers + unsigned char revision[2]; + unsigned char product[2]; + unsigned char revision_compat[2]; + uint8_t _pad0[2]; + + // all the mac addrs + uint8_t mac_addr0[6]; + uint8_t _pad1[2]; + uint8_t mac_addr1[6]; + uint8_t _pad2[2]; + + // all the IP addrs + uint32_t gateway; + uint32_t subnet[4]; + uint32_t ip_addr[4]; + uint8_t _pad3[16]; + + // names and serials + unsigned char name[NAME_MAX_LEN]; + unsigned char serial[SERIAL_LEN]; +}; +} // namespace using namespace uhd; using uhd::usrp::mboard_eeprom_t; @@ -51,170 +51,150 @@ mboard_eeprom_t x300_impl::get_mb_eeprom(uhd::i2c_iface::sptr iface) return mb_eeprom; } - //extract the revision number + // extract the revision number mb_eeprom["revision"] = uint16_bytes_to_string( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, revision), - bytes.begin() + (offsetof(x300_eeprom_map, revision)+2)) - ); + byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, revision), + bytes.begin() + (offsetof(x300_eeprom_map, revision) + 2))); - //extract the revision compat number + // extract the revision compat number mb_eeprom["revision_compat"] = uint16_bytes_to_string( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, revision_compat), - bytes.begin() + (offsetof(x300_eeprom_map, revision_compat)+2)) - ); + byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, revision_compat), + bytes.begin() + (offsetof(x300_eeprom_map, revision_compat) + 2))); - //extract the product code + // extract the product code mb_eeprom["product"] = uint16_bytes_to_string( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, product), - bytes.begin() + (offsetof(x300_eeprom_map, product)+2)) - ); + byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, product), + bytes.begin() + (offsetof(x300_eeprom_map, product) + 2))); - //extract the mac addresses + // extract the mac addresses mb_eeprom["mac-addr0"] = mac_addr_t::from_bytes( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, mac_addr0), - bytes.begin() + (offsetof(x300_eeprom_map, mac_addr0)+6)) - ).to_string(); + byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, mac_addr0), + bytes.begin() + (offsetof(x300_eeprom_map, mac_addr0) + 6))) + .to_string(); mb_eeprom["mac-addr1"] = mac_addr_t::from_bytes( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, mac_addr1), - bytes.begin() + (offsetof(x300_eeprom_map, mac_addr1)+6)) - ).to_string(); + byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, mac_addr1), + bytes.begin() + (offsetof(x300_eeprom_map, mac_addr1) + 6))) + .to_string(); - //extract the ip addresses + // extract the ip addresses boost::asio::ip::address_v4::bytes_type ip_addr_bytes; - byte_copy( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, gateway), - bytes.begin() + (offsetof(x300_eeprom_map, gateway)+4)), - ip_addr_bytes - ); + byte_copy(byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, gateway), + bytes.begin() + (offsetof(x300_eeprom_map, gateway) + 4)), + ip_addr_bytes); mb_eeprom["gateway"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string(); - for (size_t i = 0; i < 4; i++) - { - const std::string n(1, char(i)+'0'); + for (size_t i = 0; i < 4; i++) { + const std::string n(1, char(i) + '0'); byte_copy( - byte_vector_t( - bytes.begin() + (offsetof(x300_eeprom_map, ip_addr)+(i*4)), - bytes.begin() + (offsetof(x300_eeprom_map, ip_addr)+(i*4)+4)), - ip_addr_bytes - ); - mb_eeprom["ip-addr"+n] = boost::asio::ip::address_v4(ip_addr_bytes).to_string(); + byte_vector_t(bytes.begin() + (offsetof(x300_eeprom_map, ip_addr) + (i * 4)), + bytes.begin() + (offsetof(x300_eeprom_map, ip_addr) + (i * 4) + 4)), + ip_addr_bytes); + mb_eeprom["ip-addr" + n] = boost::asio::ip::address_v4(ip_addr_bytes).to_string(); byte_copy( - byte_vector_t( - bytes.begin() + (offsetof(x300_eeprom_map, subnet)+(i*4)), - bytes.begin() + (offsetof(x300_eeprom_map, subnet)+(i*4)+4)), - ip_addr_bytes - ); - mb_eeprom["subnet"+n] = boost::asio::ip::address_v4(ip_addr_bytes).to_string(); + byte_vector_t(bytes.begin() + (offsetof(x300_eeprom_map, subnet) + (i * 4)), + bytes.begin() + (offsetof(x300_eeprom_map, subnet) + (i * 4) + 4)), + ip_addr_bytes); + mb_eeprom["subnet" + n] = boost::asio::ip::address_v4(ip_addr_bytes).to_string(); } - //extract the serial - mb_eeprom["serial"] = bytes_to_string( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, serial), - bytes.begin() + (offsetof(x300_eeprom_map, serial)+SERIAL_LEN)) - ); + // extract the serial + mb_eeprom["serial"] = + bytes_to_string(byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, serial), + bytes.begin() + (offsetof(x300_eeprom_map, serial) + SERIAL_LEN))); - //extract the name - mb_eeprom["name"] = bytes_to_string( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, name), - bytes.begin() + (offsetof(x300_eeprom_map, name)+NAME_MAX_LEN)) - ); + // extract the name + mb_eeprom["name"] = + bytes_to_string(byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, name), + bytes.begin() + (offsetof(x300_eeprom_map, name) + NAME_MAX_LEN))); return mb_eeprom; } -void x300_impl::set_mb_eeprom( - i2c_iface::sptr iface, - const mboard_eeprom_t &mb_eeprom -) { +void x300_impl::set_mb_eeprom(i2c_iface::sptr iface, const mboard_eeprom_t& mb_eeprom) +{ const mboard_eeprom_t curr_eeprom = get_mb_eeprom(iface); // Check for duplicate MAC and IP addresses - const std::vector<std::string> mac_keys{ - "mac-addr0", - "mac-addr1" - }; + const std::vector<std::string> mac_keys{"mac-addr0", "mac-addr1"}; const std::vector<std::string> ip_keys{ - "ip-addr0", - "ip-addr1", - "ip-addr2", - "ip-addr3" - }; + "ip-addr0", "ip-addr1", "ip-addr2", "ip-addr3"}; - //make sure there are no duplicate values + // make sure there are no duplicate values if (check_for_duplicates<uhd::mac_addr_t>( - "X300", mb_eeprom, curr_eeprom,"MAC address", mac_keys) or - check_for_duplicates<boost::asio::ip::address_v4>( - "X300", mb_eeprom, curr_eeprom, "IP address", ip_keys)) - { + "X300", mb_eeprom, curr_eeprom, "MAC address", mac_keys) + or check_for_duplicates<boost::asio::ip::address_v4>( + "X300", mb_eeprom, curr_eeprom, "IP address", ip_keys)) { throw uhd::value_error( "Duplicate values not permitted - write to EEPROM aborted"); } - //parse the revision number - if (mb_eeprom.has_key("revision")) iface->write_eeprom( - X300_EEPROM_ADDR, offsetof(x300_eeprom_map, revision), - string_to_uint16_bytes(mb_eeprom["revision"]) - ); - - //parse the revision compat number - if (mb_eeprom.has_key("revision_compat")) iface->write_eeprom( - X300_EEPROM_ADDR, offsetof(x300_eeprom_map, revision_compat), - string_to_uint16_bytes(mb_eeprom["revision_compat"]) - ); - - //parse the product code - if (mb_eeprom.has_key("product")) iface->write_eeprom( - X300_EEPROM_ADDR, offsetof(x300_eeprom_map, product), - string_to_uint16_bytes(mb_eeprom["product"]) - ); - - //store the mac addresses - if (mb_eeprom.has_key("mac-addr0")) iface->write_eeprom( - X300_EEPROM_ADDR, offsetof(x300_eeprom_map, mac_addr0), - mac_addr_t::from_string(mb_eeprom["mac-addr0"]).to_bytes() - ); - if (mb_eeprom.has_key("mac-addr1")) iface->write_eeprom( - X300_EEPROM_ADDR, offsetof(x300_eeprom_map, mac_addr1), - mac_addr_t::from_string(mb_eeprom["mac-addr1"]).to_bytes() - ); - - //store the ip addresses + // parse the revision number + if (mb_eeprom.has_key("revision")) + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, revision), + string_to_uint16_bytes(mb_eeprom["revision"])); + + // parse the revision compat number + if (mb_eeprom.has_key("revision_compat")) + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, revision_compat), + string_to_uint16_bytes(mb_eeprom["revision_compat"])); + + // parse the product code + if (mb_eeprom.has_key("product")) + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, product), + string_to_uint16_bytes(mb_eeprom["product"])); + + // store the mac addresses + if (mb_eeprom.has_key("mac-addr0")) + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, mac_addr0), + mac_addr_t::from_string(mb_eeprom["mac-addr0"]).to_bytes()); + if (mb_eeprom.has_key("mac-addr1")) + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, mac_addr1), + mac_addr_t::from_string(mb_eeprom["mac-addr1"]).to_bytes()); + + // store the ip addresses byte_vector_t ip_addr_bytes(4); - if (mb_eeprom.has_key("gateway")){ - byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["gateway"]).to_bytes(), ip_addr_bytes); - iface->write_eeprom(X300_EEPROM_ADDR, offsetof(x300_eeprom_map, gateway), ip_addr_bytes); + if (mb_eeprom.has_key("gateway")) { + byte_copy( + boost::asio::ip::address_v4::from_string(mb_eeprom["gateway"]).to_bytes(), + ip_addr_bytes); + iface->write_eeprom( + X300_EEPROM_ADDR, offsetof(x300_eeprom_map, gateway), ip_addr_bytes); } - for (size_t i = 0; i < 4; i++) - { - const std::string n(1, char(i)+'0'); - if (mb_eeprom.has_key("ip-addr"+n)){ - byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["ip-addr"+n]).to_bytes(), ip_addr_bytes); - iface->write_eeprom(X300_EEPROM_ADDR, offsetof(x300_eeprom_map, ip_addr)+(i*4), ip_addr_bytes); + for (size_t i = 0; i < 4; i++) { + const std::string n(1, char(i) + '0'); + if (mb_eeprom.has_key("ip-addr" + n)) { + byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["ip-addr" + n]) + .to_bytes(), + ip_addr_bytes); + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, ip_addr) + (i * 4), + ip_addr_bytes); } - if (mb_eeprom.has_key("subnet"+n)){ - byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["subnet"+n]).to_bytes(), ip_addr_bytes); - iface->write_eeprom(X300_EEPROM_ADDR, offsetof(x300_eeprom_map, subnet)+(i*4), ip_addr_bytes); + if (mb_eeprom.has_key("subnet" + n)) { + byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["subnet" + n]) + .to_bytes(), + ip_addr_bytes); + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, subnet) + (i * 4), + ip_addr_bytes); } } - //store the serial - if (mb_eeprom.has_key("serial")) iface->write_eeprom( - X300_EEPROM_ADDR, offsetof(x300_eeprom_map, serial), - string_to_bytes(mb_eeprom["serial"], SERIAL_LEN) - ); - - //store the name - if (mb_eeprom.has_key("name")) iface->write_eeprom( - X300_EEPROM_ADDR, offsetof(x300_eeprom_map, name), - string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN) - ); + // store the serial + if (mb_eeprom.has_key("serial")) + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, serial), + string_to_bytes(mb_eeprom["serial"], SERIAL_LEN)); + + // store the name + if (mb_eeprom.has_key("name")) + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, name), + string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN)); } diff --git a/host/lib/usrp/x300/x300_mb_eeprom_iface.cpp b/host/lib/usrp/x300/x300_mb_eeprom_iface.cpp index 630e8ce2b..12022ec24 100644 --- a/host/lib/usrp/x300/x300_mb_eeprom_iface.cpp +++ b/host/lib/usrp/x300/x300_mb_eeprom_iface.cpp @@ -19,12 +19,12 @@ #include "x300_mb_eeprom_iface.hpp" #include "x300_fw_common.h" -#include "x300_regs.hpp" #include "x300_impl.hpp" +#include "x300_regs.hpp" #include <uhd/exception.hpp> -#include <uhd/utils/platform.hpp> -#include <uhd/utils/log.hpp> #include <uhd/utils/byteswap.hpp> +#include <uhd/utils/log.hpp> +#include <uhd/utils/platform.hpp> #include <boost/thread.hpp> using namespace uhd; @@ -34,7 +34,6 @@ static const uint32_t X300_FW_SHMEM_IDENT_MIN_VERSION = 0x50001; class x300_mb_eeprom_iface_impl : public x300_mb_eeprom_iface { public: - x300_mb_eeprom_iface_impl(wb_iface::sptr wb, i2c_iface::sptr i2c) : _wb(wb), _i2c(i2c) { _compat_num = _wb->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_COMPAT_NUM)); @@ -50,14 +49,10 @@ public: * \param addr the address * \param buf the vector of bytes */ - void write_i2c( - uint16_t addr, - const byte_vector_t &buf - ) + void write_i2c(uint16_t addr, const byte_vector_t& buf) { UHD_ASSERT_THROW(addr == MBOARD_EEPROM_ADDR); - if (x300_impl::claim_status(_wb) != x300_impl::CLAIMED_BY_US) - { + if (x300_impl::claim_status(_wb) != x300_impl::CLAIMED_BY_US) { throw uhd::io_error("Attempted to write MB EEPROM without claim to device."); } _i2c->write_i2c(addr, buf); @@ -69,24 +64,18 @@ public: * \param num_bytes number of bytes to read * \return a vector of bytes */ - byte_vector_t read_i2c( - uint16_t addr, - size_t num_bytes - ) + byte_vector_t read_i2c(uint16_t addr, size_t num_bytes) { UHD_ASSERT_THROW(addr == MBOARD_EEPROM_ADDR); byte_vector_t bytes; - if (_compat_num > X300_FW_SHMEM_IDENT_MIN_VERSION) - { + if (_compat_num > X300_FW_SHMEM_IDENT_MIN_VERSION) { bytes = read_eeprom(addr, 0, num_bytes); } else { x300_impl::claim_status_t status = x300_impl::claim_status(_wb); // Claim device before driving the I2C bus - if (status == x300_impl::CLAIMED_BY_US or x300_impl::try_to_claim(_wb)) - { + if (status == x300_impl::CLAIMED_BY_US or x300_impl::try_to_claim(_wb)) { bytes = _i2c->read_i2c(addr, num_bytes); - if (status != x300_impl::CLAIMED_BY_US) - { + if (status != x300_impl::CLAIMED_BY_US) { // We didn't originally have the claim, so give it up x300_impl::release(_wb); } @@ -101,15 +90,10 @@ public: * \param offset byte offset * \param buf the vector of bytes */ - void write_eeprom( - uint16_t addr, - uint16_t offset, - const byte_vector_t &buf - ) + void write_eeprom(uint16_t addr, uint16_t offset, const byte_vector_t& buf) { UHD_ASSERT_THROW(addr == MBOARD_EEPROM_ADDR); - if (x300_impl::claim_status(_wb) != x300_impl::CLAIMED_BY_US) - { + if (x300_impl::claim_status(_wb) != x300_impl::CLAIMED_BY_US) { throw uhd::io_error("Attempted to write MB EEPROM without claim to device."); } _i2c->write_eeprom(addr, offset, buf); @@ -122,37 +106,31 @@ public: * \param num_bytes number of bytes to read * \return a vector of bytes */ - byte_vector_t read_eeprom( - uint16_t addr, - uint16_t offset, - size_t num_bytes - ) + byte_vector_t read_eeprom(uint16_t addr, uint16_t offset, size_t num_bytes) { UHD_ASSERT_THROW(addr == MBOARD_EEPROM_ADDR); byte_vector_t bytes; x300_impl::claim_status_t status = x300_impl::claim_status(_wb); - if (_compat_num >= X300_FW_SHMEM_IDENT_MIN_VERSION) - { + if (_compat_num >= X300_FW_SHMEM_IDENT_MIN_VERSION) { // Get MB EEPROM data from firmware memory - if (num_bytes == 0) return bytes; + if (num_bytes == 0) + return bytes; size_t bytes_read = 0; - for (size_t word = offset / 4; bytes_read < num_bytes; word++) - { - uint32_t value = byteswap(_wb->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_IDENT + word))); - for (size_t byte = offset % 4; byte < 4 and bytes_read < num_bytes; byte++) - { + for (size_t word = offset / 4; bytes_read < num_bytes; word++) { + uint32_t value = + byteswap(_wb->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_IDENT + word))); + for (size_t byte = offset % 4; byte < 4 and bytes_read < num_bytes; + byte++) { bytes.push_back(uint8_t((value >> (byte * 8)) & 0xff)); bytes_read++; } } } else { // Claim device before driving the I2C bus - if (status == x300_impl::CLAIMED_BY_US or x300_impl::try_to_claim(_wb)) - { + if (status == x300_impl::CLAIMED_BY_US or x300_impl::try_to_claim(_wb)) { bytes = _i2c->read_eeprom(addr, offset, num_bytes); - if (status != x300_impl::CLAIMED_BY_US) - { + if (status != x300_impl::CLAIMED_BY_US) { // We didn't originally have the claim, so give it up x300_impl::release(_wb); } @@ -173,8 +151,8 @@ x300_mb_eeprom_iface::~x300_mb_eeprom_iface(void) /* NOP */ } -x300_mb_eeprom_iface::sptr x300_mb_eeprom_iface::make(wb_iface::sptr wb, i2c_iface::sptr i2c) +x300_mb_eeprom_iface::sptr x300_mb_eeprom_iface::make( + wb_iface::sptr wb, i2c_iface::sptr i2c) { return boost::make_shared<x300_mb_eeprom_iface_impl>(wb, i2c->eeprom16()); } - diff --git a/host/lib/usrp/x300/x300_mb_eeprom_iface.hpp b/host/lib/usrp/x300/x300_mb_eeprom_iface.hpp index dfc1eea6d..d323d6359 100644 --- a/host/lib/usrp/x300/x300_mb_eeprom_iface.hpp +++ b/host/lib/usrp/x300/x300_mb_eeprom_iface.hpp @@ -10,9 +10,9 @@ #include <uhd/config.hpp> #include <uhd/types/serial.hpp> -#include <boost/utility.hpp> -#include <boost/shared_ptr.hpp> #include <uhd/types/wb_iface.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> class x300_mb_eeprom_iface : public uhd::i2c_iface { diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp index d0aadc55a..9057180e4 100644 --- a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp +++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp @@ -6,19 +6,19 @@ #include "x300_radio_ctrl_impl.hpp" #include "x300_dboard_iface.hpp" -#include <uhd/usrp/dboard_eeprom.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/usrp/dboard_iface.hpp> #include <uhd/rfnoc/node_ctrl_base.hpp> #include <uhd/transport/chdr.hpp> +#include <uhd/usrp/dboard_eeprom.hpp> +#include <uhd/usrp/dboard_iface.hpp> +#include <uhd/utils/log.hpp> #include <uhd/utils/math.hpp> #include <uhd/utils/safe_call.hpp> #include <uhdlib/rfnoc/wb_iface_adapter.hpp> -#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> #include <uhdlib/usrp/common/apply_corrections.hpp> +#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> #include <boost/algorithm/string.hpp> -#include <boost/make_shared.hpp> #include <boost/date_time/posix_time/posix_time_io.hpp> +#include <boost/make_shared.hpp> #include <chrono> #include <thread> @@ -33,26 +33,26 @@ static const size_t IO_MASTER_RADIO = 0; * Structors ***************************************************************************/ UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(x300_radio_ctrl) - , _ignore_cal_file(false) +, _ignore_cal_file(false) { - UHD_RFNOC_BLOCK_TRACE() << "x300_radio_ctrl_impl::ctor() " ; + UHD_RFNOC_BLOCK_TRACE() << "x300_radio_ctrl_impl::ctor() "; //////////////////////////////////////////////////////////////////// // Set up basic info //////////////////////////////////////////////////////////////////// - _radio_type = (get_block_id().get_block_count() == 0) ? PRIMARY : SECONDARY; - _radio_slot = (get_block_id().get_block_count() == 0) ? "A" : "B"; + _radio_type = (get_block_id().get_block_count() == 0) ? PRIMARY : SECONDARY; + _radio_slot = (get_block_id().get_block_count() == 0) ? "A" : "B"; _radio_clk_rate = _tree->access<double>("master_clock_rate").get(); //////////////////////////////////////////////////////////////////// // Set up peripherals //////////////////////////////////////////////////////////////////// wb_iface::sptr ctrl = _get_ctrl(IO_MASTER_RADIO); - _regs = boost::make_shared<radio_regmap_t>(_radio_type==PRIMARY?0:1); + _regs = boost::make_shared<radio_regmap_t>(_radio_type == PRIMARY ? 0 : 1); _regs->initialize(*ctrl, true); - //Only Radio0 has the ADC/DAC reset bits. Those bits are reserved for Radio1 - if (_radio_type==PRIMARY) { + // Only Radio0 has the ADC/DAC reset bits. Those bits are reserved for Radio1 + if (_radio_type == PRIMARY) { _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 1); _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 0); _regs->misc_outs_reg.flush(); @@ -67,84 +67,100 @@ UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(x300_radio_ctrl) //////////////////////////////////////////////////////////////// _spi = spi_core_3000::make(ctrl, regs::sr_addr(radio_ctrl_impl::regs::SPI), - regs::rb_addr(radio_ctrl_impl::regs::RB_SPI) - ); + regs::rb_addr(radio_ctrl_impl::regs::RB_SPI)); _adc = x300_adc_ctrl::make(_spi, DB_ADC_SEN); _dac = x300_dac_ctrl::make(_spi, DB_DAC_SEN, _radio_clk_rate); - if (_radio_type==PRIMARY) { - _fp_gpio = gpio_atr::gpio_atr_3000::make(ctrl, - regs::sr_addr(regs::FP_GPIO), - regs::rb_addr(regs::RB_FP_GPIO) - ); - for(const gpio_atr::gpio_attr_map_t::value_type attr: gpio_atr::gpio_attr_map) { - switch (attr.first){ + if (_radio_type == PRIMARY) { + _fp_gpio = gpio_atr::gpio_atr_3000::make( + ctrl, regs::sr_addr(regs::FP_GPIO), regs::rb_addr(regs::RB_FP_GPIO)); + for (const gpio_atr::gpio_attr_map_t::value_type attr : gpio_atr::gpio_attr_map) { + switch (attr.first) { case usrp::gpio_atr::GPIO_SRC: - _tree->create<std::vector<std::string>>(fs_path("gpio") / "FP0" / attr.second) - .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) - .add_coerced_subscriber([this](const std::vector<std::string>&){ - throw uhd::runtime_error("This device does not support setting the GPIO_SRC attribute."); - }); + _tree + ->create<std::vector<std::string>>( + fs_path("gpio") / "FP0" / attr.second) + .set(std::vector<std::string>( + 32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) + .add_coerced_subscriber([this](const std::vector<std::string>&) { + throw uhd::runtime_error("This device does not support " + "setting the GPIO_SRC attribute."); + }); break; case usrp::gpio_atr::GPIO_CTRL: case usrp::gpio_atr::GPIO_DDR: - _tree->create<std::vector<std::string>>(fs_path("gpio") / "FP0" / attr.second) - .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) - .add_coerced_subscriber([this, attr](const std::vector<std::string> str_val){ - uint32_t val = 0; - for(size_t i = 0 ; i < str_val.size() ; i++){ - val += usrp::gpio_atr::gpio_attr_value_pair.at(attr.second).at(str_val[i])<<i; - } - _fp_gpio->set_gpio_attr(attr.first, val); - }); + _tree + ->create<std::vector<std::string>>( + fs_path("gpio") / "FP0" / attr.second) + .set(std::vector<std::string>( + 32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) + .add_coerced_subscriber( + [this, attr](const std::vector<std::string> str_val) { + uint32_t val = 0; + for (size_t i = 0; i < str_val.size(); i++) { + val += usrp::gpio_atr::gpio_attr_value_pair + .at(attr.second) + .at(str_val[i]) + << i; + } + _fp_gpio->set_gpio_attr(attr.first, val); + }); break; case usrp::gpio_atr::GPIO_READBACK: _tree->create<uint32_t>(fs_path("gpio") / "FP0" / "READBACK") - .set_publisher([this](){ - return _fp_gpio->read_gpio(); - }); + .set_publisher([this]() { return _fp_gpio->read_gpio(); }); break; default: _tree->create<uint32_t>(fs_path("gpio") / "FP0" / attr.second) - .set(0) - .add_coerced_subscriber([this, attr](const uint32_t val){ - _fp_gpio->set_gpio_attr(attr.first, val); - }); + .set(0) + .add_coerced_subscriber([this, attr](const uint32_t val) { + _fp_gpio->set_gpio_attr(attr.first, val); + }); } - } } //////////////////////////////////////////////////////////////// // create legacy codec control objects //////////////////////////////////////////////////////////////// - _tree->create<int>("rx_codecs" / _radio_slot / "gains"); //phony property so this dir exists - _tree->create<int>("tx_codecs" / _radio_slot / "gains"); //phony property so this dir exists + _tree->create<int>( + "rx_codecs" / _radio_slot / "gains"); // phony property so this dir exists + _tree->create<int>( + "tx_codecs" / _radio_slot / "gains"); // phony property so this dir exists _tree->create<std::string>("rx_codecs" / _radio_slot / "name").set("ads62p48"); _tree->create<std::string>("tx_codecs" / _radio_slot / "name").set("ad9146"); - _tree->create<meta_range_t>("rx_codecs" / _radio_slot / "gains" / "digital" / "range").set(meta_range_t(0, 6.0, 0.5)); + _tree->create<meta_range_t>("rx_codecs" / _radio_slot / "gains" / "digital" / "range") + .set(meta_range_t(0, 6.0, 0.5)); _tree->create<double>("rx_codecs" / _radio_slot / "gains" / "digital" / "value") - .add_coerced_subscriber(boost::bind(&x300_adc_ctrl::set_gain, _adc, _1)).set(0) - ; + .add_coerced_subscriber(boost::bind(&x300_adc_ctrl::set_gain, _adc, _1)) + .set(0); //////////////////////////////////////////////////////////////// // create front-end objects //////////////////////////////////////////////////////////////// for (size_t i = 0; i < _get_num_radios(); i++) { - _leds[i] = gpio_atr::gpio_atr_3000::make_write_only(_get_ctrl(i), regs::sr_addr(regs::LEDS)); - _leds[i]->set_atr_mode(usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL); + _leds[i] = gpio_atr::gpio_atr_3000::make_write_only( + _get_ctrl(i), regs::sr_addr(regs::LEDS)); + _leds[i]->set_atr_mode( + usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL); - _rx_fe_map[i].core = rx_frontend_core_3000::make(_get_ctrl(i), regs::sr_addr(x300_regs::RX_FE_BASE)); + _rx_fe_map[i].core = rx_frontend_core_3000::make( + _get_ctrl(i), regs::sr_addr(x300_regs::RX_FE_BASE)); _rx_fe_map[i].core->set_adc_rate(_radio_clk_rate); _rx_fe_map[i].core->set_dc_offset(rx_frontend_core_3000::DEFAULT_DC_OFFSET_VALUE); - _rx_fe_map[i].core->set_dc_offset_auto(rx_frontend_core_3000::DEFAULT_DC_OFFSET_ENABLE); - _rx_fe_map[i].core->populate_subtree(_tree->subtree(_root_path / "rx_fe_corrections" / i)); + _rx_fe_map[i].core->set_dc_offset_auto( + rx_frontend_core_3000::DEFAULT_DC_OFFSET_ENABLE); + _rx_fe_map[i].core->populate_subtree( + _tree->subtree(_root_path / "rx_fe_corrections" / i)); - _tx_fe_map[i].core = tx_frontend_core_200::make(_get_ctrl(i), regs::sr_addr(x300_regs::TX_FE_BASE)); + _tx_fe_map[i].core = tx_frontend_core_200::make( + _get_ctrl(i), regs::sr_addr(x300_regs::TX_FE_BASE)); _tx_fe_map[i].core->set_dc_offset(tx_frontend_core_200::DEFAULT_DC_OFFSET_VALUE); - _tx_fe_map[i].core->set_iq_balance(tx_frontend_core_200::DEFAULT_IQ_BALANCE_VALUE); - _tx_fe_map[i].core->populate_subtree(_tree->subtree(_root_path / "tx_fe_corrections" / i)); + _tx_fe_map[i].core->set_iq_balance( + tx_frontend_core_200::DEFAULT_IQ_BALANCE_VALUE); + _tx_fe_map[i].core->populate_subtree( + _tree->subtree(_root_path / "tx_fe_corrections" / i)); //////////////////////////////////////////////////////////////// // Bind the daughterboard command time to the motherboard level property @@ -152,16 +168,19 @@ UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(x300_radio_ctrl) if (_tree->exists(fs_path("time") / "cmd")) { _tree->access<time_spec_t>(fs_path("time") / "cmd") - .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_fe_cmd_time, this, _1, i)); + .add_coerced_subscriber( + boost::bind(&x300_radio_ctrl_impl::set_fe_cmd_time, this, _1, i)); } } //////////////////////////////////////////////////////////////// // Update default SPP (overwrites the default value from the XML file) //////////////////////////////////////////////////////////////// - const size_t max_bytes_header = uhd::transport::vrt::chdr::max_if_hdr_words64 * sizeof(uint64_t); - const size_t default_spp = (_tree->access<size_t>("mtu/recv").get() - max_bytes_header) - / (2 * sizeof(int16_t)); + const size_t max_bytes_header = + uhd::transport::vrt::chdr::max_if_hdr_words64 * sizeof(uint64_t); + const size_t default_spp = + (_tree->access<size_t>("mtu/recv").get() - max_bytes_header) + / (2 * sizeof(int16_t)); _tree->access<int>(get_arg_path("spp") / "value").set(default_spp); } @@ -173,21 +192,19 @@ x300_radio_ctrl_impl::~x300_radio_ctrl_impl() _tree->remove(fs_path("tx_codecs" / _radio_slot)); _tree->remove(_root_path / "rx_fe_corrections"); _tree->remove(_root_path / "tx_fe_corrections"); - if (_radio_type==PRIMARY) { - for(const gpio_atr::gpio_attr_map_t::value_type attr: gpio_atr::gpio_attr_map) { + if (_radio_type == PRIMARY) { + for (const gpio_atr::gpio_attr_map_t::value_type attr : + gpio_atr::gpio_attr_map) { _tree->remove(fs_path("gpio") / "FP0" / attr.second); } } // Reset peripherals - if (_radio_type==PRIMARY) { + if (_radio_type == PRIMARY) { _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 1); _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 0); - } - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_ENABLED, 0); - _regs->misc_outs_reg.flush(); - ) - + } _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_ENABLED, 0); + _regs->misc_outs_reg.flush();) } /**************************************************************************** @@ -197,102 +214,129 @@ double x300_radio_ctrl_impl::set_rate(double rate) { const double actual_rate = get_rate(); if (not uhd::math::frequencies_are_equal(rate, actual_rate)) { - UHD_LOGGER_WARNING("X300 RADIO") << "Requesting invalid sampling rate from device: " << rate/1e6 << " MHz. Actual rate is: " << actual_rate/1e6 << " MHz." ; + UHD_LOGGER_WARNING("X300 RADIO") + << "Requesting invalid sampling rate from device: " << rate / 1e6 + << " MHz. Actual rate is: " << actual_rate / 1e6 << " MHz."; } // On X3x0, tick rate can't actually be changed at runtime return actual_rate; } -void x300_radio_ctrl_impl::set_fe_cmd_time(const time_spec_t &time, const size_t chan) +void x300_radio_ctrl_impl::set_fe_cmd_time(const time_spec_t& time, const size_t chan) { - if (_tree->exists(fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "time" / "cmd"))) { - _tree->access<time_spec_t>( - fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "time" / "cmd") - ).set(time); + if (_tree->exists(fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "time" / "cmd"))) { + _tree + ->access<time_spec_t>( + fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "time" / "cmd")) + .set(time); } } -void x300_radio_ctrl_impl::set_tx_antenna(const std::string &ant, const size_t chan) +void x300_radio_ctrl_impl::set_tx_antenna(const std::string& ant, const size_t chan) { - _tree->access<std::string>( - fs_path("dboards" / _radio_slot / "tx_frontends" / _tx_fe_map.at(chan).db_fe_name / "antenna" / "value") - ).set(ant); + _tree + ->access<std::string>( + fs_path("dboards" / _radio_slot / "tx_frontends" + / _tx_fe_map.at(chan).db_fe_name / "antenna" / "value")) + .set(ant); } std::string x300_radio_ctrl_impl::get_tx_antenna(const size_t chan) { - return _tree->access<std::string>( - fs_path("dboards" / _radio_slot / "tx_frontends" / _tx_fe_map.at(chan).db_fe_name / "antenna" / "value") - ).get(); + return _tree + ->access<std::string>( + fs_path("dboards" / _radio_slot / "tx_frontends" + / _tx_fe_map.at(chan).db_fe_name / "antenna" / "value")) + .get(); } -void x300_radio_ctrl_impl::set_rx_antenna(const std::string &ant, const size_t chan) +void x300_radio_ctrl_impl::set_rx_antenna(const std::string& ant, const size_t chan) { - _tree->access<std::string>( - fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "antenna" / "value") - ).set(ant); + _tree + ->access<std::string>( + fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "antenna" / "value")) + .set(ant); } std::string x300_radio_ctrl_impl::get_rx_antenna(const size_t chan) { - return _tree->access<std::string>( - fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "antenna" / "value") - ).get(); + return _tree + ->access<std::string>( + fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "antenna" / "value")) + .get(); } double x300_radio_ctrl_impl::set_tx_frequency(const double freq, const size_t chan) { - return _tree->access<double>( - fs_path("dboards" / _radio_slot / "tx_frontends" / _tx_fe_map.at(chan).db_fe_name / "freq" / "value") - ).set(freq).get(); + return _tree + ->access<double>(fs_path("dboards" / _radio_slot / "tx_frontends" + / _tx_fe_map.at(chan).db_fe_name / "freq" / "value")) + .set(freq) + .get(); } double x300_radio_ctrl_impl::get_tx_frequency(const size_t chan) { - return _tree->access<double>( - fs_path("dboards" / _radio_slot / "tx_frontends" / _tx_fe_map.at(chan).db_fe_name / "freq" / "value") - ).get(); + return _tree + ->access<double>(fs_path("dboards" / _radio_slot / "tx_frontends" + / _tx_fe_map.at(chan).db_fe_name / "freq" / "value")) + .get(); } double x300_radio_ctrl_impl::set_rx_frequency(const double freq, const size_t chan) { - return _tree->access<double>( - fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "freq" / "value") - ).set(freq).get(); + return _tree + ->access<double>(fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "freq" / "value")) + .set(freq) + .get(); } double x300_radio_ctrl_impl::get_rx_frequency(const size_t chan) { - return _tree->access<double>( - fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "freq" / "value") - ).get(); + return _tree + ->access<double>(fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "freq" / "value")) + .get(); } double x300_radio_ctrl_impl::set_rx_bandwidth(const double bandwidth, const size_t chan) { - return _tree->access<double>( - fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "bandwidth" / "value") - ).set(bandwidth).get(); + return _tree + ->access<double>( + fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "bandwidth" / "value")) + .set(bandwidth) + .get(); } double x300_radio_ctrl_impl::get_rx_bandwidth(const size_t chan) { - return _tree->access<double>( - fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "bandwidth" / "value") - ).get(); + return _tree + ->access<double>( + fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "bandwidth" / "value")) + .get(); } 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"); + // 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(); + 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."; + 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; } @@ -300,15 +344,18 @@ double x300_radio_ctrl_impl::set_tx_gain(const double gain, const size_t 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"); + // 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(); + 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."; + 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; } @@ -317,79 +364,105 @@ double x300_radio_ctrl_impl::set_rx_gain(const double gain, const size_t chan) std::vector<std::string> x300_radio_ctrl_impl::get_rx_lo_names(const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); std::vector<std::string> lo_names; if (_tree->exists(rx_fe_fe_root / "los")) { - for(const std::string &name: _tree->list(rx_fe_fe_root / "los")) { + for (const std::string& name : _tree->list(rx_fe_fe_root / "los")) { lo_names.push_back(name); } } return lo_names; } -std::vector<std::string> x300_radio_ctrl_impl::get_rx_lo_sources(const std::string &name, const size_t chan) +std::vector<std::string> x300_radio_ctrl_impl::get_rx_lo_sources( + const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { if (_tree->exists(rx_fe_fe_root / "los" / ALL_LOS)) { - //Special value ALL_LOS support atomically sets the source for all LOs - return _tree->access< std::vector<std::string> >(rx_fe_fe_root / "los" / ALL_LOS / "source" / "options").get(); + // Special value ALL_LOS support atomically sets the source for all LOs + return _tree + ->access<std::vector<std::string>>( + rx_fe_fe_root / "los" / ALL_LOS / "source" / "options") + .get(); } else { return std::vector<std::string>(); } } else { if (_tree->exists(rx_fe_fe_root / "los")) { - return _tree->access< std::vector<std::string> >(rx_fe_fe_root / "los" / name / "source" / "options").get(); + return _tree + ->access<std::vector<std::string>>( + rx_fe_fe_root / "los" / name / "source" / "options") + .get(); } else { throw uhd::runtime_error("Could not find LO stage " + name); } } } else { // If the daughterboard doesn't expose it's LO(s) then it can only be internal - return std::vector<std::string> (1, "internal"); + return std::vector<std::string>(1, "internal"); } } -void x300_radio_ctrl_impl::set_rx_lo_source(const std::string &src, const std::string &name, const size_t chan) +void x300_radio_ctrl_impl::set_rx_lo_source( + const std::string& src, const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { if (_tree->exists(rx_fe_fe_root / "los" / ALL_LOS)) { - //Special value ALL_LOS support atomically sets the source for all LOs - _tree->access<std::string>(rx_fe_fe_root / "los" / ALL_LOS / "source" / "value").set(src); + // Special value ALL_LOS support atomically sets the source for all LOs + _tree + ->access<std::string>( + rx_fe_fe_root / "los" / ALL_LOS / "source" / "value") + .set(src); } else { - for(const std::string &n: _tree->list(rx_fe_fe_root / "los")) { + for (const std::string& n : _tree->list(rx_fe_fe_root / "los")) { this->set_rx_lo_source(src, n, chan); } } } else { if (_tree->exists(rx_fe_fe_root / "los")) { - _tree->access<std::string>(rx_fe_fe_root / "los" / name / "source" / "value").set(src); + _tree + ->access<std::string>( + rx_fe_fe_root / "los" / name / "source" / "value") + .set(src); } else { throw uhd::runtime_error("Could not find LO stage " + name); } } } else { - throw uhd::runtime_error("This device does not support manual configuration of LOs"); + throw uhd::runtime_error( + "This device does not support manual configuration of LOs"); } } -const std::string x300_radio_ctrl_impl::get_rx_lo_source(const std::string &name, const size_t chan) +const std::string x300_radio_ctrl_impl::get_rx_lo_source( + const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { - //Special value ALL_LOS support atomically sets the source for all LOs - return _tree->access<std::string>(rx_fe_fe_root / "los" / ALL_LOS / "source" / "value").get(); + // Special value ALL_LOS support atomically sets the source for all LOs + return _tree + ->access<std::string>( + rx_fe_fe_root / "los" / ALL_LOS / "source" / "value") + .get(); } else { if (_tree->exists(rx_fe_fe_root / "los")) { - return _tree->access<std::string>(rx_fe_fe_root / "los" / name / "source" / "value").get(); + return _tree + ->access<std::string>( + rx_fe_fe_root / "los" / name / "source" / "value") + .get(); } else { throw uhd::runtime_error("Could not find LO stage " + name); } @@ -400,17 +473,20 @@ const std::string x300_radio_ctrl_impl::get_rx_lo_source(const std::string &name } } -void x300_radio_ctrl_impl::set_rx_lo_export_enabled(bool enabled, const std::string &name, const size_t chan) +void x300_radio_ctrl_impl::set_rx_lo_export_enabled( + bool enabled, const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { if (_tree->exists(rx_fe_fe_root / "los" / ALL_LOS)) { - //Special value ALL_LOS support atomically sets the source for all LOs - _tree->access<bool>(rx_fe_fe_root / "los" / ALL_LOS / "export").set(enabled); + // Special value ALL_LOS support atomically sets the source for all LOs + _tree->access<bool>(rx_fe_fe_root / "los" / ALL_LOS / "export") + .set(enabled); } else { - for(const std::string &n: _tree->list(rx_fe_fe_root / "los")) { + for (const std::string& n : _tree->list(rx_fe_fe_root / "los")) { this->set_rx_lo_export_enabled(enabled, n, chan); } } @@ -422,17 +498,20 @@ void x300_radio_ctrl_impl::set_rx_lo_export_enabled(bool enabled, const std::str } } } else { - throw uhd::runtime_error("This device does not support manual configuration of LOs"); + throw uhd::runtime_error( + "This device does not support manual configuration of LOs"); } } -bool x300_radio_ctrl_impl::get_rx_lo_export_enabled(const std::string &name, const size_t chan) +bool x300_radio_ctrl_impl::get_rx_lo_export_enabled( + const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { - //Special value ALL_LOS support atomically sets the source for all LOs + // Special value ALL_LOS support atomically sets the source for all LOs return _tree->access<bool>(rx_fe_fe_root / "los" / ALL_LOS / "export").get(); } else { if (_tree->exists(rx_fe_fe_root / "los")) { @@ -447,56 +526,73 @@ bool x300_radio_ctrl_impl::get_rx_lo_export_enabled(const std::string &name, con } } -double x300_radio_ctrl_impl::set_rx_lo_freq(double freq, const std::string &name, const size_t chan) +double x300_radio_ctrl_impl::set_rx_lo_freq( + double freq, const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { - throw uhd::runtime_error("LO frequency must be set for each stage individually"); + throw uhd::runtime_error( + "LO frequency must be set for each stage individually"); } else { if (_tree->exists(rx_fe_fe_root / "los")) { - _tree->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value").set(freq); - return _tree->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value").get(); + _tree->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value") + .set(freq); + return _tree + ->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value") + .get(); } else { throw uhd::runtime_error("Could not find LO stage " + name); } } } else { - throw uhd::runtime_error("This device does not support manual configuration of LOs"); + throw uhd::runtime_error( + "This device does not support manual configuration of LOs"); } } -double x300_radio_ctrl_impl::get_rx_lo_freq(const std::string &name, const size_t chan) +double x300_radio_ctrl_impl::get_rx_lo_freq(const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { - throw uhd::runtime_error("LO frequency must be retrieved for each stage individually"); + throw uhd::runtime_error( + "LO frequency must be retrieved for each stage individually"); } else { if (_tree->exists(rx_fe_fe_root / "los")) { - return _tree->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value").get(); + return _tree + ->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value") + .get(); } else { throw uhd::runtime_error("Could not find LO stage " + name); } } } else { // Return actual RF frequency if the daughterboard doesn't expose it's LO(s) - return _tree->access<double>(rx_fe_fe_root / "freq" /" value").get(); + return _tree->access<double>(rx_fe_fe_root / "freq" / " value").get(); } } -freq_range_t x300_radio_ctrl_impl::get_rx_lo_freq_range(const std::string &name, const size_t chan) +freq_range_t x300_radio_ctrl_impl::get_rx_lo_freq_range( + const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { - throw uhd::runtime_error("LO frequency range must be retrieved for each stage individually"); + throw uhd::runtime_error( + "LO frequency range must be retrieved for each stage individually"); } else { if (_tree->exists(rx_fe_fe_root / "los")) { - return _tree->access<freq_range_t>(rx_fe_fe_root / "los" / name / "freq" / "range").get(); + return _tree + ->access<freq_range_t>( + rx_fe_fe_root / "los" / name / "freq" / "range") + .get(); } else { throw uhd::runtime_error("Could not find LO stage " + name); } @@ -508,21 +604,19 @@ freq_range_t x300_radio_ctrl_impl::get_rx_lo_freq_range(const std::string &name, } template <typename map_type> -static size_t _get_chan_from_map(std::map<size_t, map_type> map, const std::string &fe) +static size_t _get_chan_from_map(std::map<size_t, map_type> map, const std::string& fe) { for (auto it = map.begin(); it != map.end(); ++it) { if (it->second.db_fe_name == fe) { return it->first; } - } - throw uhd::runtime_error(str( - boost::format("Invalid daughterboard frontend name: %s") - % fe - )); + throw uhd::runtime_error( + str(boost::format("Invalid daughterboard frontend name: %s") % fe)); } -size_t x300_radio_ctrl_impl::get_chan_from_dboard_fe(const std::string &fe, const uhd::direction_t direction) +size_t x300_radio_ctrl_impl::get_chan_from_dboard_fe( + const std::string& fe, const uhd::direction_t direction) { switch (direction) { case uhd::TX_DIRECTION: @@ -534,7 +628,8 @@ size_t x300_radio_ctrl_impl::get_chan_from_dboard_fe(const std::string &fe, cons } } -std::string x300_radio_ctrl_impl::get_dboard_fe_from_chan(const size_t chan, const uhd::direction_t direction) +std::string x300_radio_ctrl_impl::get_dboard_fe_from_chan( + const size_t chan, const uhd::direction_t direction) { switch (direction) { case uhd::TX_DIRECTION: @@ -565,61 +660,83 @@ double x300_radio_ctrl_impl::get_output_samp_rate(size_t chan) std::vector<std::string> x300_radio_ctrl_impl::get_gpio_banks() const { std::vector<std::string> banks{"RX", "TX"}; - // These pairs are the same, but RXA/TXA are from pre-rfnoc era and are kept for backward compat: - banks.push_back("RX"+_radio_slot); - banks.push_back("TX"+_radio_slot); + // These pairs are the same, but RXA/TXA are from pre-rfnoc era and are kept for + // backward compat: + banks.push_back("RX" + _radio_slot); + banks.push_back("TX" + _radio_slot); if (_fp_gpio) { banks.push_back("FP0"); } return banks; } -void x300_radio_ctrl_impl::set_gpio_attr( - const std::string &bank, - const std::string &attr, - const uint32_t value, - const uint32_t mask -) { +void x300_radio_ctrl_impl::set_gpio_attr(const std::string& bank, + const std::string& attr, + const uint32_t value, + const uint32_t mask) +{ if (bank == "FP0" and _fp_gpio) { - const uint32_t current = _tree->access<uint32_t>(fs_path("gpio") / bank / attr).get(); + const uint32_t current = + _tree->access<uint32_t>(fs_path("gpio") / bank / attr).get(); const uint32_t new_value = (current & ~mask) | (value & mask); _tree->access<uint32_t>(fs_path("gpio") / bank / attr).set(new_value); return; } - if (bank.size() > 2 and bank[1] == 'X') - { - const std::string name = bank.substr(2); - const dboard_iface::unit_t unit = (bank[0] == 'R')? dboard_iface::UNIT_RX : dboard_iface::UNIT_TX; - dboard_iface::sptr iface = _tree->access<dboard_iface::sptr>(fs_path("dboards") / name / "iface").get(); - if (attr == "CTRL") iface->set_pin_ctrl(unit, uint16_t(value), uint16_t(mask)); - if (attr == "DDR") iface->set_gpio_ddr(unit, uint16_t(value), uint16_t(mask)); - if (attr == "OUT") iface->set_gpio_out(unit, uint16_t(value), uint16_t(mask)); - if (attr == "ATR_0X") iface->set_atr_reg(unit, gpio_atr::ATR_REG_IDLE, uint16_t(value), uint16_t(mask)); - if (attr == "ATR_RX") iface->set_atr_reg(unit, gpio_atr::ATR_REG_RX_ONLY, uint16_t(value), uint16_t(mask)); - if (attr == "ATR_TX") iface->set_atr_reg(unit, gpio_atr::ATR_REG_TX_ONLY, uint16_t(value), uint16_t(mask)); - if (attr == "ATR_XX") iface->set_atr_reg(unit, gpio_atr::ATR_REG_FULL_DUPLEX, uint16_t(value), uint16_t(mask)); + if (bank.size() > 2 and bank[1] == 'X') { + const std::string name = bank.substr(2); + const dboard_iface::unit_t unit = (bank[0] == 'R') ? dboard_iface::UNIT_RX + : dboard_iface::UNIT_TX; + dboard_iface::sptr iface = + _tree->access<dboard_iface::sptr>(fs_path("dboards") / name / "iface").get(); + if (attr == "CTRL") + iface->set_pin_ctrl(unit, uint16_t(value), uint16_t(mask)); + if (attr == "DDR") + iface->set_gpio_ddr(unit, uint16_t(value), uint16_t(mask)); + if (attr == "OUT") + iface->set_gpio_out(unit, uint16_t(value), uint16_t(mask)); + if (attr == "ATR_0X") + iface->set_atr_reg( + unit, gpio_atr::ATR_REG_IDLE, uint16_t(value), uint16_t(mask)); + if (attr == "ATR_RX") + iface->set_atr_reg( + unit, gpio_atr::ATR_REG_RX_ONLY, uint16_t(value), uint16_t(mask)); + if (attr == "ATR_TX") + iface->set_atr_reg( + unit, gpio_atr::ATR_REG_TX_ONLY, uint16_t(value), uint16_t(mask)); + if (attr == "ATR_XX") + iface->set_atr_reg( + unit, gpio_atr::ATR_REG_FULL_DUPLEX, uint16_t(value), uint16_t(mask)); } } uint32_t x300_radio_ctrl_impl::get_gpio_attr( - const std::string &bank, - const std::string &attr -) { + const std::string& bank, const std::string& attr) +{ if (bank == "FP0" and _fp_gpio) { return uint32_t(_tree->access<uint64_t>(fs_path("gpio") / bank / attr).get()); } if (bank.size() > 2 and bank[1] == 'X') { - const std::string name = bank.substr(2); - const dboard_iface::unit_t unit = (bank[0] == 'R')? dboard_iface::UNIT_RX : dboard_iface::UNIT_TX; - dboard_iface::sptr iface = _tree->access<dboard_iface::sptr>(fs_path("dboards") / name / "iface").get(); - if (attr == "CTRL") return iface->get_pin_ctrl(unit); - if (attr == "DDR") return iface->get_gpio_ddr(unit); - if (attr == "OUT") return iface->get_gpio_out(unit); - if (attr == "ATR_0X") return iface->get_atr_reg(unit, gpio_atr::ATR_REG_IDLE); - if (attr == "ATR_RX") return iface->get_atr_reg(unit, gpio_atr::ATR_REG_RX_ONLY); - if (attr == "ATR_TX") return iface->get_atr_reg(unit, gpio_atr::ATR_REG_TX_ONLY); - if (attr == "ATR_XX") return iface->get_atr_reg(unit, gpio_atr::ATR_REG_FULL_DUPLEX); - if (attr == "READBACK") return iface->read_gpio(unit); + const std::string name = bank.substr(2); + const dboard_iface::unit_t unit = (bank[0] == 'R') ? dboard_iface::UNIT_RX + : dboard_iface::UNIT_TX; + dboard_iface::sptr iface = + _tree->access<dboard_iface::sptr>(fs_path("dboards") / name / "iface").get(); + if (attr == "CTRL") + return iface->get_pin_ctrl(unit); + if (attr == "DDR") + return iface->get_gpio_ddr(unit); + if (attr == "OUT") + return iface->get_gpio_out(unit); + if (attr == "ATR_0X") + return iface->get_atr_reg(unit, gpio_atr::ATR_REG_IDLE); + if (attr == "ATR_RX") + return iface->get_atr_reg(unit, gpio_atr::ATR_REG_RX_ONLY); + if (attr == "ATR_TX") + return iface->get_atr_reg(unit, gpio_atr::ATR_REG_TX_ONLY); + if (attr == "ATR_XX") + return iface->get_atr_reg(unit, gpio_atr::ATR_REG_FULL_DUPLEX); + if (attr == "READBACK") + return iface->read_gpio(unit); } return 0; } @@ -627,11 +744,10 @@ uint32_t x300_radio_ctrl_impl::get_gpio_attr( /**************************************************************************** * Radio control and setup ***************************************************************************/ -void x300_radio_ctrl_impl::setup_radio( - uhd::i2c_iface::sptr zpu_i2c, - x300_clock_ctrl::sptr clock, - bool ignore_cal_file, - bool verbose) +void x300_radio_ctrl_impl::setup_radio(uhd::i2c_iface::sptr zpu_i2c, + x300_clock_ctrl::sptr clock, + bool ignore_cal_file, + bool verbose) { _self_cal_adc_capture_delay(verbose); _ignore_cal_file = ignore_cal_file; @@ -644,57 +760,56 @@ void x300_radio_ctrl_impl::setup_radio( static const size_t TX_EEPROM_ADDR = 0x4; static const size_t GDB_EEPROM_ADDR = 0x1; const static std::vector<size_t> EEPROM_ADDRS{ - RX_EEPROM_ADDR, - TX_EEPROM_ADDR, - GDB_EEPROM_ADDR - }; + RX_EEPROM_ADDR, TX_EEPROM_ADDR, GDB_EEPROM_ADDR}; const static std::vector<std::string> EEPROM_PATHS{ - "rx_eeprom", - "tx_eeprom", - "gdb_eeprom" - }; + "rx_eeprom", "tx_eeprom", "gdb_eeprom"}; const size_t DB_OFFSET = (_radio_slot == "A") ? 0x0 : 0x2; - const fs_path db_path = ("dboards" / _radio_slot); + const fs_path db_path = ("dboards" / _radio_slot); for (size_t i = 0; i < EEPROM_ADDRS.size(); i++) { const size_t addr = EEPROM_ADDRS[i] + DB_OFFSET; - //Load EEPROM + // Load EEPROM _db_eeproms[addr].load(*zpu_i2c, BASE_ADDR | addr); - //Add to tree + // Add to tree _tree->create<dboard_eeprom_t>(db_path / EEPROM_PATHS[i]) .set(_db_eeproms[addr]) .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::_set_db_eeprom, - this, zpu_i2c, (BASE_ADDR | addr), _1)); + this, + zpu_i2c, + (BASE_ADDR | addr), + _1)); } - //create a new dboard interface + // create a new dboard interface x300_dboard_iface_config_t db_config; db_config.gpio = gpio_atr::db_gpio_atr_3000::make(_get_ctrl(IO_MASTER_RADIO), radio_ctrl_impl::regs::sr_addr(radio_ctrl_impl::regs::GPIO), - radio_ctrl_impl::regs::rb_addr(radio_ctrl_impl::regs::RB_DB_GPIO) - ); - db_config.spi = _spi; + radio_ctrl_impl::regs::rb_addr(radio_ctrl_impl::regs::RB_DB_GPIO)); + db_config.spi = _spi; db_config.rx_spi_slaveno = DB_RX_SEN; db_config.tx_spi_slaveno = DB_TX_SEN; - db_config.i2c = zpu_i2c; - db_config.clock = clock; - db_config.which_rx_clk = (_radio_slot == "A") ? X300_CLOCK_WHICH_DB0_RX : X300_CLOCK_WHICH_DB1_RX; - db_config.which_tx_clk = (_radio_slot == "A") ? X300_CLOCK_WHICH_DB0_TX : X300_CLOCK_WHICH_DB1_TX; - db_config.dboard_slot = (_radio_slot == "A")? 0 : 1; + db_config.i2c = zpu_i2c; + db_config.clock = clock; + db_config.which_rx_clk = (_radio_slot == "A") ? X300_CLOCK_WHICH_DB0_RX + : X300_CLOCK_WHICH_DB1_RX; + db_config.which_tx_clk = (_radio_slot == "A") ? X300_CLOCK_WHICH_DB0_TX + : X300_CLOCK_WHICH_DB1_TX; + db_config.dboard_slot = (_radio_slot == "A") ? 0 : 1; db_config.cmd_time_ctrl = _get_ctrl(IO_MASTER_RADIO); - //create a new dboard manager - boost::shared_ptr<x300_dboard_iface> db_iface = boost::make_shared<x300_dboard_iface>(db_config); - _db_manager = dboard_manager::make( - _db_eeproms[RX_EEPROM_ADDR + DB_OFFSET], + // create a new dboard manager + boost::shared_ptr<x300_dboard_iface> db_iface = + boost::make_shared<x300_dboard_iface>(db_config); + _db_manager = dboard_manager::make(_db_eeproms[RX_EEPROM_ADDR + DB_OFFSET], _db_eeproms[TX_EEPROM_ADDR + DB_OFFSET], _db_eeproms[GDB_EEPROM_ADDR + DB_OFFSET], - db_iface, _tree->subtree(db_path), + db_iface, + _tree->subtree(db_path), true // defer daughterboard intitialization ); size_t rx_chan = 0, tx_chan = 0; - for(const std::string& fe: _db_manager->get_rx_frontends()) { + for (const std::string& fe : _db_manager->get_rx_frontends()) { if (rx_chan >= _get_num_radios()) { break; } @@ -702,12 +817,14 @@ void x300_radio_ctrl_impl::setup_radio( db_iface->add_rx_fe(fe, _rx_fe_map[rx_chan].core); const fs_path fe_path(db_path / "rx_frontends" / fe); const std::string conn = _tree->access<std::string>(fe_path / "connection").get(); - const double if_freq = (_tree->exists(fe_path / "if_freq/value")) ? - _tree->access<double>(fe_path / "if_freq/value").get() : 0.0; + const double if_freq = + (_tree->exists(fe_path / "if_freq/value")) + ? _tree->access<double>(fe_path / "if_freq/value").get() + : 0.0; _rx_fe_map[rx_chan].core->set_fe_connection(usrp::fe_connection_t(conn, if_freq)); rx_chan++; } - for(const std::string& fe: _db_manager->get_tx_frontends()) { + for (const std::string& fe : _db_manager->get_tx_frontends()) { if (tx_chan >= _get_num_radios()) { break; } @@ -722,40 +839,63 @@ void x300_radio_ctrl_impl::setup_radio( // Initialize the daughterboards now that frontend cores and connections exist _db_manager->initialize_dboards(); - //now that dboard is created -- register into rx antenna event + // now that dboard is created -- register into rx antenna event if (not _rx_fe_map.empty()) { for (size_t i = 0; i < _get_num_radios(); i++) { - if (_tree->exists(db_path / "rx_frontends" / _rx_fe_map[i].db_fe_name / "antenna" / "value")) { - // We need a desired subscriber for antenna/value because the experts don't coerce that property. - _tree->access<std::string>(db_path / "rx_frontends" / _rx_fe_map[i].db_fe_name / "antenna" / "value") - .add_desired_subscriber(boost::bind(&x300_radio_ctrl_impl::_update_atr_leds, this, _1, i)); - _update_atr_leds(_tree->access<std::string> - (db_path / "rx_frontends" / _rx_fe_map[i].db_fe_name / "antenna" / "value").get(), i); + if (_tree->exists(db_path / "rx_frontends" / _rx_fe_map[i].db_fe_name + / "antenna" / "value")) { + // We need a desired subscriber for antenna/value because the experts + // don't coerce that property. + _tree + ->access<std::string>(db_path / "rx_frontends" + / _rx_fe_map[i].db_fe_name / "antenna" + / "value") + .add_desired_subscriber(boost::bind( + &x300_radio_ctrl_impl::_update_atr_leds, this, _1, i)); + _update_atr_leds(_tree + ->access<std::string>(db_path / "rx_frontends" + / _rx_fe_map[i].db_fe_name + / "antenna" / "value") + .get(), + i); } else { - _update_atr_leds("", i); //init anyway, even if never called + _update_atr_leds("", i); // init anyway, even if never called } } } - //bind frontend corrections to the dboard freq props + // bind frontend corrections to the dboard freq props const fs_path db_tx_fe_path = db_path / "tx_frontends"; if (not _tx_fe_map.empty()) { for (size_t i = 0; i < _get_num_radios(); i++) { - if (_tree->exists(db_tx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")) { - _tree->access<double>(db_tx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value") - .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_tx_fe_corrections, this, db_path, - _root_path / "tx_fe_corrections" / _tx_fe_map[i].db_fe_name, _1)); + if (_tree->exists( + db_tx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")) { + _tree + ->access<double>( + db_tx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value") + .add_coerced_subscriber( + boost::bind(&x300_radio_ctrl_impl::set_tx_fe_corrections, + this, + db_path, + _root_path / "tx_fe_corrections" / _tx_fe_map[i].db_fe_name, + _1)); } } } const fs_path db_rx_fe_path = db_path / "rx_frontends"; if (not _rx_fe_map.empty()) { for (size_t i = 0; i < _get_num_radios(); i++) { - if (_tree->exists(db_rx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")) { - _tree->access<double>(db_rx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value") - .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_rx_fe_corrections, this, db_path, - _root_path / "rx_fe_corrections" / _tx_fe_map[i].db_fe_name, - _1)); + if (_tree->exists( + db_rx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")) { + _tree + ->access<double>( + db_rx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value") + .add_coerced_subscriber( + boost::bind(&x300_radio_ctrl_impl::set_rx_fe_corrections, + this, + db_path, + _root_path / "rx_fe_corrections" / _tx_fe_map[i].db_fe_name, + _1)); } } } @@ -764,7 +904,7 @@ void x300_radio_ctrl_impl::setup_radio( // Set tick rate //////////////////////////////////////////////////////////////// const double tick_rate = get_output_samp_rate(0); - if (_radio_type==PRIMARY) { + if (_radio_type == PRIMARY) { // Slot A is the highlander timekeeper _tree->access<double>("tick_rate").set(tick_rate); } @@ -772,20 +912,16 @@ void x300_radio_ctrl_impl::setup_radio( } void x300_radio_ctrl_impl::set_rx_fe_corrections( - const fs_path &db_path, - const fs_path &rx_fe_corr_path, - const double lo_freq -) { + const fs_path& db_path, const fs_path& rx_fe_corr_path, const double lo_freq) +{ if (not _ignore_cal_file) { apply_rx_fe_corrections(_tree, db_path, rx_fe_corr_path, lo_freq); } } void x300_radio_ctrl_impl::set_tx_fe_corrections( - const fs_path &db_path, - const fs_path &tx_fe_corr_path, - const double lo_freq -) { + const fs_path& db_path, const fs_path& tx_fe_corr_path, const double lo_freq) +{ if (not _ignore_cal_file) { apply_tx_fe_corrections(_tree, db_path, tx_fe_corr_path, lo_freq); } @@ -793,7 +929,7 @@ void x300_radio_ctrl_impl::set_tx_fe_corrections( void x300_radio_ctrl_impl::reset_codec() { - if (_radio_type==PRIMARY) { //ADC/DAC reset lines only exist in Radio0 + if (_radio_type == PRIMARY) { // ADC/DAC reset lines only exist in Radio0 _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 1); _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 0); _regs->misc_outs_reg.flush(); @@ -809,29 +945,34 @@ void x300_radio_ctrl_impl::reset_codec() void x300_radio_ctrl_impl::self_test_adc(uint32_t ramp_time_ms) { - //Bypass all front-end corrections + // Bypass all front-end corrections for (size_t i = 0; i < _get_num_radios(); i++) { _rx_fe_map[i].core->bypass_all(true); } - //Test basic patterns - _adc->set_test_word("ones", "ones"); _check_adc(0xfffcfffc); - _adc->set_test_word("zeros", "zeros"); _check_adc(0x00000000); - _adc->set_test_word("ones", "zeros"); _check_adc(0xfffc0000); - _adc->set_test_word("zeros", "ones"); _check_adc(0x0000fffc); + // Test basic patterns + _adc->set_test_word("ones", "ones"); + _check_adc(0xfffcfffc); + _adc->set_test_word("zeros", "zeros"); + _check_adc(0x00000000); + _adc->set_test_word("ones", "zeros"); + _check_adc(0xfffc0000); + _adc->set_test_word("zeros", "ones"); + _check_adc(0x0000fffc); for (size_t k = 0; k < 14; k++) { _adc->set_test_word("zeros", "custom", 1 << k); - _check_adc(1 << (k+2)); + _check_adc(1 << (k + 2)); } for (size_t k = 0; k < 14; k++) { _adc->set_test_word("custom", "zeros", 1 << k); - _check_adc(1 << (k+18)); + _check_adc(1 << (k + 18)); } - //Turn on ramp pattern test + // Turn on ramp pattern test _adc->set_test_word("ramp", "ramp"); _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); - //Sleep added for SPI transactions to finish and ramp to start before checker is enabled. + // Sleep added for SPI transactions to finish and ramp to start before checker is + // enabled. std::this_thread::sleep_for(std::chrono::microseconds(1000)); _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); @@ -855,37 +996,46 @@ void x300_radio_ctrl_impl::self_test_adc(uint32_t ramp_time_ms) else q_status = "Not Locked!"; - //Return to normal mode + // Return to normal mode _adc->set_test_word("normal", "normal"); if ((i_status != "Good") or (q_status != "Good")) { throw uhd::runtime_error( - (boost::format("ADC self-test failed for %s. Ramp checker status: {ADC_A=%s, ADC_B=%s}")%unique_id()%i_status%q_status).str()); + (boost::format( + "ADC self-test failed for %s. Ramp checker status: {ADC_A=%s, ADC_B=%s}") + % unique_id() % i_status % q_status) + .str()); } - //Restore front-end corrections + // Restore front-end corrections for (size_t i = 0; i < _get_num_radios(); i++) { _rx_fe_map[i].core->bypass_all(false); } } -void x300_radio_ctrl_impl::extended_adc_test(const std::vector<x300_radio_ctrl_impl::sptr>& radios, double duration_s) +void x300_radio_ctrl_impl::extended_adc_test( + const std::vector<x300_radio_ctrl_impl::sptr>& radios, double duration_s) { static const size_t SECS_PER_ITER = 5; - UHD_LOGGER_INFO("X300 RADIO") << boost::format("Running Extended ADC Self-Test (Duration=%.0fs, %ds/iteration)...") - % duration_s % SECS_PER_ITER; + UHD_LOGGER_INFO("X300 RADIO") + << boost::format( + "Running Extended ADC Self-Test (Duration=%.0fs, %ds/iteration)...") + % duration_s % SECS_PER_ITER; - size_t num_iters = static_cast<size_t>(ceil(duration_s/SECS_PER_ITER)); + size_t num_iters = static_cast<size_t>(ceil(duration_s / SECS_PER_ITER)); size_t num_failures = 0; for (size_t iter = 0; iter < num_iters; iter++) { - //Run self-test - UHD_LOGGER_INFO("X300 RADIO") << boost::format("Extended ADC Self-Test Iteration %06d... ") % (iter+1); + // Run self-test + UHD_LOGGER_INFO("X300 RADIO") + << boost::format("Extended ADC Self-Test Iteration %06d... ") % (iter + 1); try { for (size_t i = 0; i < radios.size(); i++) { - radios[i]->self_test_adc((SECS_PER_ITER*1000)/radios.size()); + radios[i]->self_test_adc((SECS_PER_ITER * 1000) / radios.size()); } - UHD_LOGGER_INFO("X300 RADIO") << boost::format("Extended ADC Self-Test Iteration %06d passed ") % (iter+1); - } catch(std::exception &e) { + UHD_LOGGER_INFO("X300 RADIO") + << boost::format("Extended ADC Self-Test Iteration %06d passed ") + % (iter + 1); + } catch (std::exception& e) { num_failures++; UHD_LOGGER_ERROR("X300 RADIO") << e.what(); } @@ -894,75 +1044,82 @@ void x300_radio_ctrl_impl::extended_adc_test(const std::vector<x300_radio_ctrl_i UHD_LOGGER_INFO("X300 RADIO") << "Extended ADC Self-Test PASSED"; } else { throw uhd::runtime_error( - (boost::format("Extended ADC Self-Test FAILED!!! (%d/%d failures)\n") % num_failures % num_iters).str()); + (boost::format("Extended ADC Self-Test FAILED!!! (%d/%d failures)\n") + % num_failures % num_iters) + .str()); } } -void x300_radio_ctrl_impl::synchronize_dacs(const std::vector<x300_radio_ctrl_impl::sptr>& radios) +void x300_radio_ctrl_impl::synchronize_dacs( + const std::vector<x300_radio_ctrl_impl::sptr>& radios) { - if (radios.size() < 2) return; //Nothing to synchronize + if (radios.size() < 2) + return; // Nothing to synchronize //**PRECONDITION** - //This function assumes that all the VITA times in "radios" are synchronized - //to a common reference. Currently, this function is called in get_tx_stream - //which also has the same precondition. + // This function assumes that all the VITA times in "radios" are synchronized + // to a common reference. Currently, this function is called in get_tx_stream + // which also has the same precondition. - //Get a rough estimate of the cumulative command latency + // Get a rough estimate of the cumulative command latency boost::posix_time::ptime t_start = boost::posix_time::microsec_clock::local_time(); for (size_t i = 0; i < radios.size(); i++) { - radios[i]->user_reg_read64(regs::RB_TIME_NOW); //Discard value. We are just timing the call + radios[i]->user_reg_read64( + regs::RB_TIME_NOW); // Discard value. We are just timing the call } boost::posix_time::time_duration t_elapsed = boost::posix_time::microsec_clock::local_time() - t_start; - //Add 100% of headroom + uncertainty to the command time - uint64_t t_sync_us = (t_elapsed.total_microseconds() * 2) + 16000 /*Scheduler latency*/; + // Add 100% of headroom + uncertainty to the command time + uint64_t t_sync_us = + (t_elapsed.total_microseconds() * 2) + 16000 /*Scheduler latency*/; std::string err_str; - //Try to sync 3 times before giving up - for (size_t attempt = 0; attempt < 3; attempt++) - { - try - { - //Reinitialize and resync all DACs + // Try to sync 3 times before giving up + for (size_t attempt = 0; attempt < 3; attempt++) { + try { + // Reinitialize and resync all DACs for (size_t i = 0; i < radios.size(); i++) { radios[i]->_dac->sync(); } - //Set tick rate and make sure FRAMEP/N is 0 + // Set tick rate and make sure FRAMEP/N is 0 for (size_t i = 0; i < radios.size(); i++) { - radios[i]->set_command_tick_rate(radios[i]->_radio_clk_rate, IO_MASTER_RADIO); - radios[i]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0); + radios[i]->set_command_tick_rate( + radios[i]->_radio_clk_rate, IO_MASTER_RADIO); + radios[i]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0); } - //Pick radios[0] as the time reference. - uhd::time_spec_t sync_time = - radios[0]->_time64->get_time_now() + uhd::time_spec_t(((double)t_sync_us)/1e6); + // Pick radios[0] as the time reference. + uhd::time_spec_t sync_time = radios[0]->_time64->get_time_now() + + uhd::time_spec_t(((double)t_sync_us) / 1e6); - //Send the sync command + // Send the sync command for (size_t i = 0; i < radios.size(); i++) { radios[i]->set_command_time(sync_time, IO_MASTER_RADIO); - //Arm FRAMEP/N sync pulse by asserting a rising edge - radios[i]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 1); + // Arm FRAMEP/N sync pulse by asserting a rising edge + radios[i]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 1); } - //Reset FRAMEP/N to 0 after 2 clock cycles + // Reset FRAMEP/N to 0 after 2 clock cycles for (size_t i = 0; i < radios.size(); i++) { - radios[i]->set_command_time(sync_time + (2.0 / radios[i]->_radio_clk_rate), IO_MASTER_RADIO); - radios[i]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0); + radios[i]->set_command_time( + sync_time + (2.0 / radios[i]->_radio_clk_rate), IO_MASTER_RADIO); + radios[i]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0); radios[i]->set_command_time(uhd::time_spec_t(0.0), IO_MASTER_RADIO); } - //Wait and check status + // Wait and check status std::this_thread::sleep_for(std::chrono::microseconds(t_sync_us)); for (size_t i = 0; i < radios.size(); i++) { radios[i]->_dac->verify_sync(); } return; - } - catch (const uhd::runtime_error &e) - { + } catch (const uhd::runtime_error& e) { err_str = e.what(); UHD_LOGGER_TRACE("X300 RADIO") << "Retrying DAC synchronization: " << err_str; } @@ -978,144 +1135,165 @@ double x300_radio_ctrl_impl::self_cal_adc_xfer_delay( { UHD_LOGGER_INFO("X300 RADIO") << "Running ADC transfer delay self-cal: "; - //Effective resolution of the self-cal. + // Effective resolution of the self-cal. static const size_t NUM_DELAY_STEPS = 100; - double master_clk_period = (1.0e9 / clock->get_master_clock_rate()); //in ns - double delay_start = 0.0; - double delay_range = 2 * master_clk_period; - double delay_incr = delay_range / NUM_DELAY_STEPS; + double master_clk_period = (1.0e9 / clock->get_master_clock_rate()); // in ns + double delay_start = 0.0; + double delay_range = 2 * master_clk_period; + double delay_incr = delay_range / NUM_DELAY_STEPS; double cached_clk_delay = clock->get_clock_delay(X300_CLOCK_WHICH_ADC0); - double fpga_clk_delay = clock->get_clock_delay(X300_CLOCK_WHICH_FPGA); + double fpga_clk_delay = clock->get_clock_delay(X300_CLOCK_WHICH_FPGA); - //Iterate through several values of delays and measure ADC data integrity - std::vector< std::pair<double,bool> > results; + // Iterate through several values of delays and measure ADC data integrity + std::vector<std::pair<double, bool>> results; for (size_t i = 0; i < NUM_DELAY_STEPS; i++) { - //Delay the ADC clock (will set both Ch0 and Ch1 delays) - double delay = clock->set_clock_delay(X300_CLOCK_WHICH_ADC0, delay_incr*i + delay_start); + // Delay the ADC clock (will set both Ch0 and Ch1 delays) + double delay = + clock->set_clock_delay(X300_CLOCK_WHICH_ADC0, delay_incr * i + delay_start); wait_for_clk_locked(0.1); uint32_t err_code = 0; for (size_t r = 0; r < radios.size(); r++) { - //Test each channel (I and Q) individually so as to not accidentally trigger - //on the data from the other channel if there is a swap + // Test each channel (I and Q) individually so as to not accidentally trigger + // on the data from the other channel if there is a swap // -- Test I Channel -- - //Put ADC in ramp test mode. Tie the other channel to all ones. + // Put ADC in ramp test mode. Tie the other channel to all ones. radios[r]->_adc->set_test_word("ramp", "ones"); - //Turn on the pattern checker in the FPGA. It will lock when it sees a zero - //and count deviations from the expected value - radios[r]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); - radios[r]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); - //50ms @ 200MHz = 10 million samples + // Turn on the pattern checker in the FPGA. It will lock when it sees a zero + // and count deviations from the expected value + radios[r]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); + radios[r]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); + // 50ms @ 200MHz = 10 million samples std::this_thread::sleep_for(std::chrono::milliseconds(50)); - if (radios[r]->_regs->misc_ins_reg.read(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_LOCKED)) { - err_code += radios[r]->_regs->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_ERROR); + if (radios[r]->_regs->misc_ins_reg.read( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_LOCKED)) { + err_code += radios[r]->_regs->misc_ins_reg.get( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_ERROR); } else { - err_code += 100; //Increment error code by 100 to indicate no lock + err_code += 100; // Increment error code by 100 to indicate no lock } // -- Test Q Channel -- - //Put ADC in ramp test mode. Tie the other channel to all ones. + // Put ADC in ramp test mode. Tie the other channel to all ones. radios[r]->_adc->set_test_word("ones", "ramp"); - //Turn on the pattern checker in the FPGA. It will lock when it sees a zero - //and count deviations from the expected value - radios[r]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); - radios[r]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); - //50ms @ 200MHz = 10 million samples + // Turn on the pattern checker in the FPGA. It will lock when it sees a zero + // and count deviations from the expected value + radios[r]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); + radios[r]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); + // 50ms @ 200MHz = 10 million samples std::this_thread::sleep_for(std::chrono::milliseconds(50)); - if (radios[r]->_regs->misc_ins_reg.read(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_LOCKED)) { - err_code += radios[r]->_regs->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_ERROR); + if (radios[r]->_regs->misc_ins_reg.read( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_LOCKED)) { + err_code += radios[r]->_regs->misc_ins_reg.get( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_ERROR); } else { - err_code += 100; //Increment error code by 100 to indicate no lock + err_code += 100; // Increment error code by 100 to indicate no lock } } - //UHD_LOGGER_INFO("X300 RADIO") << (boost::format("XferDelay=%fns, Error=%d") % delay % err_code); - results.push_back(std::pair<double,bool>(delay, err_code==0)); + // UHD_LOGGER_INFO("X300 RADIO") << (boost::format("XferDelay=%fns, Error=%d") % + // delay % err_code); + results.push_back(std::pair<double, bool>(delay, err_code == 0)); } - //Calculate the valid window + // Calculate the valid window int win_start_idx = -1, win_stop_idx = -1, cur_start_idx = -1, cur_stop_idx = -1; for (size_t i = 0; i < results.size(); i++) { - std::pair<double,bool>& item = results[i]; - if (item.second) { //If data is stable - if (cur_start_idx == -1) { //This is the first window + std::pair<double, bool>& item = results[i]; + if (item.second) { // If data is stable + if (cur_start_idx == -1) { // This is the first window cur_start_idx = i; - cur_stop_idx = i; - } else { //We are extending the window + cur_stop_idx = i; + } else { // We are extending the window cur_stop_idx = i; } } else { - if (cur_start_idx == -1) { //We haven't yet seen valid data - //Do nothing - } else if (win_start_idx == -1) { //We passed the first valid window + if (cur_start_idx == -1) { // We haven't yet seen valid data + // Do nothing + } else if (win_start_idx == -1) { // We passed the first valid window win_start_idx = cur_start_idx; - win_stop_idx = cur_stop_idx; - } else { //Update cached window if current window is larger - double cur_win_len = results[cur_stop_idx].first - results[cur_start_idx].first; - double cached_win_len = results[win_stop_idx].first - results[win_start_idx].first; + win_stop_idx = cur_stop_idx; + } else { // Update cached window if current window is larger + double cur_win_len = + results[cur_stop_idx].first - results[cur_start_idx].first; + double cached_win_len = + results[win_stop_idx].first - results[win_start_idx].first; if (cur_win_len > cached_win_len) { win_start_idx = cur_start_idx; - win_stop_idx = cur_stop_idx; + win_stop_idx = cur_stop_idx; } } - //Reset current window + // Reset current window cur_start_idx = -1; - cur_stop_idx = -1; + cur_stop_idx = -1; } } if (win_start_idx == -1) { - throw uhd::runtime_error("self_cal_adc_xfer_delay: Self calibration failed. Convergence error."); + throw uhd::runtime_error( + "self_cal_adc_xfer_delay: Self calibration failed. Convergence error."); } - double win_center = (results[win_stop_idx].first + results[win_start_idx].first) / 2.0; + double win_center = + (results[win_stop_idx].first + results[win_start_idx].first) / 2.0; double win_length = results[win_stop_idx].first - results[win_start_idx].first; - if (win_length < master_clk_period/4) { - throw uhd::runtime_error("self_cal_adc_xfer_delay: Self calibration failed. Valid window too narrow."); + if (win_length < master_clk_period / 4) { + throw uhd::runtime_error( + "self_cal_adc_xfer_delay: Self calibration failed. Valid window too narrow."); } - //Cycle slip the relative delay by a clock cycle to prevent sample misalignment - //fpga_clk_delay > 0 and 0 < win_center < 2*(1/MCR) so one cycle slip is all we need - bool cycle_slip = (win_center-fpga_clk_delay >= master_clk_period); + // Cycle slip the relative delay by a clock cycle to prevent sample misalignment + // fpga_clk_delay > 0 and 0 < win_center < 2*(1/MCR) so one cycle slip is all we need + bool cycle_slip = (win_center - fpga_clk_delay >= master_clk_period); if (cycle_slip) { win_center -= master_clk_period; } if (apply_delay) { - //Apply delay - win_center = clock->set_clock_delay(X300_CLOCK_WHICH_ADC0, win_center); //Sets ADC0 and ADC1 + // Apply delay + win_center = clock->set_clock_delay( + X300_CLOCK_WHICH_ADC0, win_center); // Sets ADC0 and ADC1 wait_for_clk_locked(0.1); - //Validate + // Validate for (size_t r = 0; r < radios.size(); r++) { radios[r]->self_test_adc(2000); } } else { - //Restore delay - clock->set_clock_delay(X300_CLOCK_WHICH_ADC0, cached_clk_delay); //Sets ADC0 and ADC1 + // Restore delay + clock->set_clock_delay( + X300_CLOCK_WHICH_ADC0, cached_clk_delay); // Sets ADC0 and ADC1 } - //Teardown + // Teardown for (size_t r = 0; r < radios.size(); r++) { radios[r]->_adc->set_test_word("normal", "normal"); - radios[r]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); + radios[r]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); } - UHD_LOGGER_INFO("X300 RADIO") << (boost::format("ADC transfer delay self-cal done (FPGA->ADC=%.3fns%s, Window=%.3fns)") % - (win_center-fpga_clk_delay) % (cycle_slip?" +cyc":"") % win_length); + UHD_LOGGER_INFO("X300 RADIO") + << (boost::format( + "ADC transfer delay self-cal done (FPGA->ADC=%.3fns%s, Window=%.3fns)") + % (win_center - fpga_clk_delay) % (cycle_slip ? " +cyc" : "") + % win_length); return win_center; } /**************************************************************************** * Helpers ***************************************************************************/ -void x300_radio_ctrl_impl::_update_atr_leds(const std::string &rx_ant, const size_t chan) +void x300_radio_ctrl_impl::_update_atr_leds(const std::string& rx_ant, const size_t chan) { // The "RX1" port is used by TwinRX and the "TX/RX" port is used by all // other full-duplex dboards. We need to handle both here. const bool is_txrx = (rx_ant == "TX/RX" or rx_ant == "RX1"); - const int TXRX_RX = (1 << 0); - const int TXRX_TX = (1 << 1); - const int RX2_RX = (1 << 2); + const int TXRX_RX = (1 << 0); + const int TXRX_TX = (1 << 1); + const int RX2_RX = (1 << 2); _leds.at(chan)->set_atr_reg(gpio_atr::ATR_REG_IDLE, 0); _leds.at(chan)->set_atr_reg(gpio_atr::ATR_REG_RX_ONLY, is_txrx ? TXRX_RX : RX2_RX); _leds.at(chan)->set_atr_reg(gpio_atr::ATR_REG_TX_ONLY, TXRX_TX); @@ -1124,76 +1302,91 @@ void x300_radio_ctrl_impl::_update_atr_leds(const std::string &rx_ant, const siz void x300_radio_ctrl_impl::_self_cal_adc_capture_delay(bool print_status) { - if (print_status) UHD_LOGGER_INFO("X300 RADIO") << "Running ADC capture delay self-cal..."; + if (print_status) + UHD_LOGGER_INFO("X300 RADIO") << "Running ADC capture delay self-cal..."; - static const uint32_t NUM_DELAY_STEPS = 32; //The IDELAYE2 element has 32 steps - static const uint32_t NUM_RETRIES = 2; //Retry self-cal if it fails in warmup situations - static const int32_t MIN_WINDOW_LEN = 4; + static const uint32_t NUM_DELAY_STEPS = 32; // The IDELAYE2 element has 32 steps + static const uint32_t NUM_RETRIES = + 2; // Retry self-cal if it fails in warmup situations + static const int32_t MIN_WINDOW_LEN = 4; int32_t win_start = -1, win_stop = -1; uint32_t iter = 0; while (iter++ < NUM_RETRIES) { for (uint32_t dly_tap = 0; dly_tap < NUM_DELAY_STEPS; dly_tap++) { - //Apply delay - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_VAL, dly_tap); - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 1); - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 0); + // Apply delay + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_VAL, dly_tap); + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 1); + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 0); uint32_t err_code = 0; // -- Test I Channel -- - //Put ADC in ramp test mode. Tie the other channel to all ones. + // Put ADC in ramp test mode. Tie the other channel to all ones. _adc->set_test_word("ramp", "ones"); - //Turn on the pattern checker in the FPGA. It will lock when it sees a zero - //and count deviations from the expected value - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); - //5ms @ 200MHz = 1 million samples + // Turn on the pattern checker in the FPGA. It will lock when it sees a zero + // and count deviations from the expected value + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); + // 5ms @ 200MHz = 1 million samples std::this_thread::sleep_for(std::chrono::milliseconds(5)); - if (_regs->misc_ins_reg.read(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_I_LOCKED)) { - err_code += _regs->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_I_ERROR); + if (_regs->misc_ins_reg.read( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_I_LOCKED)) { + err_code += _regs->misc_ins_reg.get( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_I_ERROR); } else { - err_code += 100; //Increment error code by 100 to indicate no lock + err_code += 100; // Increment error code by 100 to indicate no lock } // -- Test Q Channel -- - //Put ADC in ramp test mode. Tie the other channel to all ones. + // Put ADC in ramp test mode. Tie the other channel to all ones. _adc->set_test_word("ones", "ramp"); - //Turn on the pattern checker in the FPGA. It will lock when it sees a zero - //and count deviations from the expected value - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); - //5ms @ 200MHz = 1 million samples + // Turn on the pattern checker in the FPGA. It will lock when it sees a zero + // and count deviations from the expected value + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); + // 5ms @ 200MHz = 1 million samples std::this_thread::sleep_for(std::chrono::milliseconds(5)); - if (_regs->misc_ins_reg.read(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_Q_LOCKED)) { - err_code += _regs->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_Q_ERROR); + if (_regs->misc_ins_reg.read( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_Q_LOCKED)) { + err_code += _regs->misc_ins_reg.get( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_Q_ERROR); } else { - err_code += 100; //Increment error code by 100 to indicate no lock + err_code += 100; // Increment error code by 100 to indicate no lock } if (err_code == 0) { - if (win_start == -1) { //This is the first window + if (win_start == -1) { // This is the first window win_start = dly_tap; - win_stop = dly_tap; - } else { //We are extending the window + win_stop = dly_tap; + } else { // We are extending the window win_stop = dly_tap; } } else { - if (win_start != -1) { //A valid window turned invalid + if (win_start != -1) { // A valid window turned invalid if (win_stop - win_start >= MIN_WINDOW_LEN) { - break; //Valid window found + break; // Valid window found } else { - win_start = -1; //Reset window + win_start = -1; // Reset window } } } - //UHD_LOGGER_INFO("X300 RADIO") << (boost::format("CapTap=%d, Error=%d") % dly_tap % err_code); + // UHD_LOGGER_INFO("X300 RADIO") << (boost::format("CapTap=%d, Error=%d") % + // dly_tap % err_code); } - //Retry the self-cal if it fails - if ((win_start == -1 || (win_stop - win_start) < MIN_WINDOW_LEN) && iter < NUM_RETRIES /*not last iteration*/) { + // Retry the self-cal if it fails + if ((win_start == -1 || (win_stop - win_start) < MIN_WINDOW_LEN) + && iter < NUM_RETRIES /*not last iteration*/) { win_start = -1; - win_stop = -1; + win_stop = -1; std::this_thread::sleep_for(std::chrono::milliseconds(2000)); } else { break; @@ -1203,46 +1396,55 @@ void x300_radio_ctrl_impl::_self_cal_adc_capture_delay(bool print_status) _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); if (win_start == -1) { - throw uhd::runtime_error("self_cal_adc_capture_delay: Self calibration failed. Convergence error."); + throw uhd::runtime_error( + "self_cal_adc_capture_delay: Self calibration failed. Convergence error."); } - if (win_stop-win_start < MIN_WINDOW_LEN) { - throw uhd::runtime_error("self_cal_adc_capture_delay: Self calibration failed. Valid window too narrow."); + if (win_stop - win_start < MIN_WINDOW_LEN) { + throw uhd::runtime_error("self_cal_adc_capture_delay: Self calibration failed. " + "Valid window too narrow."); } uint32_t ideal_tap = (win_stop + win_start) / 2; - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_VAL, ideal_tap); + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_VAL, ideal_tap); _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 1); _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 0); if (print_status) { - double tap_delay = (1.0e12 / _radio_clk_rate) / (2*32); //in ps - UHD_LOGGER_INFO("X300 RADIO") << boost::format("ADC capture delay self-cal done (Tap=%d, Window=%d, TapDelay=%.3fps, Iter=%d)") % ideal_tap % (win_stop-win_start) % tap_delay % iter; + double tap_delay = (1.0e12 / _radio_clk_rate) / (2 * 32); // in ps + UHD_LOGGER_INFO("X300 RADIO") + << boost::format("ADC capture delay self-cal done (Tap=%d, Window=%d, " + "TapDelay=%.3fps, Iter=%d)") + % ideal_tap % (win_stop - win_start) % tap_delay % iter; } } void x300_radio_ctrl_impl::_check_adc(const uint32_t val) { - //Wait for previous control transaction to flush + // Wait for previous control transaction to flush user_reg_read64(regs::RB_TEST); - //Wait for ADC test pattern to propagate + // Wait for ADC test pattern to propagate std::this_thread::sleep_for(std::chrono::microseconds(5)); - //Read value of RX readback register and verify - uint32_t adc_rb = static_cast<uint32_t>(user_reg_read64(regs::RB_TEST)>>32); - adc_rb ^= 0xfffc0000; //adapt for I inversion in FPGA + // Read value of RX readback register and verify + uint32_t adc_rb = static_cast<uint32_t>(user_reg_read64(regs::RB_TEST) >> 32); + adc_rb ^= 0xfffc0000; // adapt for I inversion in FPGA if (val != adc_rb) { throw uhd::runtime_error( - (boost::format("ADC self-test failed for %s. (Exp=0x%x, Got=0x%x)")%unique_id()%val%adc_rb).str()); + (boost::format("ADC self-test failed for %s. (Exp=0x%x, Got=0x%x)") + % unique_id() % val % adc_rb) + .str()); } } -void x300_radio_ctrl_impl::_set_db_eeprom(i2c_iface::sptr i2c, const size_t addr, const uhd::usrp::dboard_eeprom_t &db_eeprom) +void x300_radio_ctrl_impl::_set_db_eeprom( + i2c_iface::sptr i2c, const size_t addr, const uhd::usrp::dboard_eeprom_t& db_eeprom) { db_eeprom.store(*i2c, addr); _db_eeproms[addr] = db_eeprom; } -void x300_radio_ctrl_impl::_set_command_time(const time_spec_t &spec, const size_t port) +void x300_radio_ctrl_impl::_set_command_time(const time_spec_t& spec, const size_t port) { set_fe_cmd_time(spec, port); } @@ -1251,15 +1453,16 @@ void x300_radio_ctrl_impl::_set_command_time(const time_spec_t &spec, const size ***************************************************************************/ bool x300_radio_ctrl_impl::check_radio_config() { - UHD_RFNOC_BLOCK_TRACE() << "x300_radio_ctrl_impl::check_radio_config() " ; + UHD_RFNOC_BLOCK_TRACE() << "x300_radio_ctrl_impl::check_radio_config() "; const fs_path rx_fe_path = fs_path("dboards" / _radio_slot / "rx_frontends"); for (size_t chan = 0; chan < _num_rx_channels; chan++) { if (_tree->exists(rx_fe_path / _rx_fe_map.at(chan).db_fe_name / "enabled")) { const bool chan_active = _is_streamer_active(uhd::RX_DIRECTION, chan); if (chan_active) { - _tree->access<bool>(rx_fe_path / _rx_fe_map.at(chan).db_fe_name / "enabled") - .set(chan_active) - ; + _tree + ->access<bool>( + rx_fe_path / _rx_fe_map.at(chan).db_fe_name / "enabled") + .set(chan_active); } } } @@ -1269,9 +1472,10 @@ bool x300_radio_ctrl_impl::check_radio_config() if (_tree->exists(tx_fe_path / _tx_fe_map.at(chan).db_fe_name / "enabled")) { const bool chan_active = _is_streamer_active(uhd::TX_DIRECTION, chan); if (chan_active) { - _tree->access<bool>(tx_fe_path / _tx_fe_map.at(chan).db_fe_name / "enabled") - .set(chan_active) - ; + _tree + ->access<bool>( + tx_fe_path / _tx_fe_map.at(chan).db_fe_name / "enabled") + .set(chan_active); } } } diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp index 7b02f2cf1..7cc0ea18d 100644 --- a/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp +++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp @@ -8,8 +8,8 @@ #ifndef INCLUDED_LIBUHD_RFNOC_X300_RADIO_CTRL_IMPL_HPP #define INCLUDED_LIBUHD_RFNOC_X300_RADIO_CTRL_IMPL_HPP -#include "x300_clock_ctrl.hpp" #include "x300_adc_ctrl.hpp" +#include "x300_clock_ctrl.hpp" #include "x300_dac_ctrl.hpp" #include "x300_regs.hpp" #include <uhd/usrp/dboard_eeprom.hpp> @@ -17,11 +17,10 @@ #include <uhd/usrp/gpio_defs.hpp> #include <uhdlib/rfnoc/radio_ctrl_impl.hpp> #include <uhdlib/usrp/cores/rx_frontend_core_3000.hpp> -#include <uhdlib/usrp/cores/tx_frontend_core_200.hpp> #include <uhdlib/usrp/cores/spi_core_3000.hpp> +#include <uhdlib/usrp/cores/tx_frontend_core_200.hpp> -namespace uhd { - namespace rfnoc { +namespace uhd { namespace rfnoc { /*! \brief Provide access to an X300 radio. */ @@ -41,8 +40,8 @@ public: ***********************************************************************/ double set_rate(double rate); - void set_tx_antenna(const std::string &ant, const size_t chan); - void set_rx_antenna(const std::string &ant, const size_t chan); + void set_tx_antenna(const std::string& ant, const size_t chan); + void set_rx_antenna(const std::string& ant, const size_t chan); std::string get_tx_antenna(const size_t chan); std::string get_rx_antenna(const size_t chan); @@ -57,24 +56,30 @@ public: double set_rx_gain(const double 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(const std::string &name, const size_t chan); - freq_range_t get_rx_lo_freq_range(const std::string &name, const size_t chan); + std::vector<std::string> get_rx_lo_sources( + const std::string& name, const size_t chan); + freq_range_t get_rx_lo_freq_range(const std::string& name, const size_t chan); - void set_rx_lo_source(const std::string &src, const std::string &name, const size_t chan); - const std::string get_rx_lo_source(const std::string &name, const size_t chan); + void set_rx_lo_source( + const std::string& src, const std::string& name, const size_t chan); + const std::string get_rx_lo_source(const std::string& name, const size_t chan); - void set_rx_lo_export_enabled(bool enabled, const std::string &name, const size_t chan); - bool get_rx_lo_export_enabled(const std::string &name, const size_t chan); + void set_rx_lo_export_enabled( + bool enabled, const std::string& name, const size_t chan); + bool get_rx_lo_export_enabled(const std::string& name, const size_t chan); - double set_rx_lo_freq(double freq, const std::string &name, const size_t chan); - double get_rx_lo_freq(const std::string &name, const size_t chan); + double set_rx_lo_freq(double freq, const std::string& name, const size_t chan); + double get_rx_lo_freq(const std::string& name, const size_t chan); - size_t get_chan_from_dboard_fe(const std::string &fe, const direction_t dir); + 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); std::vector<std::string> get_gpio_banks() const; - void set_gpio_attr(const std::string &bank, const std::string &attr, const uint32_t value, const uint32_t mask); - uint32_t get_gpio_attr(const std::string &bank, const std::string &attr); + void set_gpio_attr(const std::string& bank, + const std::string& attr, + const uint32_t value, + const uint32_t mask); + uint32_t get_gpio_attr(const std::string& bank, const std::string& attr); double get_output_samp_rate(size_t port); @@ -83,23 +88,19 @@ public: ***********************************************************************/ /*! Set up the radio. No API calls may be made before this one. */ - void setup_radio( - uhd::i2c_iface::sptr zpu_i2c, + void setup_radio(uhd::i2c_iface::sptr zpu_i2c, x300_clock_ctrl::sptr clock, bool ignore_cal_file, - bool verbose - ); + bool verbose); void reset_codec(); - void self_test_adc( - uint32_t ramp_time_ms = 100); + void self_test_adc(uint32_t ramp_time_ms = 100); static void extended_adc_test( const std::vector<x300_radio_ctrl_impl::sptr>&, double duration_s); - static void synchronize_dacs( - const std::vector<x300_radio_ctrl_impl::sptr>& radios); + static void synchronize_dacs(const std::vector<x300_radio_ctrl_impl::sptr>& radios); static double self_cal_adc_xfer_delay( const std::vector<x300_radio_ctrl_impl::sptr>& radios, @@ -111,21 +112,25 @@ protected: virtual bool check_radio_config(); private: - class radio_regmap_t : public uhd::soft_regmap_t { + class radio_regmap_t : public uhd::soft_regmap_t + { public: typedef boost::shared_ptr<radio_regmap_t> sptr; - class misc_outs_reg_t : public uhd::soft_reg32_wo_t { + class misc_outs_reg_t : public uhd::soft_reg32_wo_t + { public: - UHD_DEFINE_SOFT_REG_FIELD(DAC_ENABLED, /*width*/ 1, /*shift*/ 0); //[0] - UHD_DEFINE_SOFT_REG_FIELD(DAC_RESET_N, /*width*/ 1, /*shift*/ 1); //[1] - UHD_DEFINE_SOFT_REG_FIELD(ADC_RESET, /*width*/ 1, /*shift*/ 2); //[2] - UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_STB, /*width*/ 1, /*shift*/ 3); //[3] - UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_VAL, /*width*/ 5, /*shift*/ 4); //[8:4] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER_ENABLED, /*width*/ 1, /*shift*/ 9); //[9] - UHD_DEFINE_SOFT_REG_FIELD(DAC_SYNC, /*width*/ 1, /*shift*/ 10); //[10] - - misc_outs_reg_t(): uhd::soft_reg32_wo_t(regs::sr_addr(regs::MISC_OUTS)) { - //Initial values + UHD_DEFINE_SOFT_REG_FIELD(DAC_ENABLED, /*width*/ 1, /*shift*/ 0); //[0] + UHD_DEFINE_SOFT_REG_FIELD(DAC_RESET_N, /*width*/ 1, /*shift*/ 1); //[1] + UHD_DEFINE_SOFT_REG_FIELD(ADC_RESET, /*width*/ 1, /*shift*/ 2); //[2] + UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_STB, /*width*/ 1, /*shift*/ 3); //[3] + UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_VAL, /*width*/ 5, /*shift*/ 4); //[8:4] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER_ENABLED, /*width*/ 1, /*shift*/ 9); //[9] + UHD_DEFINE_SOFT_REG_FIELD(DAC_SYNC, /*width*/ 1, /*shift*/ 10); //[10] + + misc_outs_reg_t() : uhd::soft_reg32_wo_t(regs::sr_addr(regs::MISC_OUTS)) + { + // Initial values set(DAC_ENABLED, 0); set(DAC_RESET_N, 0); set(ADC_RESET, 0); @@ -136,77 +141,96 @@ private: } } misc_outs_reg; - class misc_ins_reg_t : public uhd::soft_reg64_ro_t { + class misc_ins_reg_t : public uhd::soft_reg64_ro_t + { public: - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_Q_LOCKED, /*width*/ 1, /*shift*/ 32); //[0] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_I_LOCKED, /*width*/ 1, /*shift*/ 33); //[1] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_Q_LOCKED, /*width*/ 1, /*shift*/ 34); //[2] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_I_LOCKED, /*width*/ 1, /*shift*/ 35); //[3] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_Q_ERROR, /*width*/ 1, /*shift*/ 36); //[4] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_I_ERROR, /*width*/ 1, /*shift*/ 37); //[5] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_Q_ERROR, /*width*/ 1, /*shift*/ 38); //[6] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_I_ERROR, /*width*/ 1, /*shift*/ 39); //[7] - - misc_ins_reg_t(): uhd::soft_reg64_ro_t(regs::rb_addr(regs::RB_MISC_IO)) { } + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER0_Q_LOCKED, /*width*/ 1, /*shift*/ 32); //[0] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER0_I_LOCKED, /*width*/ 1, /*shift*/ 33); //[1] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER1_Q_LOCKED, /*width*/ 1, /*shift*/ 34); //[2] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER1_I_LOCKED, /*width*/ 1, /*shift*/ 35); //[3] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER0_Q_ERROR, /*width*/ 1, /*shift*/ 36); //[4] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER0_I_ERROR, /*width*/ 1, /*shift*/ 37); //[5] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER1_Q_ERROR, /*width*/ 1, /*shift*/ 38); //[6] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER1_I_ERROR, /*width*/ 1, /*shift*/ 39); //[7] + + misc_ins_reg_t() : uhd::soft_reg64_ro_t(regs::rb_addr(regs::RB_MISC_IO)) {} } misc_ins_reg; - radio_regmap_t(int radio_num) : soft_regmap_t("radio" + std::to_string(radio_num) + "_regmap") { + radio_regmap_t(int radio_num) + : soft_regmap_t("radio" + std::to_string(radio_num) + "_regmap") + { add_to_map(misc_outs_reg, "misc_outs_reg", PRIVATE); add_to_map(misc_ins_reg, "misc_ins_reg", PRIVATE); } }; - struct x300_regs { - static const uint32_t TX_FE_BASE = 224; - static const uint32_t RX_FE_BASE = 232; + struct x300_regs + { + static const uint32_t TX_FE_BASE = 224; + static const uint32_t RX_FE_BASE = 232; }; - void _update_atr_leds(const std::string &rx_ant, const size_t chan); + void _update_atr_leds(const std::string& rx_ant, const size_t chan); void _self_cal_adc_capture_delay(bool print_status); void _check_adc(const uint32_t val); - void _set_db_eeprom(uhd::i2c_iface::sptr i2c, const size_t, const uhd::usrp::dboard_eeprom_t &); + void _set_db_eeprom( + uhd::i2c_iface::sptr i2c, const size_t, const uhd::usrp::dboard_eeprom_t&); - void set_rx_fe_corrections(const uhd::fs_path &db_path, const uhd::fs_path &rx_fe_corr_path, const double lo_freq); - void set_tx_fe_corrections(const uhd::fs_path &db_path, const uhd::fs_path &tx_fe_corr_path, const double lo_freq); + void set_rx_fe_corrections(const uhd::fs_path& db_path, + const uhd::fs_path& rx_fe_corr_path, + const double lo_freq); + void set_tx_fe_corrections(const uhd::fs_path& db_path, + const uhd::fs_path& tx_fe_corr_path, + const double lo_freq); - void _set_command_time(const uhd::time_spec_t &spec, const size_t port); - void set_fe_cmd_time(const time_spec_t &time, const size_t chan); + void _set_command_time(const uhd::time_spec_t& spec, const size_t port); + void set_fe_cmd_time(const time_spec_t& time, const size_t chan); private: // members enum radio_connection_t { PRIMARY, SECONDARY }; - radio_connection_t _radio_type; - std::string _radio_slot; + radio_connection_t _radio_type; + std::string _radio_slot; //! Radio clock rate is the rate at which the ADC and DAC are running at. // Not necessarily this block's sampling rate (tick rate). - double _radio_clk_rate; + double _radio_clk_rate; - radio_regmap_t::sptr _regs; - std::map<size_t, usrp::gpio_atr::gpio_atr_3000::sptr> _leds; - spi_core_3000::sptr _spi; - x300_adc_ctrl::sptr _adc; - x300_dac_ctrl::sptr _dac; - usrp::gpio_atr::gpio_atr_3000::sptr _fp_gpio; + radio_regmap_t::sptr _regs; + std::map<size_t, usrp::gpio_atr::gpio_atr_3000::sptr> _leds; + spi_core_3000::sptr _spi; + x300_adc_ctrl::sptr _adc; + x300_dac_ctrl::sptr _dac; + usrp::gpio_atr::gpio_atr_3000::sptr _fp_gpio; std::map<size_t, usrp::dboard_eeprom_t> _db_eeproms; - usrp::dboard_manager::sptr _db_manager; + usrp::dboard_manager::sptr _db_manager; - struct rx_fe_perif { - std::string name; - std::string db_fe_name; + struct rx_fe_perif + { + std::string name; + std::string db_fe_name; rx_frontend_core_3000::sptr core; }; - struct tx_fe_perif { - std::string name; - std::string db_fe_name; - tx_frontend_core_200::sptr core; + struct tx_fe_perif + { + std::string name; + std::string db_fe_name; + tx_frontend_core_200::sptr core; }; - std::map<size_t, rx_fe_perif> _rx_fe_map; - std::map<size_t, tx_fe_perif> _tx_fe_map; + std::map<size_t, rx_fe_perif> _rx_fe_map; + std::map<size_t, tx_fe_perif> _tx_fe_map; bool _ignore_cal_file; diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp index 5fdc89979..d2677c05e 100644 --- a/host/lib/usrp/x300/x300_regs.hpp +++ b/host/lib/usrp/x300/x300_regs.hpp @@ -9,22 +9,22 @@ #define INCLUDED_X300_REGS_HPP #include <uhd/config.hpp> -#include <stdint.h> #include <uhd/utils/soft_register.hpp> +#include <stdint.h> -static const int BL_ADDRESS = 0; -static const int BL_DATA = 1; +static const int BL_ADDRESS = 0; +static const int BL_DATA = 1; -//wishbone settings map - relevant to host code -#define SET0_BASE 0xa000 -#define SETXB_BASE 0xb000 +// wishbone settings map - relevant to host code +#define SET0_BASE 0xa000 +#define SETXB_BASE 0xb000 #define BOOT_LDR_BASE 0xfa00 -#define I2C0_BASE 0xfe00 -#define I2C1_BASE 0xff00 +#define I2C0_BASE 0xfe00 +#define I2C1_BASE 0xff00 #define SR_ADDR(base, offset) ((base) + (offset)*4) -//I2C1 device addresses -#define MBOARD_EEPROM_ADDR 0x50 +// I2C1 device addresses +#define MBOARD_EEPROM_ADDR 0x50 static const int ZPU_SR_LEDS = 00; static const int ZPU_SR_SW_RST = 01; @@ -37,11 +37,11 @@ static const int ZPU_SR_ETHINT1 = 56; static const int ZPU_SR_DRAM_FIFO0 = 72; static const int ZPU_SR_DRAM_FIFO1 = 80; -//reset bits -#define ZPU_SR_SW_RST_ETH_PHY (1<<0) -#define ZPU_SR_SW_RST_RADIO_RST (1<<1) -#define ZPU_SR_SW_RST_RADIO_CLK_PLL (1<<2) -#define ZPU_SR_SW_RST_ADC_IDELAYCTRL (1<<3) +// reset bits +#define ZPU_SR_SW_RST_ETH_PHY (1 << 0) +#define ZPU_SR_SW_RST_RADIO_RST (1 << 1) +#define ZPU_SR_SW_RST_RADIO_CLK_PLL (1 << 2) +#define ZPU_SR_SW_RST_ADC_IDELAYCTRL (1 << 3) static const int ZPU_RB_SPI = 2; static const int ZPU_RB_CLK_STATUS = 3; @@ -55,23 +55,23 @@ static const uint32_t RB_SFP_1G_ETH = 0; static const uint32_t RB_SFP_10G_ETH = 1; static const uint32_t RB_SFP_AURORA = 2; -//spi slaves on radio -#define DB_DAC_SEN (1 << 7) -#define DB_ADC_SEN (1 << 6) +// spi slaves on radio +#define DB_DAC_SEN (1 << 7) +#define DB_ADC_SEN (1 << 6) #define DB_RX_LSADC_SEN (1 << 5) #define DB_RX_LSDAC_SEN (1 << 4) #define DB_TX_LSADC_SEN (1 << 3) #define DB_TX_LSDAC_SEN (1 << 2) -#define DB_RX_SEN (1 << 1) -#define DB_TX_SEN (1 << 0) +#define DB_RX_SEN (1 << 1) +#define DB_TX_SEN (1 << 0) //------------------------------------------------------------------- // PCIe Registers //------------------------------------------------------------------- -static const uint32_t X300_PCIE_VID = 0x1093; -static const uint32_t X300_PCIE_PID = 0xC4C4; -//Rev 0-6 motherboard/PCIe IDs (ADC driven at 3.3V) +static const uint32_t X300_PCIE_VID = 0x1093; +static const uint32_t X300_PCIE_PID = 0xC4C4; +// Rev 0-6 motherboard/PCIe IDs (ADC driven at 3.3V) static const uint32_t X300_USRP_PCIE_SSID_ADC_33 = 0x7736; static const uint32_t X310_USRP_PCIE_SSID_ADC_33 = 0x76CA; static const uint32_t X310_2940R_40MHz_PCIE_SSID_ADC_33 = 0x772B; @@ -88,7 +88,7 @@ static const uint32_t X310_2952R_120MHz_PCIE_SSID_ADC_33 = 0x77FF; static const uint32_t X310_2953R_40MHz_PCIE_SSID_ADC_33 = 0x7731; static const uint32_t X310_2953R_120MHz_PCIE_SSID_ADC_33 = 0x7800; static const uint32_t X310_2954R_40MHz_PCIE_SSID_ADC_33 = 0x7732; -//Rev 7+ motherboard/PCIe IDs (ADCs driven at 1.8V) +// Rev 7+ motherboard/PCIe IDs (ADCs driven at 1.8V) static const uint32_t X300_USRP_PCIE_SSID_ADC_18 = 0x7861; static const uint32_t X310_USRP_PCIE_SSID_ADC_18 = 0x7862; static const uint32_t X310_2940R_40MHz_PCIE_SSID_ADC_18 = 0x7853; @@ -109,10 +109,10 @@ static const uint32_t X310_2954R_40MHz_PCIE_SSID_ADC_18 = 0x785A; static const uint32_t X310_2955R_PCIE_SSID_ADC_18 = 0x78F0; static const uint32_t X310_2974_PCIE_SSID_ADC_18 = 0x799B; -static const uint32_t FPGA_X3xx_SIG_VALUE = 0x58333030; +static const uint32_t FPGA_X3xx_SIG_VALUE = 0x58333030; -static const uint32_t PCIE_FPGA_ADDR_BASE = 0xC0000; -#define PCIE_FPGA_REG(X) (PCIE_FPGA_ADDR_BASE + (X)) +static const uint32_t PCIE_FPGA_ADDR_BASE = 0xC0000; +#define PCIE_FPGA_REG(X) (PCIE_FPGA_ADDR_BASE + (X)) static const uint32_t FPGA_PCIE_SIG_REG = PCIE_FPGA_REG(0x0000); static const uint32_t FPGA_CNTR_LO_REG = PCIE_FPGA_REG(0x0004); @@ -124,38 +124,40 @@ static const uint32_t FPGA_USR_SIG_REG_SIZE = 16; static const uint32_t FPGA_STATUS_DMA_ACTIVE_MASK = 0x3F3F0000; -static const uint32_t PCIE_TX_DMA_REG_BASE = PCIE_FPGA_REG(0x0200); -static const uint32_t PCIE_RX_DMA_REG_BASE = PCIE_FPGA_REG(0x0400); - -static const uint32_t DMA_REG_GRP_SIZE = 16; -static const uint32_t DMA_CTRL_STATUS_REG = 0x0; -static const uint32_t DMA_FRAME_SIZE_REG = 0x4; -static const uint32_t DMA_SAMPLE_COUNT_REG = 0x8; -static const uint32_t DMA_PKT_COUNT_REG = 0xC; - -#define PCIE_TX_DMA_REG(REG, CHAN) (PCIE_TX_DMA_REG_BASE + ((CHAN)*DMA_REG_GRP_SIZE) + (REG)) -#define PCIE_RX_DMA_REG(REG, CHAN) (PCIE_RX_DMA_REG_BASE + ((CHAN)*DMA_REG_GRP_SIZE) + (REG)) - -static const uint32_t DMA_CTRL_DISABLED = 0x00000000; -static const uint32_t DMA_CTRL_ENABLED = 0x00000002; -static const uint32_t DMA_CTRL_CLEAR_STB = 0x00000001; -static const uint32_t DMA_CTRL_SW_BUF_U64 = (3 << 4); -static const uint32_t DMA_CTRL_SW_BUF_U32 = (2 << 4); -static const uint32_t DMA_CTRL_SW_BUF_U16 = (1 << 4); -static const uint32_t DMA_CTRL_SW_BUF_U8 = (0 << 4); -static const uint32_t DMA_STATUS_ERROR = 0x00000001; -static const uint32_t DMA_STATUS_BUSY = 0x00000002; - -static const uint32_t PCIE_ROUTER_REG_BASE = PCIE_FPGA_REG(0x0500); -#define PCIE_ROUTER_REG(X) (PCIE_ROUTER_REG_BASE + (X)) - -static const uint32_t PCIE_ZPU_DATA_BASE = 0x30000; -static const uint32_t PCIE_ZPU_READ_BASE = 0x20000; //Trig and Status share the same base -static const uint32_t PCIE_ZPU_STATUS_BASE = 0x20000; - -#define PCIE_ZPU_DATA_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_DATA_BASE) + (X)) -#define PCIE_ZPU_READ_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_READ_BASE) + (X)) -#define PCIE_ZPU_STATUS_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_STATUS_BASE) + (X)) +static const uint32_t PCIE_TX_DMA_REG_BASE = PCIE_FPGA_REG(0x0200); +static const uint32_t PCIE_RX_DMA_REG_BASE = PCIE_FPGA_REG(0x0400); + +static const uint32_t DMA_REG_GRP_SIZE = 16; +static const uint32_t DMA_CTRL_STATUS_REG = 0x0; +static const uint32_t DMA_FRAME_SIZE_REG = 0x4; +static const uint32_t DMA_SAMPLE_COUNT_REG = 0x8; +static const uint32_t DMA_PKT_COUNT_REG = 0xC; + +#define PCIE_TX_DMA_REG(REG, CHAN) \ + (PCIE_TX_DMA_REG_BASE + ((CHAN)*DMA_REG_GRP_SIZE) + (REG)) +#define PCIE_RX_DMA_REG(REG, CHAN) \ + (PCIE_RX_DMA_REG_BASE + ((CHAN)*DMA_REG_GRP_SIZE) + (REG)) + +static const uint32_t DMA_CTRL_DISABLED = 0x00000000; +static const uint32_t DMA_CTRL_ENABLED = 0x00000002; +static const uint32_t DMA_CTRL_CLEAR_STB = 0x00000001; +static const uint32_t DMA_CTRL_SW_BUF_U64 = (3 << 4); +static const uint32_t DMA_CTRL_SW_BUF_U32 = (2 << 4); +static const uint32_t DMA_CTRL_SW_BUF_U16 = (1 << 4); +static const uint32_t DMA_CTRL_SW_BUF_U8 = (0 << 4); +static const uint32_t DMA_STATUS_ERROR = 0x00000001; +static const uint32_t DMA_STATUS_BUSY = 0x00000002; + +static const uint32_t PCIE_ROUTER_REG_BASE = PCIE_FPGA_REG(0x0500); +#define PCIE_ROUTER_REG(X) (PCIE_ROUTER_REG_BASE + (X)) + +static const uint32_t PCIE_ZPU_DATA_BASE = 0x30000; +static const uint32_t PCIE_ZPU_READ_BASE = 0x20000; // Trig and Status share the same base +static const uint32_t PCIE_ZPU_STATUS_BASE = 0x20000; + +#define PCIE_ZPU_DATA_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_DATA_BASE) + (X)) +#define PCIE_ZPU_READ_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_READ_BASE) + (X)) +#define PCIE_ZPU_STATUS_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_STATUS_BASE) + (X)) static const uint32_t PCIE_ZPU_READ_START = 0x0; static const uint32_t PCIE_ZPU_READ_CLOBBER = 0x80000000; @@ -166,63 +168,72 @@ static const uint32_t PCIE_ZPU_STATUS_SUSPENDED = 0x80000000; // Register Maps //------------------------------------------------------------------- namespace uhd { namespace usrp { namespace x300 { - class fw_regmap_t : public uhd::soft_regmap_t { +class fw_regmap_t : public uhd::soft_regmap_t +{ +public: + typedef boost::shared_ptr<fw_regmap_t> sptr; + + class clk_ctrl_reg_t : public uhd::soft_reg32_wo_t + { public: - typedef boost::shared_ptr<fw_regmap_t> sptr; - - class clk_ctrl_reg_t : public uhd::soft_reg32_wo_t { - public: - UHD_DEFINE_SOFT_REG_FIELD(CLK_SOURCE, /*width*/ 2, /*shift*/ 0); //[1:0] - UHD_DEFINE_SOFT_REG_FIELD(PPS_SELECT, /*width*/ 2, /*shift*/ 2); //[3:2] - UHD_DEFINE_SOFT_REG_FIELD(PPS_OUT_EN, /*width*/ 1, /*shift*/ 4); //[4] - UHD_DEFINE_SOFT_REG_FIELD(TCXO_EN, /*width*/ 1, /*shift*/ 5); //[5] - UHD_DEFINE_SOFT_REG_FIELD(GPSDO_PWR_EN, /*width*/ 1, /*shift*/ 6); //[6] - UHD_DEFINE_SOFT_REG_FIELD(TIME_SYNC, /*width*/ 1, /*shift*/ 7); //[7] - - static const uint32_t SRC_EXTERNAL = 0x0; - static const uint32_t SRC_INTERNAL = 0x2; - static const uint32_t SRC_GPSDO = 0x3; - - clk_ctrl_reg_t(): uhd::soft_reg32_wo_t(SR_ADDR(SET0_BASE, ZPU_SR_CLOCK_CTRL)) { - //Initial values - set(CLK_SOURCE, SRC_INTERNAL); - set(PPS_SELECT, SRC_INTERNAL); - set(PPS_OUT_EN, 0); - set(TCXO_EN, 1); - set(GPSDO_PWR_EN, 1); //GPSDO power always ON - set(TIME_SYNC, 0); - } - } clock_ctrl_reg; - - class clk_status_reg_t : public uhd::soft_reg32_ro_t { - public: - UHD_DEFINE_SOFT_REG_FIELD(LMK_STATUS, /*width*/ 2, /*shift*/ 0); //[1:0] - UHD_DEFINE_SOFT_REG_FIELD(LMK_LOCK, /*width*/ 1, /*shift*/ 2); //[2] - UHD_DEFINE_SOFT_REG_FIELD(LMK_HOLDOVER, /*width*/ 1, /*shift*/ 3); //[3] - UHD_DEFINE_SOFT_REG_FIELD(PPS_DETECT, /*width*/ 1, /*shift*/ 4); //[4] - UHD_DEFINE_SOFT_REG_FIELD(RADIO_CLK_LOCK, /*width*/ 1, /*shift*/ 5); //[5] - UHD_DEFINE_SOFT_REG_FIELD(IDELAYCTRL_LOCK, /*width*/ 1, /*shift*/ 6); //[6] - - clk_status_reg_t(): uhd::soft_reg32_ro_t(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)) {} - } clock_status_reg; - - class ref_freq_reg_t : public uhd::soft_reg32_wo_t { - public: - UHD_DEFINE_SOFT_REG_FIELD(REF_FREQ, /*width*/ 32, /*shift*/ 0); - - ref_freq_reg_t(): uhd::soft_reg32_wo_t(SR_ADDR(SET0_BASE, ZPU_SR_REF_FREQ)) { - //Initial values - set(REF_FREQ, 10000000); - } - } ref_freq_reg; - - fw_regmap_t() : soft_regmap_t("fw_regmap") { - add_to_map(clock_ctrl_reg, "clock_ctrl_reg", PUBLIC); - add_to_map(clock_status_reg, "clock_status_reg", PUBLIC); - add_to_map(ref_freq_reg, "ref_freq_reg", PUBLIC); + UHD_DEFINE_SOFT_REG_FIELD(CLK_SOURCE, /*width*/ 2, /*shift*/ 0); //[1:0] + UHD_DEFINE_SOFT_REG_FIELD(PPS_SELECT, /*width*/ 2, /*shift*/ 2); //[3:2] + UHD_DEFINE_SOFT_REG_FIELD(PPS_OUT_EN, /*width*/ 1, /*shift*/ 4); //[4] + UHD_DEFINE_SOFT_REG_FIELD(TCXO_EN, /*width*/ 1, /*shift*/ 5); //[5] + UHD_DEFINE_SOFT_REG_FIELD(GPSDO_PWR_EN, /*width*/ 1, /*shift*/ 6); //[6] + UHD_DEFINE_SOFT_REG_FIELD(TIME_SYNC, /*width*/ 1, /*shift*/ 7); //[7] + + static const uint32_t SRC_EXTERNAL = 0x0; + static const uint32_t SRC_INTERNAL = 0x2; + static const uint32_t SRC_GPSDO = 0x3; + + clk_ctrl_reg_t() : uhd::soft_reg32_wo_t(SR_ADDR(SET0_BASE, ZPU_SR_CLOCK_CTRL)) + { + // Initial values + set(CLK_SOURCE, SRC_INTERNAL); + set(PPS_SELECT, SRC_INTERNAL); + set(PPS_OUT_EN, 0); + set(TCXO_EN, 1); + set(GPSDO_PWR_EN, 1); // GPSDO power always ON + set(TIME_SYNC, 0); } - }; + } clock_ctrl_reg; + + class clk_status_reg_t : public uhd::soft_reg32_ro_t + { + public: + UHD_DEFINE_SOFT_REG_FIELD(LMK_STATUS, /*width*/ 2, /*shift*/ 0); //[1:0] + UHD_DEFINE_SOFT_REG_FIELD(LMK_LOCK, /*width*/ 1, /*shift*/ 2); //[2] + UHD_DEFINE_SOFT_REG_FIELD(LMK_HOLDOVER, /*width*/ 1, /*shift*/ 3); //[3] + UHD_DEFINE_SOFT_REG_FIELD(PPS_DETECT, /*width*/ 1, /*shift*/ 4); //[4] + UHD_DEFINE_SOFT_REG_FIELD(RADIO_CLK_LOCK, /*width*/ 1, /*shift*/ 5); //[5] + UHD_DEFINE_SOFT_REG_FIELD(IDELAYCTRL_LOCK, /*width*/ 1, /*shift*/ 6); //[6] + + clk_status_reg_t() : uhd::soft_reg32_ro_t(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)) + { + } + } clock_status_reg; + + class ref_freq_reg_t : public uhd::soft_reg32_wo_t + { + public: + UHD_DEFINE_SOFT_REG_FIELD(REF_FREQ, /*width*/ 32, /*shift*/ 0); + + ref_freq_reg_t() : uhd::soft_reg32_wo_t(SR_ADDR(SET0_BASE, ZPU_SR_REF_FREQ)) + { + // Initial values + set(REF_FREQ, 10000000); + } + } ref_freq_reg; + + fw_regmap_t() : soft_regmap_t("fw_regmap") + { + add_to_map(clock_ctrl_reg, "clock_ctrl_reg", PUBLIC); + add_to_map(clock_status_reg, "clock_status_reg", PUBLIC); + add_to_map(ref_freq_reg, "ref_freq_reg", PUBLIC); + } +}; -}}} +}}} // namespace uhd::usrp::x300 #endif /* INCLUDED_X300_REGS_HPP */ |