aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/dboard/db_sbx_common.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/dboard/db_sbx_common.cpp')
-rw-r--r--host/lib/usrp/dboard/db_sbx_common.cpp186
1 files changed, 41 insertions, 145 deletions
diff --git a/host/lib/usrp/dboard/db_sbx_common.cpp b/host/lib/usrp/dboard/db_sbx_common.cpp
index 5b713c6d7..49e30949e 100644
--- a/host/lib/usrp/dboard/db_sbx_common.cpp
+++ b/host/lib/usrp/dboard/db_sbx_common.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2011-2012 Ettus Research LLC
+// Copyright 2011-2014 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
@@ -21,137 +21,6 @@ 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)
@@ -164,6 +33,8 @@ UHD_STATIC_BLOCK(reg_sbx_dboards){
dboard_manager::register_dboard(0x0054, 0x0055, &make_sbx, "SBX");
dboard_manager::register_dboard(0x0065, 0x0064, &make_sbx, "SBX v4");
dboard_manager::register_dboard(0x0067, 0x0066, &make_sbx, "CBX");
+ dboard_manager::register_dboard(0x0083, 0x0082, &make_sbx, "SBX-120");
+ dboard_manager::register_dboard(0x0085, 0x0084, &make_sbx, "CBX-120");
}
@@ -244,15 +115,23 @@ double sbx_xcvr::set_rx_gain(double gain, const std::string &name){
**********************************************************************/
sbx_xcvr::sbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){
switch(get_rx_id().to_uint16()) {
- case 0x054:
+ case 0x0054:
db_actual = sbx_versionx_sptr(new sbx_version3(this));
freq_range = sbx_freq_range;
break;
- case 0x065:
+ case 0x0065:
db_actual = sbx_versionx_sptr(new sbx_version4(this));
freq_range = sbx_freq_range;
break;
- case 0x067:
+ case 0x0067:
+ db_actual = sbx_versionx_sptr(new cbx(this));
+ freq_range = cbx_freq_range;
+ break;
+ case 0x0083:
+ db_actual = sbx_versionx_sptr(new sbx_version4(this));
+ freq_range = sbx_freq_range;
+ break;
+ case 0x0085:
db_actual = sbx_versionx_sptr(new cbx(this));
freq_range = cbx_freq_range;
break;
@@ -264,9 +143,14 @@ sbx_xcvr::sbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){
////////////////////////////////////////////////////////////////////
// Register RX properties
////////////////////////////////////////////////////////////////////
- if(get_rx_id() == 0x054) this->get_rx_subtree()->create<std::string>("name").set("SBXv3 RX");
- else if(get_rx_id() == 0x065) this->get_rx_subtree()->create<std::string>("name").set("SBXv4 RX");
- else if(get_rx_id() == 0x067) this->get_rx_subtree()->create<std::string>("name").set("CBX RX");
+ this->get_rx_subtree()->create<device_addr_t>("tune_args").set(device_addr_t());
+
+ boost::uint16_t rx_id = get_rx_id().to_uint16();
+ if(rx_id == 0x0054) this->get_rx_subtree()->create<std::string>("name").set("SBXv3 RX");
+ else if(rx_id == 0x0065) this->get_rx_subtree()->create<std::string>("name").set("SBXv4 RX");
+ else if(rx_id == 0x0067) this->get_rx_subtree()->create<std::string>("name").set("CBX RX");
+ else if(rx_id == 0x0083) this->get_rx_subtree()->create<std::string>("name").set("SBX-120 RX");
+ else if(rx_id == 0x0085) this->get_rx_subtree()->create<std::string>("name").set("CBX-120 RX");
else this->get_rx_subtree()->create<std::string>("name").set("SBX/CBX RX");
this->get_rx_subtree()->create<sensor_value_t>("sensors/lo_locked")
@@ -290,16 +174,24 @@ sbx_xcvr::sbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){
this->get_rx_subtree()->create<std::string>("connection").set("IQ");
this->get_rx_subtree()->create<bool>("enabled").set(true); //always enabled
this->get_rx_subtree()->create<bool>("use_lo_offset").set(false);
- this->get_rx_subtree()->create<double>("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided
+
+ //Value of bw low-pass dependent on board, we want complex double-sided
+ double rx_bw = ((rx_id != 0x0083) && (rx_id != 0x0085)) ? 20.0e6 : 60.0e6;
+ this->get_rx_subtree()->create<double>("bandwidth/value").set(2*rx_bw);
this->get_rx_subtree()->create<meta_range_t>("bandwidth/range")
- .set(freq_range_t(2*20.0e6, 2*20.0e6));
+ .set(freq_range_t(2*rx_bw, 2*rx_bw));
////////////////////////////////////////////////////////////////////
// Register TX properties
////////////////////////////////////////////////////////////////////
- if(get_tx_id() == 0x055) this->get_tx_subtree()->create<std::string>("name").set("SBXv3 TX");
- else if(get_tx_id() == 0x064) this->get_tx_subtree()->create<std::string>("name").set("SBXv4 TX");
- else if(get_tx_id() == 0x066) this->get_tx_subtree()->create<std::string>("name").set("CBX TX");
+ this->get_tx_subtree()->create<device_addr_t>("tune_args").set(device_addr_t());
+
+ boost::uint16_t tx_id = get_tx_id().to_uint16();
+ if(tx_id == 0x0055) this->get_tx_subtree()->create<std::string>("name").set("SBXv3 TX");
+ else if(tx_id == 0x0064) this->get_tx_subtree()->create<std::string>("name").set("SBXv4 TX");
+ else if(tx_id == 0x0066) this->get_tx_subtree()->create<std::string>("name").set("CBX TX");
+ else if(tx_id == 0x0082) this->get_tx_subtree()->create<std::string>("name").set("SBX-120 TX");
+ else if(tx_id == 0x0084) this->get_tx_subtree()->create<std::string>("name").set("CBX-120 TX");
else this->get_tx_subtree()->create<std::string>("name").set("SBX/CBX TX");
this->get_tx_subtree()->create<sensor_value_t>("sensors/lo_locked")
@@ -323,9 +215,12 @@ sbx_xcvr::sbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){
this->get_tx_subtree()->create<std::string>("connection").set("QI");
this->get_tx_subtree()->create<bool>("enabled").set(true); //always enabled
this->get_tx_subtree()->create<bool>("use_lo_offset").set(false);
- this->get_tx_subtree()->create<double>("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided
+
+ //Value of bw low-pass dependent on board, we want complex double-sided
+ double tx_bw = ((tx_id != 0x0082) && (tx_id != 0x0084)) ? 20.0e6 : 60.0e6;
+ this->get_tx_subtree()->create<double>("bandwidth/value").set(2*tx_bw);
this->get_tx_subtree()->create<meta_range_t>("bandwidth/range")
- .set(freq_range_t(2*20.0e6, 2*20.0e6));
+ .set(freq_range_t(2*tx_bw, 2*tx_bw));
//enable the clocks that we need
this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true);
@@ -493,3 +388,4 @@ 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));
}
+