From ff1546f8137f7f92bb250f685561b0c34cc0e053 Mon Sep 17 00:00:00 2001 From: Ben Hilburn Date: Fri, 14 Feb 2014 12:05:07 -0800 Subject: Pushing the bulk of UHD-3.7.0 code. --- host/lib/usrp/dboard/db_cbx.cpp | 6 +++--- host/lib/usrp/dboard/db_sbx_version3.cpp | 8 +++++--- host/lib/usrp/dboard/db_sbx_version4.cpp | 8 +++++--- host/lib/usrp/dboard/db_wbx_version2.cpp | 33 +++++++++++++++++++++++-------- host/lib/usrp/dboard/db_wbx_version3.cpp | 33 +++++++++++++++++++++++-------- host/lib/usrp/dboard/db_wbx_version4.cpp | 34 ++++++++++++++++++++++++-------- 6 files changed, 89 insertions(+), 33 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_cbx.cpp b/host/lib/usrp/dboard/db_cbx.cpp index ae41a7971..78ecd9794 100644 --- a/host/lib/usrp/dboard/db_cbx.cpp +++ b/host/lib/usrp/dboard/db_cbx.cpp @@ -18,7 +18,7 @@ #include "max2870_regs.hpp" #include "db_sbx_common.hpp" - +#include using namespace uhd; using namespace uhd::usrp; @@ -47,14 +47,14 @@ double sbx_xcvr::cbx::set_lo_freq(dboard_iface::unit_t unit, double target_freq) ) % (target_freq/1e6) << std::endl; /* - * If the user sets 'mode_n=int-n' in the tuning args, the user wishes to + * If the user sets 'mode_n=integer' in the tuning args, the user wishes to * tune in Integer-N mode, which can result in better spur * performance on some mixers. The default is fractional tuning. */ property_tree::sptr subtree = (unit == dboard_iface::UNIT_RX) ? self_base->get_rx_subtree() : self_base->get_tx_subtree(); device_addr_t tune_args = subtree->access("tune_args").get(); - bool is_int_n = (tune_args.get("mode_n","") == "int-n"); + bool is_int_n = boost::iequals(tune_args.get("mode_n",""), "integer"); //clip the input target_freq = cbx_freq_range.clip(target_freq); diff --git a/host/lib/usrp/dboard/db_sbx_version3.cpp b/host/lib/usrp/dboard/db_sbx_version3.cpp index ef0126557..463de5e15 100644 --- a/host/lib/usrp/dboard/db_sbx_version3.cpp +++ b/host/lib/usrp/dboard/db_sbx_version3.cpp @@ -20,6 +20,7 @@ #include "db_sbx_common.hpp" #include "../common/adf435x_common.hpp" #include +#include using namespace uhd; using namespace uhd::usrp; @@ -47,14 +48,14 @@ double sbx_xcvr::sbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar ) % (target_freq/1e6) << std::endl; /* - * If the user sets 'mode_n=int-n' in the tuning args, the user wishes to + * If the user sets 'mode_n=integer' in the tuning args, the user wishes to * tune in Integer-N mode, which can result in better spur * performance on some mixers. The default is fractional tuning. */ property_tree::sptr subtree = (unit == dboard_iface::UNIT_RX) ? self_base->get_rx_subtree() : self_base->get_tx_subtree(); device_addr_t tune_args = subtree->access("tune_args").get(); - bool is_int_n = (tune_args.get("mode_n","") == "int-n"); + bool is_int_n = boost::iequals(tune_args.get("mode_n",""), "integer"); //clip the input target_freq = sbx_freq_range.clip(target_freq); @@ -84,6 +85,7 @@ double sbx_xcvr::sbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar 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); + tuning_constraints.feedback_after_divider = true; double actual_freq; adf435x_tuning_settings tuning_settings = tune_adf435x_synth( @@ -102,7 +104,7 @@ double sbx_xcvr::sbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar 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 ? + regs.feedback_select = tuning_constraints.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; diff --git a/host/lib/usrp/dboard/db_sbx_version4.cpp b/host/lib/usrp/dboard/db_sbx_version4.cpp index 6c0cebb4b..ff4e19163 100644 --- a/host/lib/usrp/dboard/db_sbx_version4.cpp +++ b/host/lib/usrp/dboard/db_sbx_version4.cpp @@ -20,6 +20,7 @@ #include "db_sbx_common.hpp" #include "../common/adf435x_common.hpp" #include +#include using namespace uhd; using namespace uhd::usrp; @@ -48,14 +49,14 @@ double sbx_xcvr::sbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar ) % (target_freq/1e6) << std::endl; /* - * If the user sets 'mode_n=int-n' in the tuning args, the user wishes to + * If the user sets 'mode_n=integer' in the tuning args, the user wishes to * tune in Integer-N mode, which can result in better spur * performance on some mixers. The default is fractional tuning. */ property_tree::sptr subtree = (unit == dboard_iface::UNIT_RX) ? self_base->get_rx_subtree() : self_base->get_tx_subtree(); device_addr_t tune_args = subtree->access("tune_args").get(); - bool is_int_n = (tune_args.get("mode_n","") == "int-n"); + bool is_int_n = boost::iequals(tune_args.get("mode_n",""), "integer"); //clip the input target_freq = sbx_freq_range.clip(target_freq); @@ -87,6 +88,7 @@ double sbx_xcvr::sbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar 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); + tuning_constraints.feedback_after_divider = true; double actual_freq; adf435x_tuning_settings tuning_settings = tune_adf435x_synth( @@ -105,7 +107,7 @@ double sbx_xcvr::sbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar 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 ? + regs.feedback_select = tuning_constraints.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; diff --git a/host/lib/usrp/dboard/db_wbx_version2.cpp b/host/lib/usrp/dboard/db_wbx_version2.cpp index 2afdce4cd..c5945483d 100644 --- a/host/lib/usrp/dboard/db_wbx_version2.cpp +++ b/host/lib/usrp/dboard/db_wbx_version2.cpp @@ -30,6 +30,7 @@ #include #include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -169,14 +170,14 @@ double wbx_base::wbx_version2::set_lo_freq(dboard_iface::unit_t unit, double tar ) % (target_freq/1e6) << std::endl; /* - * If the user sets 'mode_n=int-n' in the tuning args, the user wishes to + * If the user sets 'mode_n=integer' in the tuning args, the user wishes to * tune in Integer-N mode, which can result in better spur * performance on some mixers. The default is fractional tuning. */ property_tree::sptr subtree = (unit == dboard_iface::UNIT_RX) ? self_base->get_rx_subtree() : self_base->get_tx_subtree(); device_addr_t tune_args = subtree->access("tune_args").get(); - bool is_int_n = (tune_args.get("mode_n","") == "int-n"); + bool is_int_n = boost::iequals(tune_args.get("mode_n",""), "integer"); //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) static const uhd::dict prescaler_to_min_int_div = map_list_of @@ -193,7 +194,15 @@ double wbx_base::wbx_version2::set_lo_freq(dboard_iface::unit_t unit, double tar (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16) ; - adf4350_regs_t::prescaler_t prescaler = target_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5; + double reference_freq = self_base->get_iface()->get_clock_rate(unit); + //The mixer has a divide-by-2 stage on the LO port so the synthesizer + //frequency must 2x the target frequency + double synth_target_freq = target_freq * 2; + //TODO: Document why the following has to be true + bool div_resync_enabled = (target_freq > reference_freq); + + adf4350_regs_t::prescaler_t prescaler = + synth_target_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5; adf435x_tuning_constraints tuning_constraints; tuning_constraints.force_frac0 = is_int_n; @@ -202,11 +211,17 @@ double wbx_base::wbx_version2::set_lo_freq(dboard_iface::unit_t unit, double tar tuning_constraints.int_range = uhd::range_t(prescaler_to_min_int_div[prescaler], 4095); tuning_constraints.pfd_freq_max = 25e6; tuning_constraints.rf_divider_range = uhd::range_t(1, 16); + //When divider resync is enabled, a 180 deg phase error is introduced when syncing + //multiple WBX boards. Switching to fundamental mode works arounds this issue. + tuning_constraints.feedback_after_divider = div_resync_enabled; - double actual_freq; + double synth_actual_freq = 0; adf435x_tuning_settings tuning_settings = tune_adf435x_synth( - target_freq, self_base->get_iface()->get_clock_rate(unit), - tuning_constraints, actual_freq); + synth_target_freq, reference_freq, tuning_constraints, synth_actual_freq); + + //The mixer has a divide-by-2 stage on the LO port so the synthesizer + //actual_freq must /2 the synth_actual_freq + double actual_freq = synth_actual_freq / 2; //load the register values adf4350_regs_t regs; @@ -222,10 +237,12 @@ double wbx_base::wbx_version2::set_lo_freq(dboard_iface::unit_t unit, double tar 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 ? + regs.feedback_select = tuning_constraints.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.clock_div_mode = div_resync_enabled ? + adf4350_regs_t::CLOCK_DIV_MODE_RESYNC_ENABLE : + adf4350_regs_t::CLOCK_DIV_MODE_FAST_LOCK; 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 ? diff --git a/host/lib/usrp/dboard/db_wbx_version3.cpp b/host/lib/usrp/dboard/db_wbx_version3.cpp index e30d6c665..80ecb426b 100644 --- a/host/lib/usrp/dboard/db_wbx_version3.cpp +++ b/host/lib/usrp/dboard/db_wbx_version3.cpp @@ -29,6 +29,7 @@ #include #include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -200,14 +201,14 @@ double wbx_base::wbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar ) % (target_freq/1e6) << std::endl; /* - * If the user sets 'mode_n=int-n' in the tuning args, the user wishes to + * If the user sets 'mode_n=integer' in the tuning args, the user wishes to * tune in Integer-N mode, which can result in better spur * performance on some mixers. The default is fractional tuning. */ property_tree::sptr subtree = (unit == dboard_iface::UNIT_RX) ? self_base->get_rx_subtree() : self_base->get_tx_subtree(); device_addr_t tune_args = subtree->access("tune_args").get(); - bool is_int_n = (tune_args.get("mode_n","") == "int-n"); + bool is_int_n = boost::iequals(tune_args.get("mode_n",""), "integer"); //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) static const uhd::dict prescaler_to_min_int_div = map_list_of @@ -224,7 +225,15 @@ double wbx_base::wbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16) ; - adf4350_regs_t::prescaler_t prescaler = target_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5; + double reference_freq = self_base->get_iface()->get_clock_rate(unit); + //The mixer has a divide-by-2 stage on the LO port so the synthesizer + //frequency must 2x the target frequency + double synth_target_freq = target_freq * 2; + //TODO: Document why the following has to be true + bool div_resync_enabled = (target_freq > reference_freq); + + adf4350_regs_t::prescaler_t prescaler = + synth_target_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5; adf435x_tuning_constraints tuning_constraints; tuning_constraints.force_frac0 = is_int_n; @@ -233,11 +242,17 @@ double wbx_base::wbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar tuning_constraints.int_range = uhd::range_t(prescaler_to_min_int_div[prescaler], 4095); tuning_constraints.pfd_freq_max = 25e6; tuning_constraints.rf_divider_range = uhd::range_t(1, 16); + //When divider resync is enabled, a 180 deg phase error is introduced when syncing + //multiple WBX boards. Switching to fundamental mode works arounds this issue. + tuning_constraints.feedback_after_divider = div_resync_enabled; - double actual_freq; + double synth_actual_freq = 0; adf435x_tuning_settings tuning_settings = tune_adf435x_synth( - target_freq, self_base->get_iface()->get_clock_rate(unit), - tuning_constraints, actual_freq); + synth_target_freq, reference_freq, tuning_constraints, synth_actual_freq); + + //The mixer has a divide-by-2 stage on the LO port so the synthesizer + //actual_freq must /2 the synth_actual_freq + double actual_freq = synth_actual_freq / 2; //load the register values adf4350_regs_t regs; @@ -253,10 +268,12 @@ double wbx_base::wbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar 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 ? + regs.feedback_select = tuning_constraints.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.clock_div_mode = div_resync_enabled ? + adf4350_regs_t::CLOCK_DIV_MODE_RESYNC_ENABLE : + adf4350_regs_t::CLOCK_DIV_MODE_FAST_LOCK; 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 ? diff --git a/host/lib/usrp/dboard/db_wbx_version4.cpp b/host/lib/usrp/dboard/db_wbx_version4.cpp index dc1ae4df8..80ff3f998 100644 --- a/host/lib/usrp/dboard/db_wbx_version4.cpp +++ b/host/lib/usrp/dboard/db_wbx_version4.cpp @@ -29,6 +29,7 @@ #include #include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -208,14 +209,14 @@ double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar ) % (target_freq/1e6) << std::endl; /* - * If the user sets 'mode_n=int-n' in the tuning args, the user wishes to + * If the user sets 'mode_n=integer' in the tuning args, the user wishes to * tune in Integer-N mode, which can result in better spur * performance on some mixers. The default is fractional tuning. */ property_tree::sptr subtree = (unit == dboard_iface::UNIT_RX) ? self_base->get_rx_subtree() : self_base->get_tx_subtree(); device_addr_t tune_args = subtree->access("tune_args").get(); - bool is_int_n = (tune_args.get("mode_n","") == "int-n"); + bool is_int_n = boost::iequals(tune_args.get("mode_n",""), "integer"); //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) static const uhd::dict prescaler_to_min_int_div = map_list_of @@ -234,7 +235,15 @@ double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar (64, adf4351_regs_t::RF_DIVIDER_SELECT_DIV64) ; - adf4351_regs_t::prescaler_t prescaler = target_freq > 3e9 ? adf4351_regs_t::PRESCALER_8_9 : adf4351_regs_t::PRESCALER_4_5; + double reference_freq = self_base->get_iface()->get_clock_rate(unit); + //The mixer has a divide-by-2 stage on the LO port so the synthesizer + //frequency must 2x the target frequency + double synth_target_freq = target_freq * 2; + //TODO: Document why the following has to be true + bool div_resync_enabled = (target_freq > reference_freq); + + adf4351_regs_t::prescaler_t prescaler = + synth_target_freq > 3e9 ? adf4351_regs_t::PRESCALER_8_9 : adf4351_regs_t::PRESCALER_4_5; adf435x_tuning_constraints tuning_constraints; tuning_constraints.force_frac0 = is_int_n; @@ -243,11 +252,17 @@ double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar tuning_constraints.int_range = uhd::range_t(prescaler_to_min_int_div[prescaler], 4095); tuning_constraints.pfd_freq_max = 25e6; tuning_constraints.rf_divider_range = uhd::range_t(1, 64); + //When divider resync is enabled, a 180 deg phase error is introduced when syncing + //multiple WBX boards. Switching to fundamental mode works arounds this issue. + tuning_constraints.feedback_after_divider = div_resync_enabled; - double actual_freq; + double synth_actual_freq = 0; adf435x_tuning_settings tuning_settings = tune_adf435x_synth( - target_freq, self_base->get_iface()->get_clock_rate(unit), - tuning_constraints, actual_freq); + synth_target_freq, reference_freq, tuning_constraints, synth_actual_freq); + + //The mixer has a divide-by-2 stage on the LO port so the synthesizer + //actual_freq must /2 the synth_actual_freq + double actual_freq = synth_actual_freq / 2; //load the register values adf4351_regs_t regs; @@ -263,10 +278,12 @@ double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar 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 ? + regs.feedback_select = tuning_constraints.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.clock_div_mode = div_resync_enabled ? + adf4351_regs_t::CLOCK_DIV_MODE_RESYNC_ENABLE : + adf4351_regs_t::CLOCK_DIV_MODE_FAST_LOCK; 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 ? @@ -307,5 +324,6 @@ double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar UHD_LOGV(often) << boost::format( "%s tune: actual frequency %f Mhz" ) % board_name.c_str() % (actual_freq/1e6) << std::endl; + return actual_freq; } -- cgit v1.2.3