aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
Diffstat (limited to 'host')
-rw-r--r--host/lib/include/uhdlib/usrp/common/adf535x.hpp814
-rw-r--r--host/lib/include/uhdlib/usrp/common/lmx2592.hpp6
-rw-r--r--host/lib/usrp/b100/clock_ctrl.cpp506
-rw-r--r--host/lib/usrp/b200/b200_io_impl.cpp527
-rw-r--r--host/lib/usrp/common/ad936x_manager.cpp247
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);
}
-