aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/dboard/db_wbx_version4.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/dboard/db_wbx_version4.cpp')
-rw-r--r--host/lib/usrp/dboard/db_wbx_version4.cpp112
1 files changed, 21 insertions, 91 deletions
diff --git a/host/lib/usrp/dboard/db_wbx_version4.cpp b/host/lib/usrp/dboard/db_wbx_version4.cpp
index 721f5ed45..dc351af1d 100644
--- a/host/lib/usrp/dboard/db_wbx_version4.cpp
+++ b/host/lib/usrp/dboard/db_wbx_version4.cpp
@@ -16,8 +16,6 @@
//
#include "db_wbx_common.hpp"
-#include "adf4351_regs.hpp"
-#include "../common/adf435x_common.hpp"
#include <uhd/utils/log.hpp>
#include <uhd/types/dict.hpp>
#include <uhd/types/ranges.hpp>
@@ -83,6 +81,8 @@ static int tx_pga0_gain_to_iobits(double &gain){
wbx_base::wbx_version4::wbx_version4(wbx_base *_self_wbx_base) {
//register our handle on the primary wbx_base instance
self_base = _self_wbx_base;
+ _txlo = adf435x_iface::make_adf4351(boost::bind(&wbx_base::wbx_versionx::write_lo_regs, this, dboard_iface::UNIT_TX, _1));
+ _rxlo = adf435x_iface::make_adf4351(boost::bind(&wbx_base::wbx_versionx::write_lo_regs, this, dboard_iface::UNIT_RX, _1));
////////////////////////////////////////////////////////////////////
// Register RX properties
@@ -217,116 +217,46 @@ double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar
: self_base->get_tx_subtree();
device_addr_t tune_args = subtree->access<device_addr_t>("tune_args").get();
bool is_int_n = boost::iequals(tune_args.get("mode_n",""), "integer");
+ double reference_freq = self_base->get_iface()->get_clock_rate(unit);
- //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler)
- static const uhd::dict<int, int> prescaler_to_min_int_div = map_list_of
- (adf4351_regs_t::PRESCALER_4_5, 23)
- (adf4351_regs_t::PRESCALER_8_9, 75)
- ;
-
- //map rf divider select output dividers to enums
- static const uhd::dict<int, adf4351_regs_t::rf_divider_select_t> rfdivsel_to_enum = map_list_of
- (1, adf4351_regs_t::RF_DIVIDER_SELECT_DIV1)
- (2, adf4351_regs_t::RF_DIVIDER_SELECT_DIV2)
- (4, adf4351_regs_t::RF_DIVIDER_SELECT_DIV4)
- (8, adf4351_regs_t::RF_DIVIDER_SELECT_DIV8)
- (16, adf4351_regs_t::RF_DIVIDER_SELECT_DIV16)
- (32, adf4351_regs_t::RF_DIVIDER_SELECT_DIV32)
- (64, adf4351_regs_t::RF_DIVIDER_SELECT_DIV64)
- ;
+ //Select the LO
+ adf435x_iface::sptr& lo_iface = unit == dboard_iface::UNIT_RX ? _rxlo : _txlo;
+ lo_iface->set_reference_freq(reference_freq);
- 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. This introduces a 180 degree phase
//ambiguity when trying to synchronize the phase of multiple boards.
double synth_target_freq = target_freq * 2;
- adf4351_regs_t::prescaler_t prescaler =
- synth_target_freq > 3.6e9 ? adf4351_regs_t::PRESCALER_8_9 : adf4351_regs_t::PRESCALER_4_5;
+ //Use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler)
+ lo_iface->set_prescaler(synth_target_freq > 3.6e9 ?
+ adf435x_iface::PRESCALER_8_9 : adf435x_iface::PRESCALER_4_5);
- adf435x_tuning_constraints tuning_constraints;
- tuning_constraints.force_frac0 = is_int_n;
- 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);
- tuning_constraints.pfd_freq_max = 25e6;
- tuning_constraints.rf_divider_range = uhd::range_t(1, 64);
//The feedback of the divided frequency must be disabled whenever the target frequency
//divided by the minimum PFD frequency cannot meet the minimum integer divider (N) value.
//If it is disabled, additional phase ambiguity will be introduced. With a minimum PFD
//frequency of 10 MHz, synthesizer frequencies below 230 MHz (LO frequencies below 115 MHz)
//will have too much ambiguity to synchronize.
- tuning_constraints.feedback_after_divider =
- (int(synth_target_freq / 10e6) >= prescaler_to_min_int_div[prescaler]);
+ lo_iface->set_feedback_select(
+ (int(synth_target_freq / 10e6) >= lo_iface->get_int_range().start() ?
+ adf435x_iface::FB_SEL_DIVIDED : adf435x_iface::FB_SEL_FUNDAMENTAL));
- double synth_actual_freq = 0;
- adf435x_tuning_settings tuning_settings = tune_adf435x_synth(
- synth_target_freq, reference_freq, tuning_constraints, synth_actual_freq);
+ double synth_actual_freq = lo_iface->set_frequency(synth_target_freq, is_int_n);
//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;
-
- if (unit == dboard_iface::UNIT_RX)
- regs.output_power = (actual_freq == wbx_rx_lo_5dbm.clip(actual_freq)) ? adf4351_regs_t::OUTPUT_POWER_5DBM
- : adf4351_regs_t::OUTPUT_POWER_2DBM;
- else
- regs.output_power = (actual_freq == wbx_tx_lo_5dbm.clip(actual_freq)) ? adf4351_regs_t::OUTPUT_POWER_5DBM
- : adf4351_regs_t::OUTPUT_POWER_M1DBM;
-
- 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_constraints.feedback_after_divider ?
- adf4351_regs_t::FEEDBACK_SELECT_DIVIDED :
- adf4351_regs_t::FEEDBACK_SELECT_FUNDAMENTAL;
- regs.clock_div_mode = tuning_constraints.feedback_after_divider ?
- 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 ?
- 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];
- regs.ldf = is_int_n ?
- adf4351_regs_t::LDF_INT_N :
- adf4351_regs_t::LDF_FRAC_N;
-
- //reset the N and R counter
- regs.counter_reset = adf4351_regs_t::COUNTER_RESET_ENABLED;
- self_base->get_iface()->write_spi(unit, spi_config_t::EDGE_RISE, regs.get_reg(2), 32);
- regs.counter_reset = adf4351_regs_t::COUNTER_RESET_DISABLED;
-
- //write the registers
- //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0)
- int addr;
-
- boost::uint16_t rx_id = self_base->get_rx_id().to_uint16();
- std::string board_name = (rx_id == 0x0081) ? "WBX-120" : "WBX";
- for(addr=5; addr>=0; addr--){
- UHD_LOGV(often) << boost::format(
- "%s SPI Reg (0x%02x): 0x%08x"
- ) % board_name.c_str() % addr % regs.get_reg(addr) << std::endl;
- self_base->get_iface()->write_spi(
- unit, spi_config_t::EDGE_RISE,
- regs.get_reg(addr), 32
- );
+ if (unit == dboard_iface::UNIT_RX) {
+ lo_iface->set_output_power((actual_freq == wbx_rx_lo_5dbm.clip(actual_freq)) ?
+ adf435x_iface::OUTPUT_POWER_5DBM : adf435x_iface::OUTPUT_POWER_2DBM);
+ } else {
+ lo_iface->set_output_power((actual_freq == wbx_tx_lo_5dbm.clip(actual_freq)) ?
+ adf435x_iface::OUTPUT_POWER_5DBM : adf435x_iface::OUTPUT_POWER_M1DBM);
}
- //return the actual frequency
- UHD_LOGV(often) << boost::format(
- "%s tune: actual frequency %f MHz"
- ) % board_name.c_str() % (actual_freq/1e6) << std::endl;
+ //Write to hardware
+ lo_iface->commit();
return actual_freq;
}