summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/examples/rx_samples_to_file.cpp4
-rw-r--r--host/lib/usrp/b100/b100_impl.cpp6
-rw-r--r--host/lib/usrp/dboard/db_dbsrx2.cpp6
-rw-r--r--host/lib/usrp/dboard/db_sbx_common.cpp132
-rw-r--r--host/lib/usrp/dboard/db_sbx_common.hpp28
-rw-r--r--host/lib/usrp/dboard/db_sbx_version3.cpp118
-rw-r--r--host/lib/usrp/dboard/db_sbx_version4.cpp120
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.cpp8
-rw-r--r--host/lib/utils/paths.cpp22
-rw-r--r--host/utils/uhd_images_downloader.py.in63
-rw-r--r--host/utils/usrp_burn_mb_eeprom.cpp43
11 files changed, 321 insertions, 229 deletions
diff --git a/host/examples/rx_samples_to_file.cpp b/host/examples/rx_samples_to_file.cpp
index b0e498125..a28d1d628 100644
--- a/host/examples/rx_samples_to_file.cpp
+++ b/host/examples/rx_samples_to_file.cpp
@@ -236,8 +236,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
("ref", po::value<std::string>(&ref)->default_value("internal"), "waveform type (internal, external, mimo)")
("wirefmt", po::value<std::string>(&wirefmt)->default_value("sc16"), "wire format (sc8 or sc16)")
("setup", po::value<double>(&setup_time)->default_value(1.0), "seconds of setup time")
- ("progress", "show average bandwidth on exit")
- ("stats", "periodically display short-term bandwidth")
+ ("progress", "periodically display short-term bandwidth")
+ ("stats", "show average bandwidth on exit")
("sizemap", "track packet size and display breakdown on exit")
("null", "run without writing to file")
("continue", "don't abort on a bad packet")
diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp
index 19df3d6af..305ba42a7 100644
--- a/host/lib/usrp/b100/b100_impl.cpp
+++ b/host/lib/usrp/b100/b100_impl.cpp
@@ -310,12 +310,14 @@ b100_impl::b100_impl(const device_addr_t &device_addr){
_tree->create<std::string>(rx_codec_path / "name").set("ad9522");
_tree->create<meta_range_t>(rx_codec_path / "gains/pga/range").set(b100_codec_ctrl::rx_pga_gain_range);
_tree->create<double>(rx_codec_path / "gains/pga/value")
- .coerce(boost::bind(&b100_impl::update_rx_codec_gain, this, _1));
+ .coerce(boost::bind(&b100_impl::update_rx_codec_gain, this, _1))
+ .set(0.0);
_tree->create<std::string>(tx_codec_path / "name").set("ad9522");
_tree->create<meta_range_t>(tx_codec_path / "gains/pga/range").set(b100_codec_ctrl::tx_pga_gain_range);
_tree->create<double>(tx_codec_path / "gains/pga/value")
.subscribe(boost::bind(&b100_codec_ctrl::set_tx_pga_gain, _codec_ctrl, _1))
- .publish(boost::bind(&b100_codec_ctrl::get_tx_pga_gain, _codec_ctrl));
+ .publish(boost::bind(&b100_codec_ctrl::get_tx_pga_gain, _codec_ctrl))
+ .set(0.0);
////////////////////////////////////////////////////////////////////
// and do the misc mboard sensors
diff --git a/host/lib/usrp/dboard/db_dbsrx2.cpp b/host/lib/usrp/dboard/db_dbsrx2.cpp
index 013f3178a..8a8f61a69 100644
--- a/host/lib/usrp/dboard/db_dbsrx2.cpp
+++ b/host/lib/usrp/dboard/db_dbsrx2.cpp
@@ -358,12 +358,12 @@ double dbsrx2::set_gain(double gain, const std::string &name){
* Bandwidth Handling
**********************************************************************/
double dbsrx2::set_bandwidth(double bandwidth){
- //convert complex bandpass to lowpass bandwidth
- bandwidth = bandwidth/2.0;
-
//clip the input
bandwidth = dbsrx2_bandwidth_range.clip(bandwidth);
+ //convert complex bandpass to lowpass bandwidth
+ bandwidth = bandwidth/2.0;
+
_max2112_write_regs.lp = int((bandwidth/1e6 - 4)/0.29 + 12);
_bandwidth = double(4 + (_max2112_write_regs.lp - 12) * 0.29)*1e6;
diff --git a/host/lib/usrp/dboard/db_sbx_common.cpp b/host/lib/usrp/dboard/db_sbx_common.cpp
index 9db29e65a..5b713c6d7 100644
--- a/host/lib/usrp/dboard/db_sbx_common.cpp
+++ b/host/lib/usrp/dboard/db_sbx_common.cpp
@@ -21,6 +21,137 @@ using namespace uhd;
using namespace uhd::usrp;
using namespace boost::assign;
+/***********************************************************************
+ * ADF 4350/4351 Tuning Utility
+ **********************************************************************/
+sbx_xcvr::sbx_versionx::adf435x_tuning_settings sbx_xcvr::sbx_versionx::_tune_adf435x_synth(
+ double target_freq,
+ double ref_freq,
+ const adf435x_tuning_constraints& constraints,
+ double& actual_freq)
+{
+ //Default invalid value for actual_freq
+ actual_freq = 0;
+
+ double pfd_freq = 0;
+ boost::uint16_t R = 0, BS = 0, N = 0, FRAC = 0, MOD = 0;
+ boost::uint16_t RFdiv = static_cast<boost::uint16_t>(constraints.rf_divider_range.start());
+ bool D = false, T = false;
+
+ //Reference doubler for 50% duty cycle
+ //If ref_freq < 12.5MHz enable the reference doubler
+ D = (ref_freq <= constraints.ref_doubler_threshold);
+
+ static const double MIN_VCO_FREQ = 2.2e9;
+ static const double MAX_VCO_FREQ = 4.4e9;
+
+ //increase RF divider until acceptable VCO frequency
+ double vco_freq = target_freq;
+ while (vco_freq < MIN_VCO_FREQ && RFdiv < static_cast<boost::uint16_t>(constraints.rf_divider_range.stop())) {
+ vco_freq *= 2;
+ RFdiv *= 2;
+ }
+
+ /*
+ * The goal here is to loop though possible R dividers,
+ * band select clock dividers, N (int) dividers, and FRAC
+ * (frac) dividers.
+ *
+ * Calculate the N and F dividers for each set of values.
+ * The loop exits when it meets all of the constraints.
+ * The resulting loop values are loaded into the registers.
+ *
+ * from pg.21
+ *
+ * f_pfd = f_ref*(1+D)/(R*(1+T))
+ * f_vco = (N + (FRAC/MOD))*f_pfd
+ * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD
+ * f_rf = f_vco/RFdiv)
+ * f_actual = f_rf/2
+ */
+ for(R = 1; R <= 1023; R+=1){
+ //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T)
+ pfd_freq = ref_freq*(D?2:1)/(R*(T?2:1));
+
+ //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth)
+ if (pfd_freq > constraints.pfd_freq_max) continue;
+
+ //ignore fractional part of tuning
+ //N is computed from target_freq and not vco_freq because the feedback
+ //mode is set to FEEDBACK_SELECT_DIVIDED
+ N = boost::uint16_t(std::floor(target_freq/pfd_freq));
+
+ //keep N > minimum int divider requirement
+ if (N < static_cast<boost::uint16_t>(constraints.int_range.start())) continue;
+
+ for(BS=1; BS <= 255; BS+=1){
+ //keep the band select frequency at or below band_sel_freq_max
+ //constraint on band select clock
+ if (pfd_freq/BS > constraints.band_sel_freq_max) continue;
+ goto done_loop;
+ }
+ } done_loop:
+
+ //Fractional-N calculation
+ MOD = 4095; //max fractional accuracy
+ //N is computed from target_freq and not vco_freq because the feedback
+ //mode is set to FEEDBACK_SELECT_DIVIDED
+ FRAC = static_cast<boost::uint16_t>((target_freq/pfd_freq - N)*MOD);
+ if (constraints.force_frac0) {
+ if (FRAC > (MOD / 2)) { //Round integer such that actual freq is closest to target
+ N++;
+ }
+ FRAC = 0;
+ }
+
+ //Reference divide-by-2 for 50% duty cycle
+ // if R even, move one divide by 2 to to regs.reference_divide_by_2
+ if(R % 2 == 0) {
+ T = true;
+ R /= 2;
+ }
+
+ //Typical phase resync time documented in data sheet pg.24
+ static const double PHASE_RESYNC_TIME = 400e-6;
+
+ //actual frequency calculation
+ actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(D?2:1)/(R*(T?2:1)));
+
+ //load the settings
+ adf435x_tuning_settings settings;
+ settings.frac_12_bit = FRAC;
+ settings.int_16_bit = N;
+ settings.mod_12_bit = MOD;
+ settings.clock_divider_12_bit = std::max<boost::uint16_t>(1, std::ceil(PHASE_RESYNC_TIME*pfd_freq/MOD));
+ settings.r_counter_10_bit = R;
+ settings.r_divide_by_2_en = T;
+ settings.r_doubler_en = D;
+ settings.band_select_clock_div = BS;
+ settings.rf_divider = RFdiv;
+ settings.feedback_after_divider = true;
+
+ UHD_LOGV(often)
+ << boost::format("ADF 435X Frequencies (MHz): REQUESTED=%0.9f, ACTUAL=%0.9f"
+ ) % (target_freq/1e6) % (actual_freq/1e6) << std::endl
+ << boost::format("ADF 435X Intermediates (MHz): VCO=%0.2f, PFD=%0.2f, BAND=%0.2f, REF=%0.2f"
+ ) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) % (ref_freq/1e6) << std::endl
+ << boost::format("ADF 435X Settings: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d"
+ ) % R % BS % N % FRAC % MOD % T % D % RFdiv << std::endl;
+
+ UHD_ASSERT_THROW((settings.frac_12_bit & ((boost::uint16_t)~0xFFF)) == 0);
+ UHD_ASSERT_THROW((settings.mod_12_bit & ((boost::uint16_t)~0xFFF)) == 0);
+ UHD_ASSERT_THROW((settings.clock_divider_12_bit & ((boost::uint16_t)~0xFFF)) == 0);
+ UHD_ASSERT_THROW((settings.r_counter_10_bit & ((boost::uint16_t)~0x3FF)) == 0);
+
+ UHD_ASSERT_THROW(vco_freq >= MIN_VCO_FREQ and vco_freq <= MAX_VCO_FREQ);
+ UHD_ASSERT_THROW(settings.rf_divider >= static_cast<boost::uint16_t>(constraints.rf_divider_range.start()));
+ UHD_ASSERT_THROW(settings.rf_divider <= static_cast<boost::uint16_t>(constraints.rf_divider_range.stop()));
+ UHD_ASSERT_THROW(settings.int_16_bit >= static_cast<boost::uint16_t>(constraints.int_range.start()));
+ UHD_ASSERT_THROW(settings.int_16_bit <= static_cast<boost::uint16_t>(constraints.int_range.stop()));
+
+ return settings;
+}
+
/***********************************************************************
* Register the SBX dboard (min freq, max freq, rx div2, tx div2)
@@ -362,4 +493,3 @@ void sbx_xcvr::flash_leds(void) {
this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO));
this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO));
}
-
diff --git a/host/lib/usrp/dboard/db_sbx_common.hpp b/host/lib/usrp/dboard/db_sbx_common.hpp
index 4f3a2eeaa..e9bb2434c 100644
--- a/host/lib/usrp/dboard/db_sbx_common.hpp
+++ b/host/lib/usrp/dboard/db_sbx_common.hpp
@@ -181,6 +181,34 @@ protected:
~sbx_versionx(void) {}
virtual double set_lo_freq(dboard_iface::unit_t unit, double target_freq) = 0;
+ protected:
+ struct adf435x_tuning_constraints {
+ bool force_frac0;
+ double ref_doubler_threshold;
+ double pfd_freq_max;
+ double band_sel_freq_max;
+ uhd::range_t rf_divider_range;
+ uhd::range_t int_range;
+ };
+
+ struct adf435x_tuning_settings {
+ boost::uint16_t frac_12_bit;
+ boost::uint16_t int_16_bit;
+ boost::uint16_t mod_12_bit;
+ boost::uint16_t r_counter_10_bit;
+ bool r_doubler_en;
+ bool r_divide_by_2_en;
+ boost::uint16_t clock_divider_12_bit;
+ boost::uint8_t band_select_clock_div;
+ boost::uint16_t rf_divider;
+ bool feedback_after_divider;
+ };
+
+ adf435x_tuning_settings _tune_adf435x_synth(
+ double target_freq,
+ double ref_freq,
+ const adf435x_tuning_constraints& constraints,
+ double& actual_freq);
};
/*!
diff --git a/host/lib/usrp/dboard/db_sbx_version3.cpp b/host/lib/usrp/dboard/db_sbx_version3.cpp
index 2765d530c..b0c9cd18f 100644
--- a/host/lib/usrp/dboard/db_sbx_version3.cpp
+++ b/host/lib/usrp/dboard/db_sbx_version3.cpp
@@ -63,85 +63,21 @@ double sbx_xcvr::sbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar
(16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16)
;
- double actual_freq, pfd_freq;
- double ref_freq = self_base->get_iface()->get_clock_rate(unit);
- int R=0, BS=0, N=0, FRAC=0, MOD=0;
- int RFdiv = 1;
- adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED;
- adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED;
-
- //Reference doubler for 50% duty cycle
- // if ref_freq < 12.5MHz enable regs.reference_divide_by_2
- if(ref_freq <= 12.5e6) D = adf4350_regs_t::REFERENCE_DOUBLER_ENABLED;
-
- //increase RF divider until acceptable VCO frequency
- double vco_freq = target_freq;
- while (vco_freq < 2.2e9) {
- vco_freq *= 2;
- RFdiv *= 2;
- }
-
//use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler)
adf4350_regs_t::prescaler_t prescaler = target_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5;
- /*
- * The goal here is to loop though possible R dividers,
- * band select clock dividers, N (int) dividers, and FRAC
- * (frac) dividers.
- *
- * Calculate the N and F dividers for each set of values.
- * The loop exits when it meets all of the constraints.
- * The resulting loop values are loaded into the registers.
- *
- * from pg.21
- *
- * f_pfd = f_ref*(1+D)/(R*(1+T))
- * f_vco = (N + (FRAC/MOD))*f_pfd
- * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD
- * f_rf = f_vco/RFdiv)
- * f_actual = f_rf/2
- */
- for(R = 1; R <= 1023; R+=1){
- //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T)
- pfd_freq = ref_freq*(1+D)/(R*(1+T));
-
- //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth)
- if (pfd_freq > 25e6) continue;
-
- //ignore fractional part of tuning
- N = int(std::floor(target_freq/pfd_freq));
-
- //keep N > minimum int divider requirement
- if (N < prescaler_to_min_int_div[prescaler]) continue;
-
- for(BS=1; BS <= 255; BS+=1){
- //keep the band select frequency at or below 100KHz
- //constraint on band select clock
- if (pfd_freq/BS > 100e3) continue;
- goto done_loop;
- }
- } done_loop:
-
- //Fractional-N calculation
- MOD = 4095; //max fractional accuracy
- FRAC = int((target_freq/pfd_freq - N)*MOD);
-
- //Reference divide-by-2 for 50% duty cycle
- // if R even, move one divide by 2 to to regs.reference_divide_by_2
- if(R % 2 == 0){
- T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED;
- R /= 2;
- }
-
- //actual frequency calculation
- actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T))));
+ adf435x_tuning_constraints tuning_constraints;
+ tuning_constraints.force_frac0 = false;
+ tuning_constraints.band_sel_freq_max = 100e3;
+ tuning_constraints.ref_doubler_threshold = 12.5e6;
+ tuning_constraints.int_range = uhd::range_t(prescaler_to_min_int_div[prescaler], 4095); //INT is a 12-bit field
+ tuning_constraints.pfd_freq_max = 25e6;
+ tuning_constraints.rf_divider_range = uhd::range_t(1, 16);
- UHD_LOGV(often)
- << boost::format("SBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl
- << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d"
- ) % R % BS % N % FRAC % MOD % T % D % RFdiv << std::endl
- << boost::format("SBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f"
- ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl;
+ double actual_freq;
+ adf435x_tuning_settings tuning_settings = _tune_adf435x_synth(
+ target_freq, self_base->get_iface()->get_clock_rate(unit),
+ tuning_constraints, actual_freq);
//load the register values
adf4350_regs_t regs;
@@ -151,19 +87,25 @@ double sbx_xcvr::sbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar
else
regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM;
- regs.frac_12_bit = FRAC;
- regs.int_16_bit = N;
- regs.mod_12_bit = MOD;
- regs.clock_divider_12_bit = std::max(1, int(std::ceil(400e-6*pfd_freq/MOD)));
- regs.feedback_select = adf4350_regs_t::FEEDBACK_SELECT_DIVIDED;
- regs.clock_div_mode = adf4350_regs_t::CLOCK_DIV_MODE_RESYNC_ENABLE;
- regs.prescaler = prescaler;
- regs.r_counter_10_bit = R;
- regs.reference_divide_by_2 = T;
- regs.reference_doubler = D;
- regs.band_select_clock_div = BS;
- UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv));
- regs.rf_divider_select = rfdivsel_to_enum[RFdiv];
+ regs.frac_12_bit = tuning_settings.frac_12_bit;
+ regs.int_16_bit = tuning_settings.int_16_bit;
+ regs.mod_12_bit = tuning_settings.mod_12_bit;
+ regs.clock_divider_12_bit = tuning_settings.clock_divider_12_bit;
+ regs.feedback_select = tuning_settings.feedback_after_divider ?
+ adf4350_regs_t::FEEDBACK_SELECT_DIVIDED :
+ adf4350_regs_t::FEEDBACK_SELECT_FUNDAMENTAL;
+ regs.clock_div_mode = adf4350_regs_t::CLOCK_DIV_MODE_RESYNC_ENABLE;
+ regs.prescaler = prescaler;
+ regs.r_counter_10_bit = tuning_settings.r_counter_10_bit;
+ regs.reference_divide_by_2 = tuning_settings.r_divide_by_2_en ?
+ adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED :
+ adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED;
+ regs.reference_doubler = tuning_settings.r_doubler_en ?
+ adf4350_regs_t::REFERENCE_DOUBLER_ENABLED :
+ adf4350_regs_t::REFERENCE_DOUBLER_DISABLED;
+ regs.band_select_clock_div = tuning_settings.band_select_clock_div;
+ UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(tuning_settings.rf_divider));
+ regs.rf_divider_select = rfdivsel_to_enum[tuning_settings.rf_divider];
//reset the N and R counter
regs.counter_reset = adf4350_regs_t::COUNTER_RESET_ENABLED;
diff --git a/host/lib/usrp/dboard/db_sbx_version4.cpp b/host/lib/usrp/dboard/db_sbx_version4.cpp
index 27fd68b05..8d95b0655 100644
--- a/host/lib/usrp/dboard/db_sbx_version4.cpp
+++ b/host/lib/usrp/dboard/db_sbx_version4.cpp
@@ -66,85 +66,21 @@ double sbx_xcvr::sbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar
(64, adf4351_regs_t::RF_DIVIDER_SELECT_DIV64)
;
- double actual_freq, pfd_freq;
- double ref_freq = self_base->get_iface()->get_clock_rate(unit);
- int R=0, BS=0, N=0, FRAC=0, MOD=0;
- int RFdiv = 1;
- adf4351_regs_t::reference_divide_by_2_t T = adf4351_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED;
- adf4351_regs_t::reference_doubler_t D = adf4351_regs_t::REFERENCE_DOUBLER_DISABLED;
-
- //Reference doubler for 50% duty cycle
- // if ref_freq < 12.5MHz enable regs.reference_divide_by_2
- if(ref_freq <= 12.5e6) D = adf4351_regs_t::REFERENCE_DOUBLER_ENABLED;
-
- //increase RF divider until acceptable VCO frequency
- double vco_freq = target_freq;
- while (vco_freq < 2.2e9) {
- vco_freq *= 2;
- RFdiv *= 2;
- }
-
//use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler)
- adf4351_regs_t::prescaler_t prescaler = target_freq > 3e9 ? adf4351_regs_t::PRESCALER_8_9 : adf4351_regs_t::PRESCALER_4_5;
-
- /*
- * The goal here is to loop though possible R dividers,
- * band select clock dividers, N (int) dividers, and FRAC
- * (frac) dividers.
- *
- * Calculate the N and F dividers for each set of values.
- * The loop exits when it meets all of the constraints.
- * The resulting loop values are loaded into the registers.
- *
- * from pg.21
- *
- * f_pfd = f_ref*(1+D)/(R*(1+T))
- * f_vco = (N + (FRAC/MOD))*f_pfd
- * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD
- * f_rf = f_vco/RFdiv)
- * f_actual = f_rf/2
- */
- for(R = 1; R <= 1023; R+=1){
- //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T)
- pfd_freq = ref_freq*(1+D)/(R*(1+T));
-
- //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth)
- if (pfd_freq > 25e6) continue;
-
- //ignore fractional part of tuning
- N = int(std::floor(vco_freq/pfd_freq));
-
- //keep N > minimum int divider requirement
- if (N < prescaler_to_min_int_div[prescaler]) continue;
-
- for(BS=1; BS <= 255; BS+=1){
- //keep the band select frequency at or below 100KHz
- //constraint on band select clock
- if (pfd_freq/BS > 100e3) continue;
- goto done_loop;
- }
- } done_loop:
-
- //Fractional-N calculation
- MOD = 4095; //max fractional accuracy
- FRAC = int((target_freq/pfd_freq - N)*MOD);
-
- //Reference divide-by-2 for 50% duty cycle
- // if R even, move one divide by 2 to to regs.reference_divide_by_2
- if(R % 2 == 0){
- T = adf4351_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED;
- R /= 2;
- }
+ adf4351_regs_t::prescaler_t prescaler = target_freq > 3.6e9 ? adf4351_regs_t::PRESCALER_8_9 : adf4351_regs_t::PRESCALER_4_5;
- //actual frequency calculation
- actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T))));
+ adf435x_tuning_constraints tuning_constraints;
+ tuning_constraints.force_frac0 = false;
+ tuning_constraints.band_sel_freq_max = 100e3;
+ tuning_constraints.ref_doubler_threshold = 12.5e6;
+ tuning_constraints.int_range = uhd::range_t(prescaler_to_min_int_div[prescaler], 4095); //INT is a 12-bit field
+ tuning_constraints.pfd_freq_max = 25e6;
+ tuning_constraints.rf_divider_range = uhd::range_t(1, 64);
- UHD_LOGV(often)
- << boost::format("SBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl
- << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d"
- ) % R % BS % N % FRAC % MOD % T % D % RFdiv << std::endl
- << boost::format("SBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f"
- ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl;
+ double actual_freq;
+ adf435x_tuning_settings tuning_settings = _tune_adf435x_synth(
+ target_freq, self_base->get_iface()->get_clock_rate(unit),
+ tuning_constraints, actual_freq);
//load the register values
adf4351_regs_t regs;
@@ -154,19 +90,25 @@ double sbx_xcvr::sbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar
else
regs.output_power = adf4351_regs_t::OUTPUT_POWER_5DBM;
- regs.frac_12_bit = FRAC;
- regs.int_16_bit = N;
- regs.mod_12_bit = MOD;
- regs.clock_divider_12_bit = std::max(1, int(std::ceil(400e-6*pfd_freq/MOD)));
- regs.feedback_select = adf4351_regs_t::FEEDBACK_SELECT_DIVIDED;
- regs.clock_div_mode = adf4351_regs_t::CLOCK_DIV_MODE_RESYNC_ENABLE;
- regs.prescaler = prescaler;
- regs.r_counter_10_bit = R;
- regs.reference_divide_by_2 = T;
- regs.reference_doubler = D;
- regs.band_select_clock_div = BS;
- UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv));
- regs.rf_divider_select = rfdivsel_to_enum[RFdiv];
+ regs.frac_12_bit = tuning_settings.frac_12_bit;
+ regs.int_16_bit = tuning_settings.int_16_bit;
+ regs.mod_12_bit = tuning_settings.mod_12_bit;
+ regs.clock_divider_12_bit = tuning_settings.clock_divider_12_bit;
+ regs.feedback_select = tuning_settings.feedback_after_divider ?
+ adf4351_regs_t::FEEDBACK_SELECT_DIVIDED :
+ adf4351_regs_t::FEEDBACK_SELECT_FUNDAMENTAL;
+ regs.clock_div_mode = adf4351_regs_t::CLOCK_DIV_MODE_RESYNC_ENABLE;
+ regs.prescaler = prescaler;
+ regs.r_counter_10_bit = tuning_settings.r_counter_10_bit;
+ regs.reference_divide_by_2 = tuning_settings.r_divide_by_2_en ?
+ adf4351_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED :
+ adf4351_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED;
+ regs.reference_doubler = tuning_settings.r_doubler_en ?
+ adf4351_regs_t::REFERENCE_DOUBLER_ENABLED :
+ adf4351_regs_t::REFERENCE_DOUBLER_DISABLED;
+ regs.band_select_clock_div = tuning_settings.band_select_clock_div;
+ UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(tuning_settings.rf_divider));
+ regs.rf_divider_select = rfdivsel_to_enum[tuning_settings.rf_divider];
//reset the N and R counter
regs.counter_reset = adf4351_regs_t::COUNTER_RESET_ENABLED;
diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp
index 253ac1d6f..625926f36 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.cpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.cpp
@@ -258,12 +258,14 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){
_tree->create<std::string>(rx_codec_path / "name").set("ad9522");
_tree->create<meta_range_t>(rx_codec_path / "gains/pga/range").set(usrp1_codec_ctrl::rx_pga_gain_range);
_tree->create<double>(rx_codec_path / "gains/pga/value")
- .coerce(boost::bind(&usrp1_impl::update_rx_codec_gain, this, db, _1));
+ .coerce(boost::bind(&usrp1_impl::update_rx_codec_gain, this, db, _1))
+ .set(0.0);
_tree->create<std::string>(tx_codec_path / "name").set("ad9522");
_tree->create<meta_range_t>(tx_codec_path / "gains/pga/range").set(usrp1_codec_ctrl::tx_pga_gain_range);
_tree->create<double>(tx_codec_path / "gains/pga/value")
.subscribe(boost::bind(&usrp1_codec_ctrl::set_tx_pga_gain, _dbc[db].codec, _1))
- .publish(boost::bind(&usrp1_codec_ctrl::get_tx_pga_gain, _dbc[db].codec));
+ .publish(boost::bind(&usrp1_codec_ctrl::get_tx_pga_gain, _dbc[db].codec))
+ .set(0.0);
}
////////////////////////////////////////////////////////////////////
@@ -407,7 +409,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){
_tree->access<subdev_spec_t>(mb_path / "rx_subdev_spec").set(_rx_subdev_spec);
if (_tree->list(mb_path / "tx_dsps").size() > 0)
_tree->access<subdev_spec_t>(mb_path / "tx_subdev_spec").set(_tx_subdev_spec);
-
+
}
usrp1_impl::~usrp1_impl(void){
diff --git a/host/lib/utils/paths.cpp b/host/lib/utils/paths.cpp
index 53055314b..25cade693 100644
--- a/host/lib/utils/paths.cpp
+++ b/host/lib/utils/paths.cpp
@@ -34,8 +34,19 @@
namespace fs = boost::filesystem;
/***********************************************************************
+ * Get a list of paths for an environment variable
+ **********************************************************************/
+static std::string get_env_var(const std::string &var_name, const std::string &def_val = ""){
+ const char *var_value_ptr = std::getenv(var_name.c_str());
+ return (var_value_ptr == NULL)? def_val : var_value_ptr;
+}
+
+static std::vector<fs::path> get_env_paths(const std::string &var_name){
+
+/***********************************************************************
* Determine the paths separator
**********************************************************************/
+
#ifdef UHD_PLATFORM_WIN32
static const std::string env_path_sep = ";";
#else
@@ -46,16 +57,6 @@ namespace fs = boost::filesystem;
boost::tokenizer<boost::char_separator<char> > \
(inp, boost::char_separator<char>(env_path_sep.c_str()))
-/***********************************************************************
- * Get a list of paths for an environment variable
- **********************************************************************/
-static std::string get_env_var(const std::string &var_name, const std::string &def_val = ""){
- const char *var_value_ptr = std::getenv(var_name.c_str());
- return (var_value_ptr == NULL)? def_val : var_value_ptr;
-}
-
-static std::vector<fs::path> get_env_paths(const std::string &var_name){
-
std::string var_value = get_env_var(var_name);
//convert to filesystem path, filter blank paths
@@ -85,6 +86,7 @@ std::vector<fs::path> get_image_paths(void){
std::vector<fs::path> get_module_paths(void){
std::vector<fs::path> paths = get_env_paths("UHD_MODULE_PATH");
paths.push_back(fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "modules");
+ paths.push_back(fs::path(uhd::get_pkg_path()) / "share" / "uhd" / "modules");
return paths;
}
diff --git a/host/utils/uhd_images_downloader.py.in b/host/utils/uhd_images_downloader.py.in
index e7fc9e8a5..bb082190c 100644
--- a/host/utils/uhd_images_downloader.py.in
+++ b/host/utils/uhd_images_downloader.py.in
@@ -44,13 +44,25 @@ class temp_dir():
self.name = tempfile.mkdtemp()
return self.name
def __exit__(self, type, value, traceback):
- os.removedirs(self.name)
+ try:
+ shutil.rmtree(self.name)
+ except OSError,e:
+ #Utility should have already detected this, but this is for safety
+ print str(e)
+ raise Exception("Could not install images! Make sure you have write permissions.")
if __name__ == "__main__":
+ print
+ if os.environ.get("UHD_IMAGES_DIR") != None and os.environ.get("UHD_IMAGES_DIR") != "":
+ default_images_dir = os.environ.get("UHD_IMAGES_DIR")
+ print "UHD_IMAGES_DIR environment variable is set. Default install location: %s" % default_images_dir
+ else:
+ default_images_dir = "@CMAKE_INSTALL_PREFIX@/share/uhd/images"
+
#Command line options
parser = OptionParser()
- parser.add_option("--install-location", type="string", default="", help="Set custom install location for images")
+ parser.add_option("--install-location", type="string", default=default_images_dir, help="Set custom install location for images")
parser.add_option("--buffer-size", type="int", default=8192, help="Set download buffer size, [default=%default]",)
(options, args) = parser.parse_args()
@@ -59,17 +71,27 @@ if __name__ == "__main__":
images_zip_md5sum = "@UHD_IMAGES_MD5SUM@"
filename = images_src.split("/")[-1]
+ #Use this directory with relative paths
+ current_directory = os.getcwd()
+
with temp_dir() as dirname:
os.chdir(dirname)
- #Configuring image destination
- if options.install_location != "":
+ if os.path.isabs(options.install_location):
+ #Custom absolute path given
images_dir = options.install_location
- elif os.environ.get("UHD_IMAGES_DIR") != "" and os.environ.get("UHD_IMAGES_DIR") != None:
- images_dir = os.environ.get("UHD_IMAGES_DIR")
else:
- images_dir = "@CMAKE_INSTALL_PREFIX@/share/uhd/images"
-
+ #Custom relative path given, so construct absolute path
+ images_dir = os.path.abspath(os.path.join(current_directory, options.install_location))
+
+ #Before doing anything, check for write permissions in parent directory
+ parent_directory = os.path.dirname(images_dir)
+ if os.access(parent_directory, os.W_OK):
+ print "Downloading images to: %s" % images_dir
+ else:
+ print "You do not have write permissions at the install location!"
+ sys.exit(1)
+
opener = urllib2.build_opener()
opener.add_headers = [('User-Agent', 'UHD Images Downloader')]
u = opener.open(images_src)
@@ -101,32 +123,37 @@ if __name__ == "__main__":
if images_zip_md5sum != downloaded_zip_md5sum:
print "\nMD5 checksum does not match!"
print "Expected %s, got %s" % (images_zip_md5sum, downloaded_zip_md5sum)
+ print "Images did not install. If problem persists, please contact support@ettus.com."
os.remove(filename)
os.chdir("/".join(images_dir.split("/")[:-1]))
+ sys.exit(1)
else:
+ temp_path = "tempdir"
+
#Extracting contents of zip file
- if os.path.exists("tempdir"):
- shutil.rmtree("tempdir")
- os.mkdir("tempdir")
+ if os.path.exists(temp_path):
+ shutil.rmtree(temp_path)
+ os.mkdir(temp_path)
images_zip = zipfile.ZipFile(filename)
- images_zip.extractall("tempdir")
+ images_zip.extractall(temp_path)
#Removing images currently in images_dir
if os.path.exists(images_dir):
try:
shutil.rmtree(images_dir)
- except:
- sys.stderr.write("\nMake sure you have write permissions in the images directory.\n")
- sys.exit(0)
+ except OSError,e:
+ print str(e)
+ print "Make sure you have write permissions in the images directory."
+ sys.exit(1)
#Copying downloaded images into images_dir
- shutil.copytree("tempdir/%s/share/uhd/images" % filename[:-4],images_dir)
+ shutil.copytree(os.path.join(temp_path, os.path.splitext(filename)[0], 'share', 'uhd', 'images'), images_dir)
#Removing tempdir and zip file
- shutil.rmtree("tempdir")
+ shutil.rmtree(temp_path)
images_zip.close()
os.remove(filename)
os.chdir(images_dir)
- print "\nImages successfully installed to: %s" % images_dir
+ print "\n\nImages successfully installed!"
diff --git a/host/utils/usrp_burn_mb_eeprom.cpp b/host/utils/usrp_burn_mb_eeprom.cpp
index 1b13fb615..ce0879c8e 100644
--- a/host/utils/usrp_burn_mb_eeprom.cpp
+++ b/host/utils/usrp_burn_mb_eeprom.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010,2013 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -19,9 +19,11 @@
#include <uhd/device.hpp>
#include <uhd/property_tree.hpp>
#include <uhd/usrp/mboard_eeprom.hpp>
+#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
#include <iostream>
+#include <vector>
namespace po = boost::program_options;
@@ -32,8 +34,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
desc.add_options()
("help", "help message")
("args", po::value<std::string>(&args)->default_value(""), "device address args [default = \"\"]")
- ("key", po::value<std::string>(&key), "the indentifier for a value in EEPROM")
- ("val", po::value<std::string>(&val), "the new value to set, omit for readback")
+ ("key", po::value<std::string>(&key), "identifiers for new values in EEPROM, separate multiple by \",\"")
+ ("val", po::value<std::string>(&val), "the new values to set, omit for readback, separate multiple by \",\"")
;
po::variables_map vm;
@@ -55,20 +57,35 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
uhd::property_tree::sptr tree = dev->get_tree();
std::cout << std::endl;
- if (true /*always readback*/){
- std::cout << "Fetching current settings from EEPROM..." << std::endl;
- uhd::usrp::mboard_eeprom_t mb_eeprom = tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").get();
- if (not mb_eeprom.has_key(key)){
- std::cerr << boost::format("Cannot find value for EEPROM[%s]") % key << std::endl;
+ //remove whitespace, split arguments and values
+ boost::algorithm::erase_all(key, " ");
+ boost::algorithm::erase_all(val, " ");
+
+ std::vector<std::string> keys_vec, vals_vec;
+ boost::split(keys_vec, key, boost::is_any_of("\"',"));
+ boost::split(vals_vec, val, boost::is_any_of("\"',"));
+
+ if((keys_vec.size() != vals_vec.size()) and val != "") {
+ //If zero values are given, then user just wants values read to them
+ throw std::runtime_error("Number of keys must match number of values!");
+ }
+
+ std::cout << "Fetching current settings from EEPROM..." << std::endl;
+ uhd::usrp::mboard_eeprom_t mb_eeprom = tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").get();
+ for(size_t i = 0; i < keys_vec.size(); i++){
+ if (not mb_eeprom.has_key(keys_vec[i])){
+ std::cerr << boost::format("Cannot find value for EEPROM[%s]") % keys_vec[i] << std::endl;
return EXIT_FAILURE;
}
- std::cout << boost::format(" EEPROM [\"%s\"] is \"%s\"") % key % mb_eeprom[key] << std::endl;
- std::cout << std::endl;
+ std::cout << boost::format(" EEPROM [\"%s\"] is \"%s\"") % keys_vec[i] % mb_eeprom[keys_vec[i]] << std::endl;
}
+ std::cout << std::endl;
if (vm.count("val")){
- uhd::usrp::mboard_eeprom_t mb_eeprom; mb_eeprom[key] = val;
- std::cout << boost::format("Setting EEPROM [\"%s\"] to \"%s\"...") % key % val << std::endl;
- tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").set(mb_eeprom);
+ for(size_t i = 0; i < vals_vec.size(); i++){
+ uhd::usrp::mboard_eeprom_t mb_eeprom; mb_eeprom[keys_vec[i]] = vals_vec[i];
+ std::cout << boost::format("Setting EEPROM [\"%s\"] to \"%s\"...") % keys_vec[i] % vals_vec[i] << std::endl;
+ tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").set(mb_eeprom);
+ }
std::cout << "Power-cycle the USRP device for the changes to take effect." << std::endl;
std::cout << std::endl;
}