diff options
Diffstat (limited to 'host')
-rw-r--r-- | host/lib/include/uhdlib/usrp/common/adf535x.hpp | 814 | ||||
-rw-r--r-- | host/lib/include/uhdlib/usrp/common/lmx2592.hpp | 6 | ||||
-rw-r--r-- | host/lib/usrp/b100/clock_ctrl.cpp | 506 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_io_impl.cpp | 527 | ||||
-rw-r--r-- | host/lib/usrp/common/ad936x_manager.cpp | 247 |
5 files changed, 1129 insertions, 971 deletions
diff --git a/host/lib/include/uhdlib/usrp/common/adf535x.hpp b/host/lib/include/uhdlib/usrp/common/adf535x.hpp index 39dfb4b2a..200610d02 100644 --- a/host/lib/include/uhdlib/usrp/common/adf535x.hpp +++ b/host/lib/include/uhdlib/usrp/common/adf535x.hpp @@ -9,16 +9,16 @@ #include "adf5355_regs.hpp" #include "adf5356_regs.hpp" -#include <uhd/utils/math.hpp> #include <uhd/utils/log.hpp> +#include <uhd/utils/math.hpp> +#include <uhd/utils/safe_call.hpp> +#include <stdint.h> +#include <boost/format.hpp> #include <boost/function.hpp> #include <boost/math/common_factor_rt.hpp> //gcd +#include <algorithm> #include <utility> #include <vector> -#include <algorithm> -#include <stdint.h> -#include <boost/format.hpp> -#include <uhd/utils/safe_call.hpp> class adf535x_iface { @@ -36,9 +36,22 @@ public: enum feedback_sel_t { FB_SEL_FUNDAMENTAL, FB_SEL_DIVIDED }; - enum output_power_t { OUTPUT_POWER_M4DBM, OUTPUT_POWER_M1DBM, OUTPUT_POWER_2DBM, OUTPUT_POWER_5DBM }; - - enum muxout_t { MUXOUT_3STATE, MUXOUT_DVDD, MUXOUT_DGND, MUXOUT_RDIV, MUXOUT_NDIV, MUXOUT_ALD, MUXOUT_DLD }; + enum output_power_t { + OUTPUT_POWER_M4DBM, + OUTPUT_POWER_M1DBM, + OUTPUT_POWER_2DBM, + OUTPUT_POWER_5DBM + }; + + enum muxout_t { + MUXOUT_3STATE, + MUXOUT_DVDD, + MUXOUT_DGND, + MUXOUT_RDIV, + MUXOUT_NDIV, + MUXOUT_ALD, + MUXOUT_DLD + }; virtual void set_reference_freq(double fref, bool force = false) = 0; @@ -52,7 +65,8 @@ public: virtual void set_muxout_mode(muxout_t mode) = 0; - virtual double set_frequency(double target_freq, double freq_resolution, bool flush = false) = 0; + virtual double set_frequency( + double target_freq, double freq_resolution, bool flush = false) = 0; virtual void commit() = 0; }; @@ -60,405 +74,471 @@ public: using namespace uhd; namespace { - const double ADF535X_DOUBLER_MAX_REF_FREQ = 60e6; - const double ADF535X_MAX_FREQ_PFD = 125e6; -//const double ADF535X_PRESCALER_THRESH = 7e9; - - const double ADF535X_MIN_VCO_FREQ = 3.4e9; -//const double ADF535X_MAX_VCO_FREQ = 6.8e9; - const double ADF535X_MAX_OUT_FREQ = 6.8e9; - const double ADF535X_MIN_OUT_FREQ = (3.4e9 / 64); -//const double ADF535X_MAX_OUTB_FREQ = (6.8e9 * 2); -//const double ADF535X_MIN_OUTB_FREQ = (3.4e9 * 2); - - const double ADF535X_PHASE_RESYNC_TIME = 400e-6; - - const uint32_t ADF535X_MOD1 = 16777216; - const uint32_t ADF535X_MAX_MOD2 = 16383; - const uint32_t ADF535X_MAX_FRAC2 = 16383; -//const uint16_t ADF535X_MIN_INT_PRESCALER_89 = 75; -} - -template <typename adf535x_regs_t> -class adf535x_impl : public adf535x_iface +const double ADF535X_DOUBLER_MAX_REF_FREQ = 60e6; +const double ADF535X_MAX_FREQ_PFD = 125e6; +// const double ADF535X_PRESCALER_THRESH = 7e9; + +const double ADF535X_MIN_VCO_FREQ = 3.4e9; +// const double ADF535X_MAX_VCO_FREQ = 6.8e9; +const double ADF535X_MAX_OUT_FREQ = 6.8e9; +const double ADF535X_MIN_OUT_FREQ = (3.4e9 / 64); +// const double ADF535X_MAX_OUTB_FREQ = (6.8e9 * 2); +// const double ADF535X_MIN_OUTB_FREQ = (3.4e9 * 2); + +const double ADF535X_PHASE_RESYNC_TIME = 400e-6; + +const uint32_t ADF535X_MOD1 = 16777216; +const uint32_t ADF535X_MAX_MOD2 = 16383; +const uint32_t ADF535X_MAX_FRAC2 = 16383; +// const uint16_t ADF535X_MIN_INT_PRESCALER_89 = 75; +} // namespace + +template <typename adf535x_regs_t> class adf535x_impl : public adf535x_iface { public: - explicit adf535x_impl(write_fn_t write_fn, wait_fn_t wait_fn) : - _write_fn(std::move(write_fn)), - _wait_fn(std::move(wait_fn)), - _regs(), - _rewrite_regs(true), - _wait_time_us(0), - _ref_freq(0.0), - _pfd_freq(0.0), - _fb_after_divider(true) - { - - _regs.vco_band_div = 3; - _regs.timeout = 11; - _regs.auto_level_timeout = 30; - _regs.synth_lock_timeout = 12; - - _regs.adc_clock_divider = 16; - _regs.adc_conversion = adf535x_regs_t::ADC_CONVERSION_ENABLED; - _regs.adc_enable = adf535x_regs_t::ADC_ENABLE_ENABLED; - - // Start with phase resync disabled and enable when reference clock is set - _regs.phase_resync = adf535x_regs_t::PHASE_RESYNC_DISABLED; - - set_feedback_select(FB_SEL_DIVIDED); - } - - ~adf535x_impl() override - { - UHD_SAFE_CALL( - _regs.power_down = adf535x_regs_t::POWER_DOWN_ENABLED; - commit(); - ) - } - - void set_feedback_select(const feedback_sel_t fb_sel) override - { - _fb_after_divider = (fb_sel == FB_SEL_DIVIDED); - - if (_fb_after_divider) { - _regs.feedback_select = adf535x_regs_t::FEEDBACK_SELECT_DIVIDED; - } else { - _regs.feedback_select = adf535x_regs_t::FEEDBACK_SELECT_FUNDAMENTAL; + explicit adf535x_impl(write_fn_t write_fn, wait_fn_t wait_fn) + : _write_fn(std::move(write_fn)) + , _wait_fn(std::move(wait_fn)) + , _regs() + , _rewrite_regs(true) + , _wait_time_us(0) + , _ref_freq(0.0) + , _pfd_freq(0.0) + , _fb_after_divider(true) + { + _regs.vco_band_div = 3; + _regs.timeout = 11; + _regs.auto_level_timeout = 30; + _regs.synth_lock_timeout = 12; + + _regs.adc_clock_divider = 16; + _regs.adc_conversion = adf535x_regs_t::ADC_CONVERSION_ENABLED; + _regs.adc_enable = adf535x_regs_t::ADC_ENABLE_ENABLED; + + // Start with phase resync disabled and enable when reference clock is set + _regs.phase_resync = adf535x_regs_t::PHASE_RESYNC_DISABLED; + + set_feedback_select(FB_SEL_DIVIDED); } - } - - void set_pfd_freq(const double pfd_freq) override - { - if (pfd_freq > ADF535X_MAX_FREQ_PFD) { - UHD_LOGGER_ERROR("ADF535x") << boost::format("%f MHz is above the maximum PFD frequency of %f MHz\n") - % (pfd_freq/1e6) % (ADF535X_MAX_FREQ_PFD/1e6); - return; - } - _pfd_freq = pfd_freq; - - set_reference_freq(_ref_freq); - } - void set_reference_freq(const double fref, const bool force = false) override - { - //Skip the body if the reference frequency does not change - if (uhd::math::frequencies_are_equal(fref, _ref_freq) and (not force)) - return; - - _ref_freq = fref; + ~adf535x_impl() override + { + UHD_SAFE_CALL(_regs.power_down = adf535x_regs_t::POWER_DOWN_ENABLED; commit();) + } - //----------------------------------------------------------- - //Set reference settings - int ref_div_factor = static_cast<int>(std::floor(_ref_freq / _pfd_freq)); + void set_feedback_select(const feedback_sel_t fb_sel) override + { + _fb_after_divider = (fb_sel == FB_SEL_DIVIDED); - //Reference doubler for 50% duty cycle - const bool doubler_en = (_ref_freq <= ADF535X_DOUBLER_MAX_REF_FREQ); - if (doubler_en) { - ref_div_factor *= 2; + if (_fb_after_divider) { + _regs.feedback_select = adf535x_regs_t::FEEDBACK_SELECT_DIVIDED; + } else { + _regs.feedback_select = adf535x_regs_t::FEEDBACK_SELECT_FUNDAMENTAL; + } } - //Reference divide-by-2 for 50% duty cycle - // if R even, move one divide by 2 to regs.reference_divide_by_2 - const bool div2_en = (ref_div_factor % 2 == 0); - if (div2_en) { - ref_div_factor /= 2; + void set_pfd_freq(const double pfd_freq) override + { + if (pfd_freq > ADF535X_MAX_FREQ_PFD) { + UHD_LOGGER_ERROR("ADF535x") + << boost::format("%f MHz is above the maximum PFD frequency of %f MHz\n") + % (pfd_freq / 1e6) % (ADF535X_MAX_FREQ_PFD / 1e6); + return; + } + _pfd_freq = pfd_freq; + + set_reference_freq(_ref_freq); } - _regs.reference_divide_by_2 = div2_en ? - adf535x_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED : - adf535x_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; - _regs.reference_doubler = doubler_en ? - adf535x_regs_t::REFERENCE_DOUBLER_ENABLED : - adf535x_regs_t::REFERENCE_DOUBLER_DISABLED; - _regs.r_counter_10_bit = ref_div_factor; - UHD_ASSERT_THROW((_regs.r_counter_10_bit & ((uint16_t)~0x3FF)) == 0); - - //----------------------------------------------------------- - //Set timeouts (code from ADI driver) - _regs.timeout = std::max(1, std::min(int(ceil(_pfd_freq / (20e3 * 30))), 1023)); - - UHD_ASSERT_THROW((_regs.timeout & ((uint16_t)~0x3FF)) == 0); - _regs.synth_lock_timeout = + void set_reference_freq(const double fref, const bool force = false) override + { + // Skip the body if the reference frequency does not change + if (uhd::math::frequencies_are_equal(fref, _ref_freq) and (not force)) + return; + + _ref_freq = fref; + + //----------------------------------------------------------- + // Set reference settings + int ref_div_factor = static_cast<int>(std::floor(_ref_freq / _pfd_freq)); + + // Reference doubler for 50% duty cycle + const bool doubler_en = (_ref_freq <= ADF535X_DOUBLER_MAX_REF_FREQ); + if (doubler_en) { + ref_div_factor *= 2; + } + + // Reference divide-by-2 for 50% duty cycle + // if R even, move one divide by 2 to regs.reference_divide_by_2 + const bool div2_en = (ref_div_factor % 2 == 0); + if (div2_en) { + ref_div_factor /= 2; + } + + _regs.reference_divide_by_2 = + div2_en ? adf535x_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED + : adf535x_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; + _regs.reference_doubler = doubler_en ? adf535x_regs_t::REFERENCE_DOUBLER_ENABLED + : adf535x_regs_t::REFERENCE_DOUBLER_DISABLED; + _regs.r_counter_10_bit = ref_div_factor; + UHD_ASSERT_THROW((_regs.r_counter_10_bit & ((uint16_t)~0x3FF)) == 0); + + //----------------------------------------------------------- + // Set timeouts (code from ADI driver) + _regs.timeout = std::max(1, std::min(int(ceil(_pfd_freq / (20e3 * 30))), 1023)); + + UHD_ASSERT_THROW((_regs.timeout & ((uint16_t)~0x3FF)) == 0); + _regs.synth_lock_timeout = static_cast<uint8_t>(ceil((_pfd_freq * 2) / (100e3 * _regs.timeout))); - UHD_ASSERT_THROW((_regs.synth_lock_timeout & ((uint16_t)~0x1F)) == 0); - _regs.auto_level_timeout = + UHD_ASSERT_THROW((_regs.synth_lock_timeout & ((uint16_t)~0x1F)) == 0); + _regs.auto_level_timeout = static_cast<uint8_t>(ceil((_pfd_freq * 5) / (100e3 * _regs.timeout))); - //----------------------------------------------------------- - //Set VCO band divider - _regs.vco_band_div = - static_cast<uint8_t>(ceil(_pfd_freq / 2.4e6)); + //----------------------------------------------------------- + // Set VCO band divider + _regs.vco_band_div = static_cast<uint8_t>(ceil(_pfd_freq / 2.4e6)); - //----------------------------------------------------------- - //Set ADC delay (code from ADI driver) - _regs.adc_enable = adf535x_regs_t::ADC_ENABLE_ENABLED; - _regs.adc_conversion = adf535x_regs_t::ADC_CONVERSION_ENABLED; - _regs.adc_clock_divider = std::max(1, std::min(int(ceil(((_pfd_freq / 100e3) - 2) / 4)),255)); + //----------------------------------------------------------- + // Set ADC delay (code from ADI driver) + _regs.adc_enable = adf535x_regs_t::ADC_ENABLE_ENABLED; + _regs.adc_conversion = adf535x_regs_t::ADC_CONVERSION_ENABLED; + _regs.adc_clock_divider = + std::max(1, std::min(int(ceil(((_pfd_freq / 100e3) - 2) / 4)), 255)); - _wait_time_us = static_cast<uint32_t>( + _wait_time_us = static_cast<uint32_t>( ceil(16e6 / (_pfd_freq / ((4 * _regs.adc_clock_divider) + 2)))); - //----------------------------------------------------------- - //Phase resync - _regs.phase_resync = adf535x_regs_t::PHASE_RESYNC_ENABLED; - - _regs.phase_adjust = adf535x_regs_t::PHASE_ADJUST_DISABLED; - _regs.sd_load_reset = adf535x_regs_t::SD_LOAD_RESET_ON_REG0_UPDATE; - _regs.phase_resync_clk_div = static_cast<uint16_t>( - floor(ADF535X_PHASE_RESYNC_TIME * _pfd_freq)); - - _rewrite_regs = true; - } - - double set_frequency(const double target_freq, const double freq_resolution, const bool flush = false) override - { - return _set_frequency(target_freq, freq_resolution, flush); - } - - void set_output_power(const output_power_t power) override - { - typename adf535x_regs_t::output_power_t setting; - switch (power) { - case OUTPUT_POWER_M4DBM: setting = adf535x_regs_t::OUTPUT_POWER_M4DBM; break; - case OUTPUT_POWER_M1DBM: setting = adf535x_regs_t::OUTPUT_POWER_M1DBM; break; - case OUTPUT_POWER_2DBM: setting = adf535x_regs_t::OUTPUT_POWER_2DBM; break; - case OUTPUT_POWER_5DBM: setting = adf535x_regs_t::OUTPUT_POWER_5DBM; break; - default: UHD_THROW_INVALID_CODE_PATH(); + //----------------------------------------------------------- + // Phase resync + _regs.phase_resync = adf535x_regs_t::PHASE_RESYNC_ENABLED; + + _regs.phase_adjust = adf535x_regs_t::PHASE_ADJUST_DISABLED; + _regs.sd_load_reset = adf535x_regs_t::SD_LOAD_RESET_ON_REG0_UPDATE; + _regs.phase_resync_clk_div = + static_cast<uint16_t>(floor(ADF535X_PHASE_RESYNC_TIME * _pfd_freq)); + + _rewrite_regs = true; + } + + double set_frequency(const double target_freq, + const double freq_resolution, + const bool flush = false) override + { + return _set_frequency(target_freq, freq_resolution, flush); } - if (_regs.output_power != setting) _rewrite_regs = true; - _regs.output_power = setting; - } - - void set_output_enable(const output_t output, const bool enable) override - { - switch (output) { - case RF_OUTPUT_A: _regs.rf_out_a_enabled = enable ? adf535x_regs_t::RF_OUT_A_ENABLED_ENABLED : - adf535x_regs_t::RF_OUT_A_ENABLED_DISABLED; - break; - case RF_OUTPUT_B: _regs.rf_out_b_enabled = enable ? adf535x_regs_t::RF_OUT_B_ENABLED_ENABLED : - adf535x_regs_t::RF_OUT_B_ENABLED_DISABLED; - break; + + void set_output_power(const output_power_t power) override + { + typename adf535x_regs_t::output_power_t setting; + switch (power) { + case OUTPUT_POWER_M4DBM: + setting = adf535x_regs_t::OUTPUT_POWER_M4DBM; + break; + case OUTPUT_POWER_M1DBM: + setting = adf535x_regs_t::OUTPUT_POWER_M1DBM; + break; + case OUTPUT_POWER_2DBM: + setting = adf535x_regs_t::OUTPUT_POWER_2DBM; + break; + case OUTPUT_POWER_5DBM: + setting = adf535x_regs_t::OUTPUT_POWER_5DBM; + break; + default: + UHD_THROW_INVALID_CODE_PATH(); + } + if (_regs.output_power != setting) + _rewrite_regs = true; + _regs.output_power = setting; + } + + void set_output_enable(const output_t output, const bool enable) override + { + switch (output) { + case RF_OUTPUT_A: + _regs.rf_out_a_enabled = enable + ? adf535x_regs_t::RF_OUT_A_ENABLED_ENABLED + : adf535x_regs_t::RF_OUT_A_ENABLED_DISABLED; + break; + case RF_OUTPUT_B: + _regs.rf_out_b_enabled = enable + ? adf535x_regs_t::RF_OUT_B_ENABLED_ENABLED + : adf535x_regs_t::RF_OUT_B_ENABLED_DISABLED; + break; + } } - } - - void set_muxout_mode(const muxout_t mode) override - { - switch (mode) { - case MUXOUT_3STATE: _regs.muxout = adf535x_regs_t::MUXOUT_3STATE; break; - case MUXOUT_DVDD: _regs.muxout = adf535x_regs_t::MUXOUT_DVDD; break; - case MUXOUT_DGND: _regs.muxout = adf535x_regs_t::MUXOUT_DGND; break; - case MUXOUT_RDIV: _regs.muxout = adf535x_regs_t::MUXOUT_RDIV; break; - case MUXOUT_NDIV: _regs.muxout = adf535x_regs_t::MUXOUT_NDIV; break; - case MUXOUT_ALD: _regs.muxout = adf535x_regs_t::MUXOUT_ANALOG_LD; break; - case MUXOUT_DLD: _regs.muxout = adf535x_regs_t::MUXOUT_DLD; break; - default: UHD_THROW_INVALID_CODE_PATH(); + + void set_muxout_mode(const muxout_t mode) override + { + switch (mode) { + case MUXOUT_3STATE: + _regs.muxout = adf535x_regs_t::MUXOUT_3STATE; + break; + case MUXOUT_DVDD: + _regs.muxout = adf535x_regs_t::MUXOUT_DVDD; + break; + case MUXOUT_DGND: + _regs.muxout = adf535x_regs_t::MUXOUT_DGND; + break; + case MUXOUT_RDIV: + _regs.muxout = adf535x_regs_t::MUXOUT_RDIV; + break; + case MUXOUT_NDIV: + _regs.muxout = adf535x_regs_t::MUXOUT_NDIV; + break; + case MUXOUT_ALD: + _regs.muxout = adf535x_regs_t::MUXOUT_ANALOG_LD; + break; + case MUXOUT_DLD: + _regs.muxout = adf535x_regs_t::MUXOUT_DLD; + break; + default: + UHD_THROW_INVALID_CODE_PATH(); + } } - } - void commit() override - { - _commit(); - } + void commit() override + { + _commit(); + } protected: - double _set_frequency(double, double, bool); - void _commit(); - -private: //Members - typedef std::vector<uint32_t> addr_vtr_t; - - write_fn_t _write_fn; - wait_fn_t _wait_fn; - adf535x_regs_t _regs; - bool _rewrite_regs; - uint32_t _wait_time_us; - double _ref_freq; - double _pfd_freq; - double _fb_after_divider; + double _set_frequency(double, double, bool); + void _commit(); + +private: // Members + typedef std::vector<uint32_t> addr_vtr_t; + + write_fn_t _write_fn; + wait_fn_t _wait_fn; + adf535x_regs_t _regs; + bool _rewrite_regs; + uint32_t _wait_time_us; + double _ref_freq; + double _pfd_freq; + double _fb_after_divider; }; // ADF5355 Functions template <> -inline double adf535x_impl<adf5355_regs_t>::_set_frequency(double target_freq, double freq_resolution, bool flush) +inline double adf535x_impl<adf5355_regs_t>::_set_frequency( + double target_freq, double freq_resolution, bool flush) { - if (target_freq > ADF535X_MAX_OUT_FREQ or target_freq < ADF535X_MIN_OUT_FREQ) { - throw uhd::runtime_error("requested frequency out of range."); - } - if ((uint32_t) freq_resolution == 0) { - throw uhd::runtime_error("requested resolution cannot be less than 1."); - } - - /* Calculate target VCOout frequency */ - //Increase RF divider until acceptable VCO frequency - double target_vco_freq = target_freq; - uint32_t rf_divider = 1; - while (target_vco_freq < ADF535X_MIN_VCO_FREQ && rf_divider < 64) { - target_vco_freq *= 2; - rf_divider *= 2; - } - - switch (rf_divider) { - case 1: _regs.rf_divider_select = adf5355_regs_t::RF_DIVIDER_SELECT_DIV1; break; - case 2: _regs.rf_divider_select = adf5355_regs_t::RF_DIVIDER_SELECT_DIV2; break; - case 4: _regs.rf_divider_select = adf5355_regs_t::RF_DIVIDER_SELECT_DIV4; break; - case 8: _regs.rf_divider_select = adf5355_regs_t::RF_DIVIDER_SELECT_DIV8; break; - case 16: _regs.rf_divider_select = adf5355_regs_t::RF_DIVIDER_SELECT_DIV16; break; - case 32: _regs.rf_divider_select = adf5355_regs_t::RF_DIVIDER_SELECT_DIV32; break; - case 64: _regs.rf_divider_select = adf5355_regs_t::RF_DIVIDER_SELECT_DIV64; break; - default: UHD_THROW_INVALID_CODE_PATH(); - } - - //Compute fractional PLL params - double prescaler_input_freq = target_vco_freq; - if (_fb_after_divider) { - prescaler_input_freq /= rf_divider; - } - - const double N = prescaler_input_freq / _pfd_freq; - const auto INT = static_cast<uint16_t>(floor(N)); - const auto FRAC1 = static_cast<uint32_t>(floor((N - INT) * ADF535X_MOD1)); - const double residue = (N - INT) * ADF535X_MOD1 - FRAC1; - - const double gcd = boost::math::gcd(static_cast<int>(_pfd_freq), static_cast<int>(freq_resolution)); - const auto MOD2 = static_cast<uint16_t>(std::min(floor(_pfd_freq / gcd), static_cast<double>(ADF535X_MAX_MOD2))); - const auto FRAC2 = static_cast<uint16_t>(std::min(ceil(residue * MOD2), static_cast<double>(ADF535X_MAX_FRAC2))); - - const double coerced_vco_freq = _pfd_freq * - (_fb_after_divider ? rf_divider : 1) * - (double(INT) + ((double(FRAC1) + (double(FRAC2) / double(MOD2))) / - double(ADF535X_MOD1))); - - const double coerced_out_freq = coerced_vco_freq / rf_divider; - - /* Update registers */ - _regs.int_16_bit = INT; - _regs.frac1_24_bit = FRAC1; - _regs.frac2_14_bit = FRAC2; - _regs.mod2_14_bit = MOD2; - _regs.phase_24_bit = 0; - - if (flush) commit(); - return coerced_out_freq; + if (target_freq > ADF535X_MAX_OUT_FREQ or target_freq < ADF535X_MIN_OUT_FREQ) { + throw uhd::runtime_error("requested frequency out of range."); + } + if ((uint32_t)freq_resolution == 0) { + throw uhd::runtime_error("requested resolution cannot be less than 1."); + } + + /* Calculate target VCOout frequency */ + // Increase RF divider until acceptable VCO frequency + double target_vco_freq = target_freq; + uint32_t rf_divider = 1; + while (target_vco_freq < ADF535X_MIN_VCO_FREQ && rf_divider < 64) { + target_vco_freq *= 2; + rf_divider *= 2; + } + + switch (rf_divider) { + case 1: + _regs.rf_divider_select = adf5355_regs_t::RF_DIVIDER_SELECT_DIV1; + break; + case 2: + _regs.rf_divider_select = adf5355_regs_t::RF_DIVIDER_SELECT_DIV2; + break; + case 4: + _regs.rf_divider_select = adf5355_regs_t::RF_DIVIDER_SELECT_DIV4; + break; + case 8: + _regs.rf_divider_select = adf5355_regs_t::RF_DIVIDER_SELECT_DIV8; + break; + case 16: + _regs.rf_divider_select = adf5355_regs_t::RF_DIVIDER_SELECT_DIV16; + break; + case 32: + _regs.rf_divider_select = adf5355_regs_t::RF_DIVIDER_SELECT_DIV32; + break; + case 64: + _regs.rf_divider_select = adf5355_regs_t::RF_DIVIDER_SELECT_DIV64; + break; + default: + UHD_THROW_INVALID_CODE_PATH(); + } + + // Compute fractional PLL params + double prescaler_input_freq = target_vco_freq; + if (_fb_after_divider) { + prescaler_input_freq /= rf_divider; + } + + const double N = prescaler_input_freq / _pfd_freq; + const auto INT = static_cast<uint16_t>(floor(N)); + const auto FRAC1 = static_cast<uint32_t>(floor((N - INT) * ADF535X_MOD1)); + const double residue = (N - INT) * ADF535X_MOD1 - FRAC1; + + const double gcd = + boost::math::gcd(static_cast<int>(_pfd_freq), static_cast<int>(freq_resolution)); + const auto MOD2 = static_cast<uint16_t>( + std::min(floor(_pfd_freq / gcd), static_cast<double>(ADF535X_MAX_MOD2))); + const auto FRAC2 = static_cast<uint16_t>( + std::min(ceil(residue * MOD2), static_cast<double>(ADF535X_MAX_FRAC2))); + + const double coerced_vco_freq = + _pfd_freq * (_fb_after_divider ? rf_divider : 1) + * (double(INT) + + ((double(FRAC1) + (double(FRAC2) / double(MOD2))) + / double(ADF535X_MOD1))); + + const double coerced_out_freq = coerced_vco_freq / rf_divider; + + /* Update registers */ + _regs.int_16_bit = INT; + _regs.frac1_24_bit = FRAC1; + _regs.frac2_14_bit = FRAC2; + _regs.mod2_14_bit = MOD2; + _regs.phase_24_bit = 0; + + if (flush) + commit(); + return coerced_out_freq; } -template <> -inline void adf535x_impl<adf5355_regs_t>::_commit() +template <> inline void adf535x_impl<adf5355_regs_t>::_commit() { - const size_t ONE_REG = 1; - - if (_rewrite_regs) { - //For a full state sync write registers in reverse order 12 - 0 - addr_vtr_t regs; - for (uint8_t addr = 12; addr > 0; addr--) { - regs.push_back(_regs.get_reg(addr)); + const size_t ONE_REG = 1; + + if (_rewrite_regs) { + // For a full state sync write registers in reverse order 12 - 0 + addr_vtr_t regs; + for (uint8_t addr = 12; addr > 0; addr--) { + regs.push_back(_regs.get_reg(addr)); + } + _write_fn(regs); + _wait_fn(_wait_time_us); + _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(0))); + _rewrite_regs = false; + } else { + // Frequency update sequence from data sheet + _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(6))); + _regs.counter_reset = adf5355_regs_t::COUNTER_RESET_ENABLED; + _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(4))); + _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(2))); + _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(1))); + _regs.autocal_en = adf5355_regs_t::AUTOCAL_EN_DISABLED; + _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(0))); + _regs.counter_reset = adf5355_regs_t::COUNTER_RESET_DISABLED; + _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(4))); + _regs.autocal_en = adf5355_regs_t::AUTOCAL_EN_ENABLED; + _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(0))); } - _write_fn(regs); - _wait_fn(_wait_time_us); - _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(0))); - _rewrite_regs = false; - } else { - //Frequency update sequence from data sheet - _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(6))); - _regs.counter_reset = adf5355_regs_t::COUNTER_RESET_ENABLED; - _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(4))); - _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(2))); - _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(1))); - _regs.autocal_en = adf5355_regs_t::AUTOCAL_EN_DISABLED; - _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(0))); - _regs.counter_reset = adf5355_regs_t::COUNTER_RESET_DISABLED; - _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(4))); - _regs.autocal_en = adf5355_regs_t::AUTOCAL_EN_ENABLED; - _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(0))); - } } // ADF5356 Functions template <> -inline double adf535x_impl<adf5356_regs_t>::_set_frequency(double target_freq, double freq_resolution, bool flush) +inline double adf535x_impl<adf5356_regs_t>::_set_frequency( + double target_freq, double freq_resolution, bool flush) { - if (target_freq > ADF535X_MAX_OUT_FREQ or target_freq < ADF535X_MIN_OUT_FREQ) { - throw uhd::runtime_error("requested frequency out of range."); - } - if ((uint32_t) freq_resolution == 0) { - throw uhd::runtime_error("requested resolution cannot be less than 1."); - } - - /* Calculate target VCOout frequency */ - //Increase RF divider until acceptable VCO frequency - double target_vco_freq = target_freq; - uint32_t rf_divider = 1; - while (target_vco_freq < ADF535X_MIN_VCO_FREQ && rf_divider < 64) { - target_vco_freq *= 2; - rf_divider *= 2; - } - - switch (rf_divider) { - case 1: _regs.rf_divider_select = adf5356_regs_t::RF_DIVIDER_SELECT_DIV1; break; - case 2: _regs.rf_divider_select = adf5356_regs_t::RF_DIVIDER_SELECT_DIV2; break; - case 4: _regs.rf_divider_select = adf5356_regs_t::RF_DIVIDER_SELECT_DIV4; break; - case 8: _regs.rf_divider_select = adf5356_regs_t::RF_DIVIDER_SELECT_DIV8; break; - case 16: _regs.rf_divider_select = adf5356_regs_t::RF_DIVIDER_SELECT_DIV16; break; - case 32: _regs.rf_divider_select = adf5356_regs_t::RF_DIVIDER_SELECT_DIV32; break; - case 64: _regs.rf_divider_select = adf5356_regs_t::RF_DIVIDER_SELECT_DIV64; break; - default: UHD_THROW_INVALID_CODE_PATH(); - } - - //Compute fractional PLL params - double prescaler_input_freq = target_vco_freq; - if (_fb_after_divider) { - prescaler_input_freq /= rf_divider; - } - - const double N = prescaler_input_freq / _pfd_freq; - const auto INT = static_cast<uint16_t>(floor(N)); - const auto FRAC1 = static_cast<uint32_t>(floor((N - INT) * ADF535X_MOD1)); - const double residue = (N - INT) * ADF535X_MOD1 - FRAC1; - - const double gcd = boost::math::gcd(static_cast<int>(_pfd_freq), static_cast<int>(freq_resolution)); - const auto MOD2 = static_cast<uint16_t>(std::min(floor(_pfd_freq / gcd), static_cast<double>(ADF535X_MAX_MOD2))); - const auto FRAC2 = static_cast<uint16_t>(std::min(round(residue * MOD2), static_cast<double>(ADF535X_MAX_FRAC2))); - - const double coerced_vco_freq = _pfd_freq * - (_fb_after_divider ? rf_divider : 1) * - (double(INT) + ((double(FRAC1) + (double(FRAC2) / double(MOD2))) - / double(ADF535X_MOD1))); - - const double coerced_out_freq = coerced_vco_freq / rf_divider; - - /* Update registers */ - _regs.int_16_bit = INT; - _regs.frac1_24_bit = FRAC1; - _regs.frac2_msb = FRAC2; - _regs.mod2_msb = MOD2; - _regs.phase_24_bit = 0; - - if (flush) commit(); - return coerced_out_freq; + if (target_freq > ADF535X_MAX_OUT_FREQ or target_freq < ADF535X_MIN_OUT_FREQ) { + throw uhd::runtime_error("requested frequency out of range."); + } + if ((uint32_t)freq_resolution == 0) { + throw uhd::runtime_error("requested resolution cannot be less than 1."); + } + + /* Calculate target VCOout frequency */ + // Increase RF divider until acceptable VCO frequency + double target_vco_freq = target_freq; + uint32_t rf_divider = 1; + while (target_vco_freq < ADF535X_MIN_VCO_FREQ && rf_divider < 64) { + target_vco_freq *= 2; + rf_divider *= 2; + } + + switch (rf_divider) { + case 1: + _regs.rf_divider_select = adf5356_regs_t::RF_DIVIDER_SELECT_DIV1; + break; + case 2: + _regs.rf_divider_select = adf5356_regs_t::RF_DIVIDER_SELECT_DIV2; + break; + case 4: + _regs.rf_divider_select = adf5356_regs_t::RF_DIVIDER_SELECT_DIV4; + break; + case 8: + _regs.rf_divider_select = adf5356_regs_t::RF_DIVIDER_SELECT_DIV8; + break; + case 16: + _regs.rf_divider_select = adf5356_regs_t::RF_DIVIDER_SELECT_DIV16; + break; + case 32: + _regs.rf_divider_select = adf5356_regs_t::RF_DIVIDER_SELECT_DIV32; + break; + case 64: + _regs.rf_divider_select = adf5356_regs_t::RF_DIVIDER_SELECT_DIV64; + break; + default: + UHD_THROW_INVALID_CODE_PATH(); + } + + // Compute fractional PLL params + double prescaler_input_freq = target_vco_freq; + if (_fb_after_divider) { + prescaler_input_freq /= rf_divider; + } + + const double N = prescaler_input_freq / _pfd_freq; + const auto INT = static_cast<uint16_t>(floor(N)); + const auto FRAC1 = static_cast<uint32_t>(floor((N - INT) * ADF535X_MOD1)); + const double residue = (N - INT) * ADF535X_MOD1 - FRAC1; + + const double gcd = + boost::math::gcd(static_cast<int>(_pfd_freq), static_cast<int>(freq_resolution)); + const auto MOD2 = static_cast<uint16_t>( + std::min(floor(_pfd_freq / gcd), static_cast<double>(ADF535X_MAX_MOD2))); + const auto FRAC2 = static_cast<uint16_t>( + std::min(round(residue * MOD2), static_cast<double>(ADF535X_MAX_FRAC2))); + + const double coerced_vco_freq = + _pfd_freq * (_fb_after_divider ? rf_divider : 1) + * (double(INT) + + ((double(FRAC1) + (double(FRAC2) / double(MOD2))) + / double(ADF535X_MOD1))); + + const double coerced_out_freq = coerced_vco_freq / rf_divider; + + /* Update registers */ + _regs.int_16_bit = INT; + _regs.frac1_24_bit = FRAC1; + _regs.frac2_msb = FRAC2; + _regs.mod2_msb = MOD2; + _regs.phase_24_bit = 0; + + if (flush) + commit(); + return coerced_out_freq; } -template <> -inline void adf535x_impl<adf5356_regs_t>::_commit() +template <> inline void adf535x_impl<adf5356_regs_t>::_commit() { - const size_t ONE_REG = 1; - if (_rewrite_regs) { - //For a full state sync write registers in reverse order 12 - 0 - addr_vtr_t regs; - for (uint8_t addr = 13; addr > 0; addr--) { - regs.push_back(_regs.get_reg(addr)); + const size_t ONE_REG = 1; + if (_rewrite_regs) { + // For a full state sync write registers in reverse order 12 - 0 + addr_vtr_t regs; + for (uint8_t addr = 13; addr > 0; addr--) { + regs.push_back(_regs.get_reg(addr)); + } + _write_fn(regs); + _wait_fn(_wait_time_us); + _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(0))); + _rewrite_regs = false; + } else { + // Frequency update sequence from data sheet + _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(13))); + _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(6))); + _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(2))); + _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(1))); + _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(0))); } - _write_fn(regs); - _wait_fn(_wait_time_us); - _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(0))); - _rewrite_regs = false; - } else { - //Frequency update sequence from data sheet - _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(13))); - _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(6))); - _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(2))); - _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(1))); - _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(0))); - } } #endif // INCLUDED_ADF535X_HPP diff --git a/host/lib/include/uhdlib/usrp/common/lmx2592.hpp b/host/lib/include/uhdlib/usrp/common/lmx2592.hpp index 91beb24b7..f71ae0cf5 100644 --- a/host/lib/include/uhdlib/usrp/common/lmx2592.hpp +++ b/host/lib/include/uhdlib/usrp/common/lmx2592.hpp @@ -19,7 +19,8 @@ #include <utility> #include <vector> -class lmx2592_iface { +class lmx2592_iface +{ public: typedef std::shared_ptr<lmx2592_iface> sptr; @@ -37,8 +38,7 @@ public: enum mash_order_t { INT_N, FIRST, SECOND, THIRD, FOURTH }; - virtual double set_frequency( - double target_freq, + virtual double set_frequency(double target_freq, const bool spur_dodging, const double spur_dodging_threshold) = 0; diff --git a/host/lib/usrp/b100/clock_ctrl.cpp b/host/lib/usrp/b100/clock_ctrl.cpp index 7a089e293..e30ca120f 100644 --- a/host/lib/usrp/b100/clock_ctrl.cpp +++ b/host/lib/usrp/b100/clock_ctrl.cpp @@ -7,79 +7,89 @@ #include "clock_ctrl.hpp" #include "ad9522_regs.hpp" -#include <uhd/utils/log.hpp> - +#include "b100_regs.hpp" //spi slave constants #include <uhd/exception.hpp> #include <uhd/utils/assert_has.hpp> +#include <uhd/utils/log.hpp> #include <uhd/utils/safe_call.hpp> #include <stdint.h> -#include "b100_regs.hpp" //spi slave constants #include <boost/format.hpp> #include <boost/math/common_factor_rt.hpp> //gcd #include <algorithm> -#include <utility> #include <chrono> #include <thread> +#include <utility> using namespace uhd; /*********************************************************************** * Constants **********************************************************************/ -static const bool ENABLE_THE_TEST_OUT = true; +static const bool ENABLE_THE_TEST_OUT = true; static const double REFERENCE_INPUT_RATE = 10e6; /*********************************************************************** * Helpers **********************************************************************/ -template <typename div_type, typename bypass_type> static void set_clock_divider( - size_t divider, div_type &low, div_type &high, bypass_type &bypass -){ - high = divider/2 - 1; - low = divider - high - 2; - bypass = (divider == 1)? 1 : 0; +template <typename div_type, typename bypass_type> +static void set_clock_divider( + size_t divider, div_type& low, div_type& high, bypass_type& bypass) +{ + high = divider / 2 - 1; + low = divider - high - 2; + bypass = (divider == 1) ? 1 : 0; } /*********************************************************************** * Clock rate calculation stuff: * Using the internal VCO between 1400 and 1800 MHz **********************************************************************/ -struct clock_settings_type{ - size_t ref_clock_doubler, r_counter, a_counter, b_counter, prescaler, vco_divider, chan_divider; - size_t get_n_counter(void) const{return prescaler * b_counter + a_counter;} - double get_ref_rate(void) const{return REFERENCE_INPUT_RATE * ref_clock_doubler;} - double get_vco_rate(void) const{return get_ref_rate()/r_counter * get_n_counter();} - double get_chan_rate(void) const{return get_vco_rate()/vco_divider;} - double get_out_rate(void) const{return get_chan_rate()/chan_divider;} - std::string to_pp_string(void) const{ - return str(boost::format( - " r_counter: %d\n" - " a_counter: %d\n" - " b_counter: %d\n" - " prescaler: %d\n" - " vco_divider: %d\n" - " chan_divider: %d\n" - " vco_rate: %fMHz\n" - " chan_rate: %fMHz\n" - " out_rate: %fMHz\n" - ) - % r_counter - % a_counter - % b_counter - % prescaler - % vco_divider - % chan_divider - % (get_vco_rate()/1e6) - % (get_chan_rate()/1e6) - % (get_out_rate()/1e6) - ); +struct clock_settings_type +{ + size_t ref_clock_doubler, r_counter, a_counter, b_counter, prescaler, vco_divider, + chan_divider; + size_t get_n_counter(void) const + { + return prescaler * b_counter + a_counter; + } + double get_ref_rate(void) const + { + return REFERENCE_INPUT_RATE * ref_clock_doubler; + } + double get_vco_rate(void) const + { + return get_ref_rate() / r_counter * get_n_counter(); + } + double get_chan_rate(void) const + { + return get_vco_rate() / vco_divider; + } + double get_out_rate(void) const + { + return get_chan_rate() / chan_divider; + } + std::string to_pp_string(void) const + { + return str(boost::format(" r_counter: %d\n" + " a_counter: %d\n" + " b_counter: %d\n" + " prescaler: %d\n" + " vco_divider: %d\n" + " chan_divider: %d\n" + " vco_rate: %fMHz\n" + " chan_rate: %fMHz\n" + " out_rate: %fMHz\n") + % r_counter % a_counter % b_counter % prescaler % vco_divider + % chan_divider % (get_vco_rate() / 1e6) % (get_chan_rate() / 1e6) + % (get_out_rate() / 1e6)); } }; //! gives the greatest divisor of num between 1 and max inclusive -template<typename T> static inline T greatest_divisor(T num, T max){ - for (T i = max; i > 1; i--){ - if (num%i == 0){ +template <typename T> static inline T greatest_divisor(T num, T max) +{ + for (T i = max; i > 1; i--) { + if (num % i == 0) { return i; } } @@ -87,116 +97,130 @@ template<typename T> static inline T greatest_divisor(T num, T max){ } //! gives the least divisor of num between min and num exclusive -template<typename T> static inline T least_divisor(T num, T min){ - for (T i = min; i < num; i++){ - if (num%i == 0){ +template <typename T> static inline T least_divisor(T num, T min) +{ + for (T i = min; i < num; i++) { + if (num % i == 0) { return i; } } return 1; } -static clock_settings_type get_clock_settings(double rate){ +static clock_settings_type get_clock_settings(double rate) +{ clock_settings_type cs; - cs.ref_clock_doubler = 2; //always doubling - cs.prescaler = 8; //set to 8 when input is under 2400 MHz + cs.ref_clock_doubler = 2; // always doubling + cs.prescaler = 8; // set to 8 when input is under 2400 MHz - //basic formulas used below: - //out_rate*X = ref_rate*Y - //X = i*ref_rate/gcd - //Y = i*out_rate/gcd - //X = chan_div * vco_div * R - //Y = P*B + A + // basic formulas used below: + // out_rate*X = ref_rate*Y + // X = i*ref_rate/gcd + // Y = i*out_rate/gcd + // X = chan_div * vco_div * R + // Y = P*B + A const uint64_t out_rate = uint64_t(rate); const uint64_t ref_rate = uint64_t(cs.get_ref_rate()); - const size_t gcd = size_t(boost::math::gcd(ref_rate, out_rate)); + const size_t gcd = size_t(boost::math::gcd(ref_rate, out_rate)); - for (size_t i = 1; i <= 100; i++){ - const size_t X = size_t(i*ref_rate/gcd); - const size_t Y = size_t(i*out_rate/gcd); + for (size_t i = 1; i <= 100; i++) { + const size_t X = size_t(i * ref_rate / gcd); + const size_t Y = size_t(i * out_rate / gcd); - //determine A and B (P is fixed) - cs.b_counter = Y/cs.prescaler; - cs.a_counter = Y - cs.b_counter*cs.prescaler; + // determine A and B (P is fixed) + cs.b_counter = Y / cs.prescaler; + cs.a_counter = Y - cs.b_counter * cs.prescaler; static const double vco_bound_pad = 100e6; - for ( //calculate an r divider that fits into the bounds of the vco - cs.r_counter = size_t(cs.get_n_counter()*cs.get_ref_rate()/(1800e6 - vco_bound_pad)); - cs.r_counter <= size_t(cs.get_n_counter()*cs.get_ref_rate()/(1400e6 + vco_bound_pad)) - and cs.r_counter > 0; cs.r_counter++ - ){ - - //determine chan_div and vco_div - //and fill in that order of preference - cs.chan_divider = greatest_divisor<size_t>(X/cs.r_counter, 32); - cs.vco_divider = greatest_divisor<size_t>(X/cs.chan_divider/cs.r_counter, 6); - - //avoid a vco divider of 1 (if possible) - if (cs.vco_divider == 1){ + for ( // calculate an r divider that fits into the bounds of the vco + cs.r_counter = + size_t(cs.get_n_counter() * cs.get_ref_rate() / (1800e6 - vco_bound_pad)); + cs.r_counter <= size_t(cs.get_n_counter() * cs.get_ref_rate() + / (1400e6 + vco_bound_pad)) + and cs.r_counter > 0; + cs.r_counter++) { + // determine chan_div and vco_div + // and fill in that order of preference + cs.chan_divider = greatest_divisor<size_t>(X / cs.r_counter, 32); + cs.vco_divider = + greatest_divisor<size_t>(X / cs.chan_divider / cs.r_counter, 6); + + // avoid a vco divider of 1 (if possible) + if (cs.vco_divider == 1) { cs.vco_divider = least_divisor<size_t>(cs.chan_divider, 2); cs.chan_divider /= cs.vco_divider; } UHD_LOGGER_TRACE("B100") - << "gcd: " << gcd - << " X: " << X - << " Y: " << Y - << cs.to_pp_string() - ; - - //filter limits on the counters - if (cs.vco_divider == 1) continue; - if (cs.r_counter >= (1<<14)) continue; - if (cs.b_counter == 2) continue; - if (cs.b_counter == 1 and cs.a_counter != 0) continue; - if (cs.b_counter >= (1<<13)) continue; - if (cs.a_counter >= (1<<6)) continue; - if (cs.get_vco_rate() > 1800e6 - vco_bound_pad) continue; - if (cs.get_vco_rate() < 1400e6 + vco_bound_pad) continue; - if (cs.get_out_rate() != rate) continue; - - UHD_LOGGER_TRACE("B100") << "USRP-B100 clock control: " << i << cs.to_pp_string() ; + << "gcd: " << gcd << " X: " << X << " Y: " << Y << cs.to_pp_string(); + + // filter limits on the counters + if (cs.vco_divider == 1) + continue; + if (cs.r_counter >= (1 << 14)) + continue; + if (cs.b_counter == 2) + continue; + if (cs.b_counter == 1 and cs.a_counter != 0) + continue; + if (cs.b_counter >= (1 << 13)) + continue; + if (cs.a_counter >= (1 << 6)) + continue; + if (cs.get_vco_rate() > 1800e6 - vco_bound_pad) + continue; + if (cs.get_vco_rate() < 1400e6 + vco_bound_pad) + continue; + if (cs.get_out_rate() != rate) + continue; + + UHD_LOGGER_TRACE("B100") + << "USRP-B100 clock control: " << i << cs.to_pp_string(); return cs; } } - throw uhd::value_error(str(boost::format( - "USRP-B100 clock control: could not calculate settings for clock rate %fMHz" - ) % (rate/1e6))); + throw uhd::value_error(str( + boost::format( + "USRP-B100 clock control: could not calculate settings for clock rate %fMHz") + % (rate / 1e6))); } -b100_clock_ctrl::~b100_clock_ctrl(void) { +b100_clock_ctrl::~b100_clock_ctrl(void) +{ /* NOP */ } /*********************************************************************** * Clock Control Implementation **********************************************************************/ -class b100_clock_ctrl_impl : public b100_clock_ctrl{ +class b100_clock_ctrl_impl : public b100_clock_ctrl +{ public: - b100_clock_ctrl_impl(i2c_iface::sptr iface, double master_clock_rate){ - _iface = iface; + b100_clock_ctrl_impl(i2c_iface::sptr iface, double master_clock_rate) + { + _iface = iface; _chan_rate = 0.0; - _out_rate = 0.0; + _out_rate = 0.0; - //perform soft-reset + // perform soft-reset _ad9522_regs.soft_reset = 1; this->send_reg(0x000); this->latch_regs(); _ad9522_regs.soft_reset = 0; - //init the clock gen registers - _ad9522_regs.sdo_active = ad9522_regs_t::SDO_ACTIVE_SDO_SDIO; - _ad9522_regs.enb_stat_eeprom_at_stat_pin = 0; //use status pin - _ad9522_regs.status_pin_control = 0x1; //n divider - _ad9522_regs.ld_pin_control = 0x00; //dld - _ad9522_regs.refmon_pin_control = 0x12; //show ref2 + // init the clock gen registers + _ad9522_regs.sdo_active = ad9522_regs_t::SDO_ACTIVE_SDO_SDIO; + _ad9522_regs.enb_stat_eeprom_at_stat_pin = 0; // use status pin + _ad9522_regs.status_pin_control = 0x1; // n divider + _ad9522_regs.ld_pin_control = 0x00; // dld + _ad9522_regs.refmon_pin_control = 0x12; // show ref2 _ad9522_regs.lock_detect_counter = ad9522_regs_t::LOCK_DETECT_COUNTER_16CYC; this->use_internal_ref(); - this->set_fpga_clock_rate(master_clock_rate); //initialize to something + this->set_fpga_clock_rate(master_clock_rate); // initialize to something this->enable_fpga_clock(true); this->enable_test_clock(ENABLE_THE_TEST_OUT); @@ -204,12 +228,12 @@ public: this->enable_tx_dboard_clock(false); } - ~b100_clock_ctrl_impl(void){ - UHD_SAFE_CALL( - this->enable_test_clock(ENABLE_THE_TEST_OUT); - this->enable_rx_dboard_clock(false); - this->enable_tx_dboard_clock(false); - //this->enable_fpga_clock(false); //FIXME + ~b100_clock_ctrl_impl(void) + { + UHD_SAFE_CALL(this->enable_test_clock(ENABLE_THE_TEST_OUT); + this->enable_rx_dboard_clock(false); + this->enable_tx_dboard_clock(false); + // this->enable_fpga_clock(false); //FIXME ) } @@ -218,105 +242,123 @@ public: * - set clock rate w/ internal VCO * - set clock rate w/ external VCXO **********************************************************************/ - void set_clock_settings_with_internal_vco(double rate){ + void set_clock_settings_with_internal_vco(double rate) + { const clock_settings_type cs = get_clock_settings(rate); - //set the rates to private variables so the implementation knows! + // set the rates to private variables so the implementation knows! _chan_rate = cs.get_chan_rate(); - _out_rate = cs.get_out_rate(); + _out_rate = cs.get_out_rate(); - _ad9522_regs.enable_clock_doubler = (cs.ref_clock_doubler == 2)? 1 : 0; + _ad9522_regs.enable_clock_doubler = (cs.ref_clock_doubler == 2) ? 1 : 0; _ad9522_regs.set_r_counter(cs.r_counter); _ad9522_regs.a_counter = cs.a_counter; _ad9522_regs.set_b_counter(cs.b_counter); - UHD_ASSERT_THROW(cs.prescaler == 8); //assumes this below: + UHD_ASSERT_THROW(cs.prescaler == 8); // assumes this below: _ad9522_regs.prescaler_p = ad9522_regs_t::PRESCALER_P_DIV8_9; _ad9522_regs.pll_power_down = ad9522_regs_t::PLL_POWER_DOWN_NORMAL; - _ad9522_regs.cp_current = ad9522_regs_t::CP_CURRENT_1_2MA; + _ad9522_regs.cp_current = ad9522_regs_t::CP_CURRENT_1_2MA; _ad9522_regs.bypass_vco_divider = 0; - switch(cs.vco_divider){ - case 1: _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV1; break; - case 2: _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV2; break; - case 3: _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV3; break; - case 4: _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV4; break; - case 5: _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV5; break; - case 6: _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV6; break; + switch (cs.vco_divider) { + case 1: + _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV1; + break; + case 2: + _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV2; + break; + case 3: + _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV3; + break; + case 4: + _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV4; + break; + case 5: + _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV5; + break; + case 6: + _ad9522_regs.vco_divider = ad9522_regs_t::VCO_DIVIDER_DIV6; + break; } _ad9522_regs.select_vco_or_clock = ad9522_regs_t::SELECT_VCO_OR_CLOCK_VCO; - //setup fpga master clock + // setup fpga master clock _ad9522_regs.out0_format = ad9522_regs_t::OUT0_FORMAT_LVDS; set_clock_divider(cs.chan_divider, _ad9522_regs.divider0_low_cycles, _ad9522_regs.divider0_high_cycles, - _ad9522_regs.divider0_bypass - ); + _ad9522_regs.divider0_bypass); - //setup codec clock + // setup codec clock _ad9522_regs.out3_format = ad9522_regs_t::OUT3_FORMAT_LVDS; set_clock_divider(cs.chan_divider, _ad9522_regs.divider1_low_cycles, _ad9522_regs.divider1_high_cycles, - _ad9522_regs.divider1_bypass - ); + _ad9522_regs.divider1_bypass); this->send_all_regs(); calibrate_now(); } - void set_clock_settings_with_external_vcxo(double rate){ - //set the rates to private variables so the implementation knows! + void set_clock_settings_with_external_vcxo(double rate) + { + // set the rates to private variables so the implementation knows! _chan_rate = rate; - _out_rate = rate; + _out_rate = rate; - _ad9522_regs.enable_clock_doubler = 1; //doubler always on - const double ref_rate = REFERENCE_INPUT_RATE*2; + _ad9522_regs.enable_clock_doubler = 1; // doubler always on + const double ref_rate = REFERENCE_INPUT_RATE * 2; - //bypass prescaler such that N = B + // bypass prescaler such that N = B long gcd = boost::math::gcd(long(ref_rate), long(rate)); - _ad9522_regs.set_r_counter(int(ref_rate/gcd)); + _ad9522_regs.set_r_counter(int(ref_rate / gcd)); _ad9522_regs.a_counter = 0; - _ad9522_regs.set_b_counter(int(rate/gcd)); + _ad9522_regs.set_b_counter(int(rate / gcd)); _ad9522_regs.prescaler_p = ad9522_regs_t::PRESCALER_P_DIV1; - //setup external vcxo - _ad9522_regs.pll_power_down = ad9522_regs_t::PLL_POWER_DOWN_NORMAL; - _ad9522_regs.cp_current = ad9522_regs_t::CP_CURRENT_1_2MA; - _ad9522_regs.bypass_vco_divider = 1; + // setup external vcxo + _ad9522_regs.pll_power_down = ad9522_regs_t::PLL_POWER_DOWN_NORMAL; + _ad9522_regs.cp_current = ad9522_regs_t::CP_CURRENT_1_2MA; + _ad9522_regs.bypass_vco_divider = 1; _ad9522_regs.select_vco_or_clock = ad9522_regs_t::SELECT_VCO_OR_CLOCK_EXTERNAL; - //setup fpga master clock - _ad9522_regs.out0_format = ad9522_regs_t::OUT0_FORMAT_LVDS; + // setup fpga master clock + _ad9522_regs.out0_format = ad9522_regs_t::OUT0_FORMAT_LVDS; _ad9522_regs.divider0_bypass = 1; - //setup codec clock - _ad9522_regs.out3_format = ad9522_regs_t::OUT3_FORMAT_LVDS; + // setup codec clock + _ad9522_regs.out3_format = ad9522_regs_t::OUT3_FORMAT_LVDS; _ad9522_regs.divider1_bypass = 1; this->send_all_regs(); } - void set_fpga_clock_rate(double rate){ - if (_out_rate == rate) return; - if (rate == 61.44e6) set_clock_settings_with_external_vcxo(rate); - else set_clock_settings_with_internal_vco(rate); - //clock rate changed! update dboard clocks and FPGA ticks per second + void set_fpga_clock_rate(double rate) + { + if (_out_rate == rate) + return; + if (rate == 61.44e6) + set_clock_settings_with_external_vcxo(rate); + else + set_clock_settings_with_internal_vco(rate); + // clock rate changed! update dboard clocks and FPGA ticks per second set_rx_dboard_clock_rate(rate); set_tx_dboard_clock_rate(rate); } - double get_fpga_clock_rate(void){ + double get_fpga_clock_rate(void) + { return this->_out_rate; } /*********************************************************************** * FPGA clock enable **********************************************************************/ - void enable_fpga_clock(bool enb){ - _ad9522_regs.out0_format = ad9522_regs_t::OUT0_FORMAT_LVDS; + void enable_fpga_clock(bool enb) + { + _ad9522_regs.out0_format = ad9522_regs_t::OUT0_FORMAT_LVDS; _ad9522_regs.out0_lvds_power_down = !enb; this->send_reg(0x0F0); this->latch_regs(); @@ -325,12 +367,13 @@ public: /*********************************************************************** * Special test clock output **********************************************************************/ - void enable_test_clock(bool enb){ - //setup test clock (same divider as codec clock) + void enable_test_clock(bool enb) + { + // setup test clock (same divider as codec clock) _ad9522_regs.out4_format = ad9522_regs_t::OUT4_FORMAT_CMOS; - _ad9522_regs.out4_cmos_configuration = (enb)? - ad9522_regs_t::OUT4_CMOS_CONFIGURATION_A_ON : - ad9522_regs_t::OUT4_CMOS_CONFIGURATION_OFF; + _ad9522_regs.out4_cmos_configuration = + (enb) ? ad9522_regs_t::OUT4_CMOS_CONFIGURATION_A_ON + : ad9522_regs_t::OUT4_CMOS_CONFIGURATION_OFF; this->send_reg(0x0F4); this->latch_regs(); } @@ -338,105 +381,118 @@ public: /*********************************************************************** * RX Dboard Clock Control (output 9, divider 3) **********************************************************************/ - void enable_rx_dboard_clock(bool enb){ - _ad9522_regs.out9_format = ad9522_regs_t::OUT9_FORMAT_LVDS; + void enable_rx_dboard_clock(bool enb) + { + _ad9522_regs.out9_format = ad9522_regs_t::OUT9_FORMAT_LVDS; _ad9522_regs.out9_lvds_power_down = !enb; this->send_reg(0x0F9); this->latch_regs(); } - std::vector<double> get_rx_dboard_clock_rates(void){ + std::vector<double> get_rx_dboard_clock_rates(void) + { std::vector<double> rates; - for(size_t div = 1; div <= 16+16; div++) - rates.push_back(this->_chan_rate/div); + for (size_t div = 1; div <= 16 + 16; div++) + rates.push_back(this->_chan_rate / div); return rates; } - void set_rx_dboard_clock_rate(double rate){ + void set_rx_dboard_clock_rate(double rate) + { assert_has(get_rx_dboard_clock_rates(), rate, "rx dboard clock rate"); _rx_clock_rate = rate; - size_t divider = size_t(this->_chan_rate/rate); - //set the divider registers + size_t divider = size_t(this->_chan_rate / rate); + // set the divider registers set_clock_divider(divider, _ad9522_regs.divider3_low_cycles, _ad9522_regs.divider3_high_cycles, - _ad9522_regs.divider3_bypass - ); + _ad9522_regs.divider3_bypass); this->send_reg(0x199); this->send_reg(0x19a); this->soft_sync(); } - double get_rx_clock_rate(void){ + double get_rx_clock_rate(void) + { return _rx_clock_rate; } /*********************************************************************** * TX Dboard Clock Control (output 6, divider 2) **********************************************************************/ - void enable_tx_dboard_clock(bool enb){ - _ad9522_regs.out6_format = ad9522_regs_t::OUT6_FORMAT_LVDS; + void enable_tx_dboard_clock(bool enb) + { + _ad9522_regs.out6_format = ad9522_regs_t::OUT6_FORMAT_LVDS; _ad9522_regs.out6_lvds_power_down = !enb; this->send_reg(0x0F6); this->latch_regs(); } - std::vector<double> get_tx_dboard_clock_rates(void){ - return get_rx_dboard_clock_rates(); //same master clock, same dividers... + std::vector<double> get_tx_dboard_clock_rates(void) + { + return get_rx_dboard_clock_rates(); // same master clock, same dividers... } - void set_tx_dboard_clock_rate(double rate){ + void set_tx_dboard_clock_rate(double rate) + { assert_has(get_tx_dboard_clock_rates(), rate, "tx dboard clock rate"); _tx_clock_rate = rate; - size_t divider = size_t(this->_chan_rate/rate); - //set the divider registers + size_t divider = size_t(this->_chan_rate / rate); + // set the divider registers set_clock_divider(divider, _ad9522_regs.divider2_low_cycles, _ad9522_regs.divider2_high_cycles, - _ad9522_regs.divider2_bypass - ); + _ad9522_regs.divider2_bypass); this->send_reg(0x196); this->send_reg(0x197); this->soft_sync(); } - double get_tx_clock_rate(void){ + double get_tx_clock_rate(void) + { return _tx_clock_rate; } /*********************************************************************** * Clock reference control **********************************************************************/ - void use_internal_ref(void) { + void use_internal_ref(void) + { _ad9522_regs.enable_ref2 = 1; _ad9522_regs.enable_ref1 = 0; - _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF2; - _ad9522_regs.enb_auto_ref_switchover = ad9522_regs_t::ENB_AUTO_REF_SWITCHOVER_MANUAL; + _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF2; + _ad9522_regs.enb_auto_ref_switchover = + ad9522_regs_t::ENB_AUTO_REF_SWITCHOVER_MANUAL; this->send_reg(0x01C); this->latch_regs(); } - void use_external_ref(void) { + void use_external_ref(void) + { _ad9522_regs.enable_ref2 = 0; _ad9522_regs.enable_ref1 = 1; - _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF1; - _ad9522_regs.enb_auto_ref_switchover = ad9522_regs_t::ENB_AUTO_REF_SWITCHOVER_MANUAL; + _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF1; + _ad9522_regs.enb_auto_ref_switchover = + ad9522_regs_t::ENB_AUTO_REF_SWITCHOVER_MANUAL; this->send_reg(0x01C); this->latch_regs(); } - void use_auto_ref(void) { + void use_auto_ref(void) + { _ad9522_regs.enable_ref2 = 1; _ad9522_regs.enable_ref1 = 1; - _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF1; - _ad9522_regs.enb_auto_ref_switchover = ad9522_regs_t::ENB_AUTO_REF_SWITCHOVER_AUTO; + _ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF1; + _ad9522_regs.enb_auto_ref_switchover = + ad9522_regs_t::ENB_AUTO_REF_SWITCHOVER_AUTO; this->send_reg(0x01C); this->latch_regs(); } - bool get_locked(void){ + bool get_locked(void) + { static const uint8_t addr = 0x01F; - uint32_t reg = this->read_reg(addr); + uint32_t reg = this->read_reg(addr); _ad9522_regs.set_reg(addr, reg); return _ad9522_regs.digital_lock_detect != 0; } @@ -444,18 +500,20 @@ public: private: i2c_iface::sptr _iface; ad9522_regs_t _ad9522_regs; - double _out_rate; //rate at the fpga and codec - double _chan_rate; //rate before final dividers + double _out_rate; // rate at the fpga and codec + double _chan_rate; // rate before final dividers double _rx_clock_rate, _tx_clock_rate; - void latch_regs(void){ + void latch_regs(void) + { _ad9522_regs.io_update = 1; this->send_reg(0x232); } - void send_reg(uint16_t addr){ + void send_reg(uint16_t addr) + { uint32_t reg = _ad9522_regs.get_write_reg(addr); - UHD_LOGGER_TRACE("B100") << "clock control write reg: " << std::hex << reg ; + UHD_LOGGER_TRACE("B100") << "clock control write reg: " << std::hex << reg; byte_vector_t buf; buf.push_back(uint8_t(reg >> 16)); buf.push_back(uint8_t(reg >> 8)); @@ -464,7 +522,8 @@ private: _iface->write_i2c(0x5C, buf); } - uint8_t read_reg(uint16_t addr){ + uint8_t read_reg(uint16_t addr) + { byte_vector_t buf; buf.push_back(uint8_t(addr >> 8)); buf.push_back(uint8_t(addr & 0xff)); @@ -475,35 +534,39 @@ private: return uint32_t(buf[0] & 0xFF); } - void calibrate_now(void){ - //vco calibration routine: + void calibrate_now(void) + { + // vco calibration routine: _ad9522_regs.vco_calibration_now = 0; this->send_reg(0x18); this->latch_regs(); _ad9522_regs.vco_calibration_now = 1; this->send_reg(0x18); this->latch_regs(); - //wait for calibration done: + // wait for calibration done: static const uint8_t addr = 0x01F; - for (size_t ms10 = 0; ms10 < 100; ms10++){ + for (size_t ms10 = 0; ms10 < 100; ms10++) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); uint32_t reg = read_reg(addr); _ad9522_regs.set_reg(addr, reg); - if (_ad9522_regs.vco_calibration_finished) goto wait_for_ld; + if (_ad9522_regs.vco_calibration_finished) + goto wait_for_ld; } UHD_LOGGER_ERROR("B100") << "USRP-B100 clock control: VCO calibration timeout"; - wait_for_ld: - //wait for digital lock detect: - for (size_t ms10 = 0; ms10 < 100; ms10++){ + wait_for_ld: + // wait for digital lock detect: + for (size_t ms10 = 0; ms10 < 100; ms10++) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); uint32_t reg = read_reg(addr); _ad9522_regs.set_reg(addr, reg); - if (_ad9522_regs.digital_lock_detect) return; + if (_ad9522_regs.digital_lock_detect) + return; } UHD_LOGGER_ERROR("B100") << "USRP-B100 clock control: lock detection timeout"; } - void soft_sync(void){ + void soft_sync(void) + { _ad9522_regs.soft_sync = 1; this->send_reg(0x230); this->latch_regs(); @@ -512,21 +575,20 @@ private: this->latch_regs(); } - void send_all_regs(void){ - //setup a list of register ranges to write + void send_all_regs(void) + { + // setup a list of register ranges to write typedef std::pair<uint16_t, uint16_t> range_t; - static const std::vector<range_t> ranges{ - range_t(0x000, 0x000), + static const std::vector<range_t> ranges{range_t(0x000, 0x000), range_t(0x010, 0x01F), range_t(0x0F0, 0x0FD), range_t(0x190, 0x19B), range_t(0x1E0, 0x1E1), - range_t(0x230, 0x230) - }; + range_t(0x230, 0x230)}; - //write initial register values and latch/update - for(const range_t &range: ranges){ - for(uint16_t addr = range.first; addr <= range.second; addr++){ + // write initial register values and latch/update + for (const range_t& range : ranges) { + for (uint16_t addr = range.first; addr <= range.second; addr++) { this->send_reg(addr); } } @@ -537,6 +599,8 @@ private: /*********************************************************************** * Clock Control Make **********************************************************************/ -b100_clock_ctrl::sptr b100_clock_ctrl::make(i2c_iface::sptr iface, double master_clock_rate){ +b100_clock_ctrl::sptr b100_clock_ctrl::make( + i2c_iface::sptr iface, double master_clock_rate) +{ return sptr(new b100_clock_ctrl_impl(iface, master_clock_rate)); } diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index b40ea5d82..4f4eba052 100644 --- a/host/lib/usrp/b200/b200_io_impl.cpp +++ b/host/lib/usrp/b200/b200_io_impl.cpp @@ -5,13 +5,13 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include "b200_regs.hpp" -#include "b200_impl.hpp" -#include <uhdlib/usrp/common/validate_subdev_spec.hpp> -#include <uhdlib/usrp/common/async_packet_handler.hpp> #include "../../transport/super_recv_packet_handler.hpp" #include "../../transport/super_send_packet_handler.hpp" +#include "b200_impl.hpp" +#include "b200_regs.hpp" #include <uhd/utils/math.hpp> +#include <uhdlib/usrp/common/async_packet_handler.hpp> +#include <uhdlib/usrp/common/validate_subdev_spec.hpp> #include <boost/bind.hpp> #include <boost/make_shared.hpp> #include <boost/math/common_factor.hpp> @@ -32,53 +32,56 @@ void b200_impl::check_tick_rate_with_current_streamers(double rate) } // direction can either be "TX", "RX", or empty (default) -size_t b200_impl::max_chan_count(const std::string &direction /* = "" */) +size_t b200_impl::max_chan_count(const std::string& direction /* = "" */) { size_t max_count = 0; - for(radio_perifs_t &perif: _radio_perifs) - { - if ((direction == "RX" or direction.empty()) and not perif.rx_streamer.expired()) { + for (radio_perifs_t& perif : _radio_perifs) { + if ((direction == "RX" or direction.empty()) + and not perif.rx_streamer.expired()) { boost::shared_ptr<sph::recv_packet_streamer> rx_streamer = - boost::dynamic_pointer_cast<sph::recv_packet_streamer>(perif.rx_streamer.lock()); + boost::dynamic_pointer_cast<sph::recv_packet_streamer>( + perif.rx_streamer.lock()); max_count = std::max(max_count, rx_streamer->get_num_channels()); } - if ((direction == "TX" or direction.empty()) and not perif.tx_streamer.expired()) { + if ((direction == "TX" or direction.empty()) + and not perif.tx_streamer.expired()) { boost::shared_ptr<sph::send_packet_streamer> tx_streamer = - boost::dynamic_pointer_cast<sph::send_packet_streamer>(perif.tx_streamer.lock()); + boost::dynamic_pointer_cast<sph::send_packet_streamer>( + perif.tx_streamer.lock()); max_count = std::max(max_count, tx_streamer->get_num_channels()); } } return max_count; } -void b200_impl::check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const std::string &direction /*= ""*/) +void b200_impl::check_streamer_args(const uhd::stream_args_t& args, + double tick_rate, + const std::string& direction /*= ""*/) { std::set<size_t> chans_set; - for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) - { + for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) { const size_t chan = args.channels[stream_i]; chans_set.insert(chan); } - enforce_tick_rate_limits(chans_set.size(), tick_rate, direction); // Defined in b200_impl.cpp + enforce_tick_rate_limits( + chans_set.size(), tick_rate, direction); // Defined in b200_impl.cpp } void b200_impl::set_auto_tick_rate( - const double rate, - const fs_path &tree_dsp_path, - size_t num_chans -) { + const double rate, const fs_path& tree_dsp_path, size_t num_chans) +{ if (num_chans == 0) { // Divine them num_chans = std::max(size_t(1), max_chan_count()); } - const double max_tick_rate = ad9361_device_t::AD9361_MAX_CLOCK_RATE/num_chans; + const double max_tick_rate = ad9361_device_t::AD9361_MAX_CLOCK_RATE / num_chans; using namespace uhd::math; - if (rate != 0.0 and - (fp_compare::fp_compare_delta<double>(rate, FREQ_COMPARISON_DELTA_HZ) > max_tick_rate)) { - throw uhd::value_error(str( - boost::format("Requested sampling rate (%.2f Msps) exceeds maximum tick rate of %.2f MHz.") - % (rate / 1e6) % (max_tick_rate / 1e6) - )); + if (rate != 0.0 + and (fp_compare::fp_compare_delta<double>(rate, FREQ_COMPARISON_DELTA_HZ) + > max_tick_rate)) { + throw uhd::value_error(str(boost::format("Requested sampling rate (%.2f Msps) " + "exceeds maximum tick rate of %.2f MHz.") + % (rate / 1e6) % (max_tick_rate / 1e6))); } // See also the doxygen documentation for these steps in b200_impl.hpp @@ -87,7 +90,8 @@ void b200_impl::set_auto_tick_rate( for (int i = 0; i < 2; i++) { // Loop through rx and tx std::string dir = (i == 0) ? "tx" : "rx"; // We assume all 'set' DSPs are being used. - for(const std::string &dsp_no: _tree->list(str(boost::format("/mboards/0/%s_dsps") % dir))) { + for (const std::string& dsp_no : + _tree->list(str(boost::format("/mboards/0/%s_dsps") % dir))) { fs_path dsp_path = str(boost::format("/mboards/0/%s_dsps/%s") % dir % dsp_no); if (dsp_path == tree_dsp_path) { continue; @@ -97,18 +101,18 @@ void b200_impl::set_auto_tick_rate( } double this_dsp_rate = _tree->access<double>(dsp_path / "rate/value").get(); // Check if the user selected something completely unreasonable: - if (fp_compare::fp_compare_delta<double>(this_dsp_rate, FREQ_COMPARISON_DELTA_HZ) > max_tick_rate) { - throw uhd::value_error(str( - boost::format("Requested sampling rate (%.2f Msps) exceeds maximum tick rate of %.2f MHz.") - % (this_dsp_rate / 1e6) % (max_tick_rate / 1e6) - )); + if (fp_compare::fp_compare_delta<double>( + this_dsp_rate, FREQ_COMPARISON_DELTA_HZ) + > max_tick_rate) { + throw uhd::value_error( + str(boost::format("Requested sampling rate (%.2f Msps) exceeds " + "maximum tick rate of %.2f MHz.") + % (this_dsp_rate / 1e6) % (max_tick_rate / 1e6))); } // Clean up floating point rounding errors if they crept in this_dsp_rate = std::min(max_tick_rate, this_dsp_rate); - lcm_rate = boost::math::lcm<uint32_t>( - lcm_rate, - static_cast<uint32_t>(floor(this_dsp_rate + 0.5)) - ); + lcm_rate = boost::math::lcm<uint32_t>( + lcm_rate, static_cast<uint32_t>(floor(this_dsp_rate + 0.5))); } } if (lcm_rate == 1) { @@ -121,13 +125,15 @@ void b200_impl::set_auto_tick_rate( // Step 2: Get a good tick rate value const double new_rate = _codec_mgr->get_auto_tick_rate(base_rate, num_chans); // Step 3: Set the new tick rate value (if any change) - if (!uhd::math::frequencies_are_equal(_tree->access<double>("/mboards/0/tick_rate").get(), new_rate)) { + if (!uhd::math::frequencies_are_equal( + _tree->access<double>("/mboards/0/tick_rate").get(), new_rate)) { _tree->access<double>("/mboards/0/tick_rate").set(new_rate); } - } catch (const uhd::value_error &) { - UHD_LOGGER_WARNING("B200") - << "Cannot automatically determine an appropriate tick rate for these sampling rates." - << "Consider using different sampling rates, or manually specify a suitable master clock rate." ; + } catch (const uhd::value_error&) { + UHD_LOGGER_WARNING("B200") << "Cannot automatically determine an appropriate " + "tick rate for these sampling rates." + << "Consider using different sampling rates, or " + "manually specify a suitable master clock rate."; return; // Let the others handle this } } @@ -136,22 +142,25 @@ void b200_impl::update_tick_rate(const double new_tick_rate) { check_tick_rate_with_current_streamers(new_tick_rate); - for(radio_perifs_t &perif: _radio_perifs) - { + for (radio_perifs_t& perif : _radio_perifs) { boost::shared_ptr<sph::recv_packet_streamer> my_streamer = - boost::dynamic_pointer_cast<sph::recv_packet_streamer>(perif.rx_streamer.lock()); - if (my_streamer) my_streamer->set_tick_rate(new_tick_rate); + boost::dynamic_pointer_cast<sph::recv_packet_streamer>( + perif.rx_streamer.lock()); + if (my_streamer) + my_streamer->set_tick_rate(new_tick_rate); perif.framer->set_tick_rate(new_tick_rate); } - for(radio_perifs_t &perif: _radio_perifs) - { + for (radio_perifs_t& perif : _radio_perifs) { boost::shared_ptr<sph::send_packet_streamer> my_streamer = - boost::dynamic_pointer_cast<sph::send_packet_streamer>(perif.tx_streamer.lock()); - if (my_streamer) my_streamer->set_tick_rate(new_tick_rate); + boost::dynamic_pointer_cast<sph::send_packet_streamer>( + perif.tx_streamer.lock()); + if (my_streamer) + my_streamer->set_tick_rate(new_tick_rate); } } -void b200_impl::update_rx_dsp_tick_rate(const double tick_rate, rx_dsp_core_3000::sptr ddc, uhd::fs_path rx_dsp_path) +void b200_impl::update_rx_dsp_tick_rate( + const double tick_rate, rx_dsp_core_3000::sptr ddc, uhd::fs_path rx_dsp_path) { ddc->set_tick_rate(tick_rate); if (_tree->access<bool>(rx_dsp_path / "rate" / "set").get()) { @@ -159,7 +168,8 @@ void b200_impl::update_rx_dsp_tick_rate(const double tick_rate, rx_dsp_core_3000 } } -void b200_impl::update_tx_dsp_tick_rate(const double tick_rate, tx_dsp_core_3000::sptr duc, uhd::fs_path tx_dsp_path) +void b200_impl::update_tx_dsp_tick_rate( + const double tick_rate, tx_dsp_core_3000::sptr duc, uhd::fs_path tx_dsp_path) { duc->set_tick_rate(tick_rate); if (_tree->access<bool>(tx_dsp_path / "rate" / "set").get()) { @@ -167,21 +177,27 @@ void b200_impl::update_tx_dsp_tick_rate(const double tick_rate, tx_dsp_core_3000 } } -#define CHECK_RATE_AND_THROW(rate) \ - if (uhd::math::fp_compare::fp_compare_delta<double>(rate, uhd::math::FREQ_COMPARISON_DELTA_HZ) > \ - uhd::math::fp_compare::fp_compare_delta<double>(ad9361_device_t::AD9361_MAX_CLOCK_RATE, uhd::math::FREQ_COMPARISON_DELTA_HZ)) { \ - throw uhd::value_error(str( \ - boost::format("Requested sampling rate (%.2f Msps) exceeds maximum tick rate.") \ - % (rate / 1e6) \ - )); \ - } +#define CHECK_RATE_AND_THROW(rate) \ + if (uhd::math::fp_compare::fp_compare_delta<double>( \ + rate, uhd::math::FREQ_COMPARISON_DELTA_HZ) \ + > uhd::math::fp_compare::fp_compare_delta<double>( \ + ad9361_device_t::AD9361_MAX_CLOCK_RATE, \ + uhd::math::FREQ_COMPARISON_DELTA_HZ)) { \ + throw uhd::value_error( \ + str(boost::format( \ + "Requested sampling rate (%.2f Msps) exceeds maximum tick rate.") \ + % (rate / 1e6))); \ + } -double b200_impl::coerce_rx_samp_rate(rx_dsp_core_3000::sptr ddc, size_t dspno, const double rx_rate) +double b200_impl::coerce_rx_samp_rate( + rx_dsp_core_3000::sptr ddc, size_t dspno, const double rx_rate) { - // Have to set tick rate first, or the ddc will change the requested rate based on default tick rate + // Have to set tick rate first, or the ddc will change the requested rate based on + // default tick rate if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) { CHECK_RATE_AND_THROW(rx_rate); - const std::string dsp_path = (boost::format("/mboards/0/rx_dsps/%s") % dspno).str(); + const std::string dsp_path = + (boost::format("/mboards/0/rx_dsps/%s") % dspno).str(); set_auto_tick_rate(rx_rate, dsp_path); } return ddc->set_host_rate(rx_rate); @@ -190,20 +206,25 @@ double b200_impl::coerce_rx_samp_rate(rx_dsp_core_3000::sptr ddc, size_t dspno, void b200_impl::update_rx_samp_rate(const size_t dspno, const double rate) { boost::shared_ptr<sph::recv_packet_streamer> my_streamer = - boost::dynamic_pointer_cast<sph::recv_packet_streamer>(_radio_perifs[dspno].rx_streamer.lock()); - if (not my_streamer) return; + boost::dynamic_pointer_cast<sph::recv_packet_streamer>( + _radio_perifs[dspno].rx_streamer.lock()); + if (not my_streamer) + return; my_streamer->set_samp_rate(rate); const double adj = _radio_perifs[dspno].ddc->get_scaling_adjustment(); my_streamer->set_scale_factor(adj); _codec_mgr->check_bandwidth(rate, "Rx"); } -double b200_impl::coerce_tx_samp_rate(tx_dsp_core_3000::sptr duc, size_t dspno, const double tx_rate) +double b200_impl::coerce_tx_samp_rate( + tx_dsp_core_3000::sptr duc, size_t dspno, const double tx_rate) { - // Have to set tick rate first, or the duc will change the requested rate based on default tick rate + // Have to set tick rate first, or the duc will change the requested rate based on + // default tick rate if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) { CHECK_RATE_AND_THROW(tx_rate); - const std::string dsp_path = (boost::format("/mboards/0/tx_dsps/%s") % dspno).str(); + const std::string dsp_path = + (boost::format("/mboards/0/tx_dsps/%s") % dspno).str(); set_auto_tick_rate(tx_rate, dsp_path); } return duc->set_host_rate(tx_rate); @@ -212,8 +233,10 @@ double b200_impl::coerce_tx_samp_rate(tx_dsp_core_3000::sptr duc, size_t dspno, void b200_impl::update_tx_samp_rate(const size_t dspno, const double rate) { boost::shared_ptr<sph::send_packet_streamer> my_streamer = - boost::dynamic_pointer_cast<sph::send_packet_streamer>(_radio_perifs[dspno].tx_streamer.lock()); - if (not my_streamer) return; + boost::dynamic_pointer_cast<sph::send_packet_streamer>( + _radio_perifs[dspno].tx_streamer.lock()); + if (not my_streamer) + return; my_streamer->set_samp_rate(rate); const double adj = _radio_perifs[dspno].duc->get_scaling_adjustment(); my_streamer->set_scale_factor(adj); @@ -223,7 +246,8 @@ void b200_impl::update_tx_samp_rate(const size_t dspno, const double rate) /*********************************************************************** * frontend selection **********************************************************************/ -uhd::usrp::subdev_spec_t b200_impl::coerce_subdev_spec(const uhd::usrp::subdev_spec_t &spec_) +uhd::usrp::subdev_spec_t b200_impl::coerce_subdev_spec( + const uhd::usrp::subdev_spec_t& spec_) { uhd::usrp::subdev_spec_t spec = spec_; // Because of the confusing nature of the subdevs on B200 @@ -232,16 +256,17 @@ uhd::usrp::subdev_spec_t b200_impl::coerce_subdev_spec(const uhd::usrp::subdev_s // // Any other spec is probably illegal and will be caught by // validate_subdev_spec(). - if (spec.size() and (_product == B200 or _product == B200MINI or _product == B205MINI) and spec[0].sd_name == "B") - { + if (spec.size() and (_product == B200 or _product == B200MINI or _product == B205MINI) + and spec[0].sd_name == "B") { spec[0].sd_name = "A"; } return spec; } -void b200_impl::update_subdev_spec(const std::string &tx_rx, const uhd::usrp::subdev_spec_t &spec) +void b200_impl::update_subdev_spec( + const std::string& tx_rx, const uhd::usrp::subdev_spec_t& spec) { - //sanity checking + // sanity checking if (spec.size()) { validate_subdev_spec(_tree, spec, tx_rx); } @@ -250,23 +275,22 @@ void b200_impl::update_subdev_spec(const std::string &tx_rx, const uhd::usrp::su for (size_t i = 0; i < spec.size(); i++) { chan_to_dsp_map[i] = (spec[i].sd_name == "A") ? 0 : 1; } - _tree->access<std::vector<size_t> >("/mboards/0" / (tx_rx + "_chan_dsp_mapping")).set(chan_to_dsp_map); + _tree->access<std::vector<size_t>>("/mboards/0" / (tx_rx + "_chan_dsp_mapping")) + .set(chan_to_dsp_map); this->update_enables(); } static void b200_if_hdr_unpack_le( - const uint32_t *packet_buff, - vrt::if_packet_info_t &if_packet_info -){ + const uint32_t* packet_buff, vrt::if_packet_info_t& if_packet_info) +{ if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; return vrt::if_hdr_unpack_le(packet_buff, if_packet_info); } static void b200_if_hdr_pack_le( - uint32_t *packet_buff, - vrt::if_packet_info_t &if_packet_info -){ + uint32_t* packet_buff, vrt::if_packet_info_t& if_packet_info) +{ if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; return vrt::if_hdr_pack_le(packet_buff, if_packet_info); } @@ -274,93 +298,91 @@ static void b200_if_hdr_pack_le( /*********************************************************************** * Async Data **********************************************************************/ -bool b200_impl::recv_async_msg( - async_metadata_t &async_metadata, double timeout -){ +bool b200_impl::recv_async_msg(async_metadata_t& async_metadata, double timeout) +{ return _async_task_data->async_md->pop_with_timed_wait(async_metadata, timeout); } /* * This method is constantly called in a msg_task loop. * Incoming messages are dispatched in to the hosts radio_ctrl_cores. - * The radio_ctrl_core queues are accessed via a weak_ptr to them, stored in AsyncTaskData. - * During shutdown the radio_ctrl_core dtor's are called. - * An empty peek32(0) is sent out to flush pending async messages. - * The response to those messages can't be delivered to the ctrl_core queues anymore - * because the shared pointer corresponding to the weak_ptrs is no longer valid. - * Those stranded messages are put into a dump_queue implemented in msg_task. - * A radio_ctrl_core can search for missing messages there. + * The radio_ctrl_core queues are accessed via a weak_ptr to them, stored in + * AsyncTaskData. During shutdown the radio_ctrl_core dtor's are called. An empty + * peek32(0) is sent out to flush pending async messages. The response to those messages + * can't be delivered to the ctrl_core queues anymore because the shared pointer + * corresponding to the weak_ptrs is no longer valid. Those stranded messages are put into + * a dump_queue implemented in msg_task. A radio_ctrl_core can search for missing messages + * there. */ boost::optional<uhd::msg_task::msg_type_t> b200_impl::handle_async_task( - uhd::transport::zero_copy_if::sptr xport, - boost::shared_ptr<AsyncTaskData> data -) + uhd::transport::zero_copy_if::sptr xport, boost::shared_ptr<AsyncTaskData> data) { managed_recv_buffer::sptr buff = xport->get_recv_buff(); if (not buff or buff->size() < 8) return boost::none; - const uint32_t sid = uhd::wtohx(buff->cast<const uint32_t *>()[1]); + const uint32_t sid = uhd::wtohx(buff->cast<const uint32_t*>()[1]); switch (sid) { - - //if the packet is a control response - case B200_RESP0_MSG_SID: - case B200_RESP1_MSG_SID: - case B200_LOCAL_RESP_SID: - { - radio_ctrl_core_3000::sptr ctrl; - if (sid == B200_RESP0_MSG_SID) ctrl = data->radio_ctrl[0].lock(); - if (sid == B200_RESP1_MSG_SID) ctrl = data->radio_ctrl[1].lock(); - if (sid == B200_LOCAL_RESP_SID) ctrl = data->local_ctrl.lock(); - if (ctrl){ - ctrl->push_response(buff->cast<const uint32_t *>()); - } - else{ - return std::make_pair(sid, uhd::msg_task::buff_to_vector(buff->cast<uint8_t *>(), buff->size() ) ); + // if the packet is a control response + case B200_RESP0_MSG_SID: + case B200_RESP1_MSG_SID: + case B200_LOCAL_RESP_SID: { + radio_ctrl_core_3000::sptr ctrl; + if (sid == B200_RESP0_MSG_SID) + ctrl = data->radio_ctrl[0].lock(); + if (sid == B200_RESP1_MSG_SID) + ctrl = data->radio_ctrl[1].lock(); + if (sid == B200_LOCAL_RESP_SID) + ctrl = data->local_ctrl.lock(); + if (ctrl) { + ctrl->push_response(buff->cast<const uint32_t*>()); + } else { + return std::make_pair(sid, + uhd::msg_task::buff_to_vector(buff->cast<uint8_t*>(), buff->size())); + } + break; } - break; - } - //if the packet is a uart message - case B200_RX_GPS_UART_SID: - { - data->gpsdo_uart->handle_uart_packet(buff); - break; - } - - //or maybe the packet is a TX async message - case B200_TX_MSG0_SID: - case B200_TX_MSG1_SID: - { - const size_t i = (sid == B200_TX_MSG0_SID)? 0 : 1; + // if the packet is a uart message + case B200_RX_GPS_UART_SID: { + data->gpsdo_uart->handle_uart_packet(buff); + break; + } - //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 *>(); + // or maybe the packet is a TX async message + case B200_TX_MSG0_SID: + case B200_TX_MSG1_SID: { + const size_t i = (sid == B200_TX_MSG0_SID) ? 0 : 1; + + // 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*>(); + + // unpacking can fail + try { + b200_if_hdr_unpack_le(packet_buff, if_packet_info); + } catch (const std::exception& ex) { + UHD_LOGGER_ERROR("B200") << "Error parsing ctrl packet: " << ex.what(); + break; + } - //unpacking can fail - try - { - b200_if_hdr_unpack_le(packet_buff, if_packet_info); - } - catch(const std::exception &ex) - { - UHD_LOGGER_ERROR("B200") << "Error parsing ctrl packet: " << ex.what(); + // fill in the async metadata + async_metadata_t metadata; + load_metadata_from_buff(uhd::wtohx<uint32_t>, + metadata, + if_packet_info, + packet_buff, + _tick_rate, + i); + data->async_md->push_with_pop_on_full(metadata); + standard_async_msg_prints(metadata); break; } - //fill in the async metadata - async_metadata_t metadata; - load_metadata_from_buff(uhd::wtohx<uint32_t>, metadata, if_packet_info, packet_buff, _tick_rate, i); - data->async_md->push_with_pop_on_full(metadata); - standard_async_msg_prints(metadata); - break; - } - - //doh! - default: - UHD_LOGGER_ERROR("B200") << "Got a ctrl packet with unknown SID " << sid; + // doh! + default: + UHD_LOGGER_ERROR("B200") << "Got a ctrl packet with unknown SID " << sid; } return boost::none; } @@ -368,15 +390,16 @@ boost::optional<uhd::msg_task::msg_type_t> b200_impl::handle_async_task( /*********************************************************************** * Receive streamer **********************************************************************/ -rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t &args_) +rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t& args_) { boost::mutex::scoped_lock lock(_transport_setup_mutex); stream_args_t args = args_; - //setup defaults for unspecified values - if (args.otw_format.empty()) args.otw_format = "sc16"; - args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; + // setup defaults for unspecified values + if (args.otw_format.empty()) + args.otw_format = "sc16"; + args.channels = args.channels.empty() ? std::vector<size_t>(1, 0) : args.channels; if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) { set_auto_tick_rate(0, "", args.channels.size()); @@ -384,42 +407,49 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t &args_) check_streamer_args(args, this->get_tick_rate(), "RX"); boost::shared_ptr<sph::recv_packet_streamer> my_streamer; - for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) - { - const size_t radio_index = _tree->access<std::vector<size_t> >("/mboards/0/rx_chan_dsp_mapping") - .get().at(args.channels[stream_i]); - radio_perifs_t &perif = _radio_perifs[radio_index]; - if (args.otw_format == "sc16") perif.ctrl->poke32(TOREG(SR_RX_FMT), 0); - if (args.otw_format == "sc12") perif.ctrl->poke32(TOREG(SR_RX_FMT), 1); - if (args.otw_format == "fc32") perif.ctrl->poke32(TOREG(SR_RX_FMT), 2); - if (args.otw_format == "sc8") perif.ctrl->poke32(TOREG(SR_RX_FMT), 3); + for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) { + const size_t radio_index = + _tree->access<std::vector<size_t>>("/mboards/0/rx_chan_dsp_mapping") + .get() + .at(args.channels[stream_i]); + radio_perifs_t& perif = _radio_perifs[radio_index]; + if (args.otw_format == "sc16") + perif.ctrl->poke32(TOREG(SR_RX_FMT), 0); + if (args.otw_format == "sc12") + perif.ctrl->poke32(TOREG(SR_RX_FMT), 1); + if (args.otw_format == "fc32") + perif.ctrl->poke32(TOREG(SR_RX_FMT), 2); + if (args.otw_format == "sc8") + perif.ctrl->poke32(TOREG(SR_RX_FMT), 3); const uint32_t sid = radio_index ? B200_RX_DATA1_SID : B200_RX_DATA0_SID; - //calculate packet size - static const size_t hdr_size = 0 - + vrt::max_if_hdr_words32*sizeof(uint32_t) + // calculate packet size + static const size_t hdr_size = + 0 + + vrt::max_if_hdr_words32 * sizeof(uint32_t) //+ sizeof(vrt::if_packet_info_t().tlr) //no longer using trailer - - sizeof(vrt::if_packet_info_t().cid) //no class id ever used - - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used - ; + - sizeof(vrt::if_packet_info_t().cid) // no class id ever used + - sizeof(vrt::if_packet_info_t().tsi) // no int time ever used + ; const size_t bpp = _data_transport->get_recv_frame_size() - hdr_size; const size_t bpi = convert::get_bytes_per_item(args.otw_format); - size_t spp = unsigned(args.args.cast<double>("spp", bpp/bpi)); - spp = std::min<size_t>(4092, spp); //FPGA FIFO maximum for framing at full rate + size_t spp = unsigned(args.args.cast<double>("spp", bpp / bpi)); + spp = std::min<size_t>(4092, spp); // FPGA FIFO maximum for framing at full rate - //make the new streamer given the samples per packet - if (not my_streamer) my_streamer = boost::make_shared<sph::recv_packet_streamer>(spp); + // make the new streamer given the samples per packet + if (not my_streamer) + my_streamer = boost::make_shared<sph::recv_packet_streamer>(spp); my_streamer->resize(args.channels.size()); - //init some streamer stuff + // init some streamer stuff my_streamer->set_vrt_unpacker(&b200_if_hdr_unpack_le); - //set the converter + // set the converter uhd::convert::id_type id; - id.input_format = args.otw_format + "_item32_le"; - id.num_inputs = 1; + id.input_format = args.otw_format + "_item32_le"; + id.num_inputs = 1; id.output_format = args.cpu_format; - id.num_outputs = 1; + id.num_outputs = 1; my_streamer->set_converter(id); perif.framer->clear(); @@ -428,20 +458,21 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t &args_) perif.framer->setup(args); perif.ddc->setup(args); _demux->realloc_sid(sid); - my_streamer->set_xport_chan_get_buff(stream_i, boost::bind( - &recv_packet_demuxer_3000::get_recv_buff, _demux, sid, _1 - ), true /*flush*/); - my_streamer->set_overflow_handler(stream_i, boost::bind( - &b200_impl::handle_overflow, this, radio_index - )); - my_streamer->set_issue_stream_cmd(stream_i, boost::bind( - &rx_vita_core_3000::issue_stream_command, perif.framer, _1 - )); - perif.rx_streamer = my_streamer; //store weak pointer - - //sets all tick and samp rates on this streamer + my_streamer->set_xport_chan_get_buff(stream_i, + boost::bind(&recv_packet_demuxer_3000::get_recv_buff, _demux, sid, _1), + true /*flush*/); + my_streamer->set_overflow_handler( + stream_i, boost::bind(&b200_impl::handle_overflow, this, radio_index)); + my_streamer->set_issue_stream_cmd(stream_i, + boost::bind(&rx_vita_core_3000::issue_stream_command, perif.framer, _1)); + perif.rx_streamer = my_streamer; // store weak pointer + + // sets all tick and samp rates on this streamer this->update_tick_rate(this->get_tick_rate()); - _tree->access<double>(str(boost::format("/mboards/0/rx_dsps/%u/rate/value") % radio_index)).update(); + _tree + ->access<double>( + str(boost::format("/mboards/0/rx_dsps/%u/rate/value") % radio_index)) + .update(); } this->update_enables(); @@ -451,42 +482,46 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t &args_) void b200_impl::handle_overflow(const size_t radio_index) { boost::shared_ptr<sph::recv_packet_streamer> my_streamer = - boost::dynamic_pointer_cast<sph::recv_packet_streamer>(_radio_perifs[radio_index].rx_streamer.lock()); - if (my_streamer->get_num_channels() == 2) //MIMO time + boost::dynamic_pointer_cast<sph::recv_packet_streamer>( + _radio_perifs[radio_index].rx_streamer.lock()); + if (my_streamer->get_num_channels() == 2) // MIMO time { - //find out if we were in continuous mode before stopping - const bool in_continuous_streaming_mode = _radio_perifs[radio_index].framer->in_continuous_streaming_mode(); - //stop streaming + // find out if we were in continuous mode before stopping + const bool in_continuous_streaming_mode = + _radio_perifs[radio_index].framer->in_continuous_streaming_mode(); + // stop streaming my_streamer->issue_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); - //flush demux + // flush demux _demux->realloc_sid(B200_RX_DATA0_SID); _demux->realloc_sid(B200_RX_DATA1_SID); - //flush actual transport - while (_data_transport->get_recv_buff(0.001)){} - //restart streaming - if (in_continuous_streaming_mode) - { + // flush actual transport + while (_data_transport->get_recv_buff(0.001)) { + } + // restart streaming + if (in_continuous_streaming_mode) { stream_cmd_t stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); stream_cmd.stream_now = false; - stream_cmd.time_spec = _radio_perifs[radio_index].time64->get_time_now() + time_spec_t(0.01); + stream_cmd.time_spec = + _radio_perifs[radio_index].time64->get_time_now() + time_spec_t(0.01); my_streamer->issue_stream_cmd(stream_cmd); } - } - else _radio_perifs[radio_index].framer->handle_overflow(); + } else + _radio_perifs[radio_index].framer->handle_overflow(); } /*********************************************************************** * Transmit streamer **********************************************************************/ -tx_streamer::sptr b200_impl::get_tx_stream(const uhd::stream_args_t &args_) +tx_streamer::sptr b200_impl::get_tx_stream(const uhd::stream_args_t& args_) { boost::mutex::scoped_lock lock(_transport_setup_mutex); stream_args_t args = args_; - //setup defaults for unspecified values - if (args.otw_format.empty()) args.otw_format = "sc16"; - args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; + // setup defaults for unspecified values + if (args.otw_format.empty()) + args.otw_format = "sc16"; + args.channels = args.channels.empty() ? std::vector<size_t>(1, 0) : args.channels; if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) { set_auto_tick_rate(0, "", args.channels.size()); @@ -494,58 +529,68 @@ tx_streamer::sptr b200_impl::get_tx_stream(const uhd::stream_args_t &args_) check_streamer_args(args, this->get_tick_rate(), "TX"); boost::shared_ptr<sph::send_packet_streamer> my_streamer; - for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) - { - const size_t radio_index = _tree->access<std::vector<size_t> >("/mboards/0/tx_chan_dsp_mapping") - .get().at(args.channels[stream_i]); - radio_perifs_t &perif = _radio_perifs[radio_index]; - if (args.otw_format == "sc16") perif.ctrl->poke32(TOREG(SR_TX_FMT), 0); - if (args.otw_format == "sc12") perif.ctrl->poke32(TOREG(SR_TX_FMT), 1); - if (args.otw_format == "fc32") perif.ctrl->poke32(TOREG(SR_TX_FMT), 2); - if (args.otw_format == "sc8") perif.ctrl->poke32(TOREG(SR_TX_FMT), 3); - - //calculate packet size - static const size_t hdr_size = 0 - + vrt::max_if_hdr_words32*sizeof(uint32_t) + for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) { + const size_t radio_index = + _tree->access<std::vector<size_t>>("/mboards/0/tx_chan_dsp_mapping") + .get() + .at(args.channels[stream_i]); + radio_perifs_t& perif = _radio_perifs[radio_index]; + if (args.otw_format == "sc16") + perif.ctrl->poke32(TOREG(SR_TX_FMT), 0); + if (args.otw_format == "sc12") + perif.ctrl->poke32(TOREG(SR_TX_FMT), 1); + if (args.otw_format == "fc32") + perif.ctrl->poke32(TOREG(SR_TX_FMT), 2); + if (args.otw_format == "sc8") + perif.ctrl->poke32(TOREG(SR_TX_FMT), 3); + + // calculate packet size + static const size_t hdr_size = + 0 + + vrt::max_if_hdr_words32 * sizeof(uint32_t) //+ sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - - sizeof(vrt::if_packet_info_t().cid) //no class id ever used - - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used - ; + - sizeof(vrt::if_packet_info_t().cid) // no class id ever used + - sizeof(vrt::if_packet_info_t().tsi) // no int time ever used + ; static const size_t bpp = _data_transport->get_send_frame_size() - hdr_size; - const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); + const size_t spp = bpp / convert::get_bytes_per_item(args.otw_format); - //make the new streamer given the samples per packet - if (not my_streamer) my_streamer = boost::make_shared<sph::send_packet_streamer>(spp); + // make the new streamer given the samples per packet + if (not my_streamer) + my_streamer = boost::make_shared<sph::send_packet_streamer>(spp); my_streamer->resize(args.channels.size()); - //init some streamer stuff + // init some streamer stuff my_streamer->set_vrt_packer(&b200_if_hdr_pack_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_le"; - id.num_outputs = 1; + id.num_outputs = 1; my_streamer->set_converter(id); perif.deframer->clear(); perif.deframer->setup(args); perif.duc->setup(args); - my_streamer->set_xport_chan_get_buff(stream_i, boost::bind( - &zero_copy_if::get_send_buff, _data_transport, _1 - )); + my_streamer->set_xport_chan_get_buff( + stream_i, boost::bind(&zero_copy_if::get_send_buff, _data_transport, _1)); my_streamer->set_async_receiver(boost::bind( - &async_md_type::pop_with_timed_wait, _async_task_data->async_md, _1, _2 - )); - my_streamer->set_xport_chan_sid(stream_i, true, radio_index ? B200_TX_DATA1_SID : B200_TX_DATA0_SID); - my_streamer->set_enable_trailer(false); //TODO not implemented trailer support yet - perif.tx_streamer = my_streamer; //store weak pointer - - //sets all tick and samp rates on this streamer + &async_md_type::pop_with_timed_wait, _async_task_data->async_md, _1, _2)); + my_streamer->set_xport_chan_sid( + stream_i, true, radio_index ? B200_TX_DATA1_SID : B200_TX_DATA0_SID); + my_streamer->set_enable_trailer(false); // TODO not implemented trailer support + // yet + perif.tx_streamer = my_streamer; // store weak pointer + + // sets all tick and samp rates on this streamer this->update_tick_rate(this->get_tick_rate()); - _tree->access<double>(str(boost::format("/mboards/0/tx_dsps/%u/rate/value") % radio_index)).update(); + _tree + ->access<double>( + str(boost::format("/mboards/0/tx_dsps/%u/rate/value") % radio_index)) + .update(); } this->update_enables(); diff --git a/host/lib/usrp/common/ad936x_manager.cpp b/host/lib/usrp/common/ad936x_manager.cpp index 8fd2a919d..87521e834 100644 --- a/host/lib/usrp/common/ad936x_manager.cpp +++ b/host/lib/usrp/common/ad936x_manager.cpp @@ -5,8 +5,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include <uhdlib/usrp/common/ad936x_manager.hpp> #include <uhd/utils/log.hpp> +#include <uhdlib/usrp/common/ad936x_manager.hpp> #include <boost/functional/hash.hpp> #include <boost/make_shared.hpp> #include <chrono> @@ -18,15 +18,15 @@ using namespace uhd::usrp; /**************************************************************************** * Default values ***************************************************************************/ -const double ad936x_manager::DEFAULT_GAIN = 0; -const double ad936x_manager::DEFAULT_BANDWIDTH = ad9361_device_t::AD9361_MAX_BW; -const double ad936x_manager::DEFAULT_TICK_RATE = 16e6; -const double ad936x_manager::DEFAULT_FREQ = 100e6; // Hz -const uint32_t ad936x_manager::DEFAULT_DECIM = 128; -const uint32_t ad936x_manager::DEFAULT_INTERP = 128; -const bool ad936x_manager::DEFAULT_AUTO_DC_OFFSET = true; -const bool ad936x_manager::DEFAULT_AUTO_IQ_BALANCE = true; -const bool ad936x_manager::DEFAULT_AGC_ENABLE = false; +const double ad936x_manager::DEFAULT_GAIN = 0; +const double ad936x_manager::DEFAULT_BANDWIDTH = ad9361_device_t::AD9361_MAX_BW; +const double ad936x_manager::DEFAULT_TICK_RATE = 16e6; +const double ad936x_manager::DEFAULT_FREQ = 100e6; // Hz +const uint32_t ad936x_manager::DEFAULT_DECIM = 128; +const uint32_t ad936x_manager::DEFAULT_INTERP = 128; +const bool ad936x_manager::DEFAULT_AUTO_DC_OFFSET = true; +const bool ad936x_manager::DEFAULT_AUTO_IQ_BALANCE = true; +const bool ad936x_manager::DEFAULT_AGC_ENABLE = false; class ad936x_manager_impl : public ad936x_manager { @@ -34,17 +34,14 @@ public: /************************************************************************ * Structor ***********************************************************************/ - ad936x_manager_impl( - const ad9361_ctrl::sptr &codec_ctrl, - const size_t n_frontends - ) : _codec_ctrl(codec_ctrl), - _n_frontends(n_frontends) + ad936x_manager_impl(const ad9361_ctrl::sptr& codec_ctrl, const size_t n_frontends) + : _codec_ctrl(codec_ctrl), _n_frontends(n_frontends) { if (_n_frontends < 1 or _n_frontends > 2) { - throw uhd::runtime_error(str( - boost::format("AD936x device can only have either 1 or 2 frontends, not %d.") - % _n_frontends - )); + throw uhd::runtime_error( + str(boost::format( + "AD936x device can only have either 1 or 2 frontends, not %d.") + % _n_frontends)); } for (size_t i = 1; i <= _n_frontends; i++) { const std::string rx_fe_str = str(boost::format("RX%d") % i); @@ -61,7 +58,7 @@ public: ***********************************************************************/ void init_codec() { - for (const std::string &rx_fe : _rx_frontends) { + for (const std::string& rx_fe : _rx_frontends) { _codec_ctrl->set_gain(rx_fe, DEFAULT_GAIN); _codec_ctrl->set_bw_filter(rx_fe, DEFAULT_BANDWIDTH); _codec_ctrl->tune(rx_fe, DEFAULT_FREQ); @@ -69,7 +66,7 @@ public: _codec_ctrl->set_iq_balance_auto(rx_fe, DEFAULT_AUTO_IQ_BALANCE); _codec_ctrl->set_agc(rx_fe, DEFAULT_AGC_ENABLE); } - for (const std::string &tx_fe : _tx_frontends) { + for (const std::string& tx_fe : _tx_frontends) { _codec_ctrl->set_gain(tx_fe, DEFAULT_GAIN); _codec_ctrl->set_bw_filter(tx_fe, DEFAULT_BANDWIDTH); _codec_ctrl->tune(tx_fe, DEFAULT_FREQ); @@ -87,10 +84,9 @@ public: // whatever timing is configured at the time the test is called rather than select // worst case conditions to stress the interface. // - 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) + { // Put AD936x in loopback mode _codec_ctrl->data_port_loopback(true); UHD_LOGGER_DEBUG("AD936X") << "Performing CODEC loopback test... "; @@ -115,16 +111,16 @@ public: // Read back values 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 const bool test_fail = word32 != rb_tx or word32 != rb_rx; if (test_fail) { UHD_LOGGER_ERROR("AD936X") - << "CODEC loopback test failed! " - << boost::format("Expected: 0x%08X Received (TX/RX): 0x%08X/0x%08X") - % word32 % rb_tx % rb_rx; + << "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."); } } @@ -138,22 +134,22 @@ public: } - double get_auto_tick_rate( - const double lcm_rate, - size_t num_chans - ) { + double get_auto_tick_rate(const double lcm_rate, size_t num_chans) + { UHD_ASSERT_THROW(num_chans >= 1 and num_chans <= _n_frontends); const uhd::meta_range_t rate_range = _codec_ctrl->get_clock_rate_range(); - const double min_tick_rate = rate_range.start(); - const double max_tick_rate = rate_range.stop() / num_chans; + const double min_tick_rate = rate_range.start(); + const double max_tick_rate = rate_range.stop() / num_chans; // Check if the requested rate is within available limits: - if (uhd::math::fp_compare::fp_compare_delta<double>(lcm_rate, uhd::math::FREQ_COMPARISON_DELTA_HZ) > - uhd::math::fp_compare::fp_compare_delta<double>(max_tick_rate, uhd::math::FREQ_COMPARISON_DELTA_HZ)) { - throw uhd::value_error(str( - boost::format("[ad936x_manager] Cannot get determine a tick rate if sampling rate exceeds maximum tick rate (%f > %f)") - % lcm_rate % max_tick_rate - )); + if (uhd::math::fp_compare::fp_compare_delta<double>( + lcm_rate, uhd::math::FREQ_COMPARISON_DELTA_HZ) + > uhd::math::fp_compare::fp_compare_delta<double>( + max_tick_rate, uhd::math::FREQ_COMPARISON_DELTA_HZ)) { + throw uhd::value_error( + str(boost::format("[ad936x_manager] Cannot get determine a tick rate if " + "sampling rate exceeds maximum tick rate (%f > %f)") + % lcm_rate % max_tick_rate)); } // **** Choose the new rate **** @@ -168,22 +164,23 @@ public: // // where r is the base rate and f_max is the maximum tick rate. The case // where floor() yields 1 must be caught. - // We use shifts here instead of 2^x because exp2() is not available in all compilers, - // also this guarantees no rounding issues. The type cast to int32_t serves as floor(): + // We use shifts here instead of 2^x because exp2() is not available in all + // compilers, also this guarantees no rounding issues. The type cast to int32_t + // serves as floor(): int32_t multiplier = (1 << int32_t(uhd::math::log2(max_tick_rate / lcm_rate))); if (multiplier == 2 and lcm_rate >= min_tick_rate) { // Don't bother (see above) multiplier = 1; } const double new_rate = lcm_rate * multiplier; - UHD_ASSERT_THROW( - uhd::math::fp_compare::fp_compare_delta<double>(new_rate, uhd::math::FREQ_COMPARISON_DELTA_HZ) >= - uhd::math::fp_compare::fp_compare_delta<double>(min_tick_rate, uhd::math::FREQ_COMPARISON_DELTA_HZ) - ); - UHD_ASSERT_THROW( - uhd::math::fp_compare::fp_compare_delta<double>(new_rate, uhd::math::FREQ_COMPARISON_DELTA_HZ) <= - uhd::math::fp_compare::fp_compare_delta<double>(max_tick_rate, uhd::math::FREQ_COMPARISON_DELTA_HZ) - ); + UHD_ASSERT_THROW(uhd::math::fp_compare::fp_compare_delta<double>( + new_rate, uhd::math::FREQ_COMPARISON_DELTA_HZ) + >= uhd::math::fp_compare::fp_compare_delta<double>( + min_tick_rate, uhd::math::FREQ_COMPARISON_DELTA_HZ)); + UHD_ASSERT_THROW(uhd::math::fp_compare::fp_compare_delta<double>( + new_rate, uhd::math::FREQ_COMPARISON_DELTA_HZ) + <= uhd::math::fp_compare::fp_compare_delta<double>( + max_tick_rate, uhd::math::FREQ_COMPARISON_DELTA_HZ)); return new_rate; } @@ -191,59 +188,49 @@ public: bool check_bandwidth(double rate, const std::string dir) { double bw = _bw[dir == "Rx" ? "RX1" : "TX1"]; - if (bw == 0.) //0 indicates bandwidth is default value. + if (bw == 0.) // 0 indicates bandwidth is default value. { double max_bw = ad9361_device_t::AD9361_MAX_BW; double min_bw = ad9361_device_t::AD9361_MIN_BW; - if (rate > max_bw) - { - UHD_LOGGER_WARNING("AD936X") - << "Selected " << dir << " sample rate (" << (rate/1e6) << " MHz) is greater than\n" - << "analog frontend filter bandwidth (" << (max_bw/1e6) << " MHz)." - ; - } - else if (rate < min_bw) - { - UHD_LOGGER_WARNING("AD936X") - << "Selected " << dir << " sample rate (" << (rate/1e6) << " MHz) is less than\n" - << "analog frontend filter bandwidth (" << (min_bw/1e6) << " MHz)." - ; + if (rate > max_bw) { + UHD_LOGGER_WARNING("AD936X") + << "Selected " << dir << " sample rate (" << (rate / 1e6) + << " MHz) is greater than\n" + << "analog frontend filter bandwidth (" << (max_bw / 1e6) << " MHz)."; + } else if (rate < min_bw) { + UHD_LOGGER_WARNING("AD936X") + << "Selected " << dir << " sample rate (" << (rate / 1e6) + << " MHz) is less than\n" + << "analog frontend filter bandwidth (" << (min_bw / 1e6) << " MHz)."; } } return (rate <= bw); } void populate_frontend_subtree( - uhd::property_tree::sptr subtree, - const std::string &key, - uhd::direction_t dir - ) { - subtree->create<std::string>("name").set("FE-"+key); + uhd::property_tree::sptr subtree, const std::string& key, uhd::direction_t dir) + { + subtree->create<std::string>("name").set("FE-" + key); // Sensors - subtree->create<sensor_value_t>("sensors/temp") - .set_publisher([this](){ - return this->_codec_ctrl->get_temperature(); - }) - ; + subtree->create<sensor_value_t>("sensors/temp").set_publisher([this]() { + return this->_codec_ctrl->get_temperature(); + }); if (dir == RX_DIRECTION) { - subtree->create<sensor_value_t>("sensors/rssi") - .set_publisher([this, key](){ - return this->_codec_ctrl->get_rssi(key); - }) - ; + subtree->create<sensor_value_t>("sensors/rssi").set_publisher([this, key]() { + return this->_codec_ctrl->get_rssi(key); + }); } // Gains - for (const std::string &name : ad9361_ctrl::get_gain_names(key)) { + for (const std::string& name : ad9361_ctrl::get_gain_names(key)) { subtree->create<meta_range_t>(uhd::fs_path("gains") / name / "range") .set(ad9361_ctrl::get_gain_range(key)); subtree->create<double>(uhd::fs_path("gains") / name / "value") .set(ad936x_manager::DEFAULT_GAIN) - .set_coercer([this, key](const double gain){ + .set_coercer([this, key](const double gain) { return this->_codec_ctrl->set_gain(key, gain); - }) - ; + }); } // FE Settings @@ -254,78 +241,62 @@ public: // Analog Bandwidths subtree->create<double>("bandwidth/value") .set(DEFAULT_BANDWIDTH) - .set_coercer([this,key](double bw) { - return set_bw_filter(key, bw); - } - ) - ; - subtree->create<meta_range_t>("bandwidth/range") - .set_publisher([key]() { - return ad9361_ctrl::get_bw_filter_range(); - } - ) - ; + .set_coercer([this, key](double bw) { return set_bw_filter(key, bw); }); + subtree->create<meta_range_t>("bandwidth/range").set_publisher([key]() { + return ad9361_ctrl::get_bw_filter_range(); + }); // LO Tuning - subtree->create<meta_range_t>("freq/range") - .set_publisher([](){ - return ad9361_ctrl::get_rf_freq_range(); - }) - ; + subtree->create<meta_range_t>("freq/range").set_publisher([]() { + return ad9361_ctrl::get_rf_freq_range(); + }); subtree->create<double>("freq/value") - .set_publisher([this, key](){ - return this->_codec_ctrl->get_freq(key); - }) - .set_coercer([this, key](const double freq){ + .set_publisher([this, key]() { return this->_codec_ctrl->get_freq(key); }) + .set_coercer([this, key](const double freq) { return this->_codec_ctrl->tune(key, freq); - }) - ; + }); // Frontend corrections - if(dir == RX_DIRECTION) - { - subtree->create<bool>("dc_offset/enable" ) + if (dir == RX_DIRECTION) { + subtree->create<bool>("dc_offset/enable") .set(ad936x_manager::DEFAULT_AUTO_DC_OFFSET) - .add_coerced_subscriber([this, key](const bool enable){ + .add_coerced_subscriber([this, key](const bool enable) { this->_codec_ctrl->set_dc_offset_auto(key, enable); - }) - ; - subtree->create<bool>("iq_balance/enable" ) + }); + subtree->create<bool>("iq_balance/enable") .set(ad936x_manager::DEFAULT_AUTO_IQ_BALANCE) - .add_coerced_subscriber([this, key](const bool enable){ - this->_codec_ctrl->set_iq_balance_auto(key, enable); - }) - ; + .add_coerced_subscriber([this, key](const bool enable) { + this->_codec_ctrl->set_iq_balance_auto(key, enable); + }); // AGC setup const std::list<std::string> mode_strings{"slow", "fast"}; subtree->create<bool>("gain/agc/enable") .set(DEFAULT_AGC_ENABLE) - .add_coerced_subscriber([this, key](const bool enable){ + .add_coerced_subscriber([this, key](const bool enable) { this->_codec_ctrl->set_agc(key, enable); - }) - ; + }); subtree->create<std::string>("gain/agc/mode/value") - .add_coerced_subscriber([this, key](const std::string& value){ + .add_coerced_subscriber([this, key](const std::string& value) { this->_codec_ctrl->set_agc_mode(key, value); }) - .set(mode_strings.front()) - ; + .set(mode_strings.front()); subtree->create<std::list<std::string>>("gain/agc/mode/options") - .set(mode_strings) - ; + .set(mode_strings); } // Frontend filters - for (const auto &filter_name : _codec_ctrl->get_filter_names(key)) { - subtree->create<filter_info_base::sptr>(uhd::fs_path("filters") / filter_name / "value") - .set_publisher([this, key, filter_name](){ + for (const auto& filter_name : _codec_ctrl->get_filter_names(key)) { + subtree + ->create<filter_info_base::sptr>( + uhd::fs_path("filters") / filter_name / "value") + .set_publisher([this, key, filter_name]() { return this->_codec_ctrl->get_filter(key, filter_name); }) - .add_coerced_subscriber([this, key, filter_name](filter_info_base::sptr filter_info){ - this->_codec_ctrl->set_filter(key, filter_name, filter_info); - }) - ; + .add_coerced_subscriber( + [this, key, filter_name](filter_info_base::sptr filter_info) { + this->_codec_ctrl->set_filter(key, filter_name, filter_info); + }); } } @@ -342,22 +313,20 @@ private: std::vector<std::string> _tx_frontends; //! Current bandwidths - std::map<std::string,double> _bw; + std::map<std::string, double> _bw; //! Function to set bandwidth so it is tracked here double set_bw_filter(const std::string& which, const double bw) { double actual_bw = _codec_ctrl->set_bw_filter(which, bw); - _bw[which] = actual_bw; + _bw[which] = actual_bw; return actual_bw; } }; /* class ad936x_manager_impl */ ad936x_manager::sptr ad936x_manager::make( - const ad9361_ctrl::sptr &codec_ctrl, - const size_t n_frontends -) { + const ad9361_ctrl::sptr& codec_ctrl, const size_t n_frontends) +{ return boost::make_shared<ad936x_manager_impl>(codec_ctrl, n_frontends); } - |