aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/dboard
diff options
context:
space:
mode:
authorAshish Chaudhari <ashish@ettus.com>2015-10-06 12:47:14 -0700
committerAshish Chaudhari <ashish@ettus.com>2016-02-12 11:13:20 -0800
commitb0ad2ec29f3a1bd5f2980ed1f905dac50f87c21a (patch)
tree43bb34d910823a57bf965637f1eabd8be3f0b9d0 /host/lib/usrp/dboard
parent7c7622c1fe4779c84e7c7149caa6dd08400e2774 (diff)
downloaduhd-b0ad2ec29f3a1bd5f2980ed1f905dac50f87c21a.tar.gz
uhd-b0ad2ec29f3a1bd5f2980ed1f905dac50f87c21a.tar.bz2
uhd-b0ad2ec29f3a1bd5f2980ed1f905dac50f87c21a.zip
adf435x: Refactored ADF435X control code
- Removed adf435x_common and replaced with a real encapsulated interface - Looks similar to the MAX287X code - Updated all DB classes to use the new common code
Diffstat (limited to 'host/lib/usrp/dboard')
-rw-r--r--host/lib/usrp/dboard/db_sbx_common.hpp19
-rw-r--r--host/lib/usrp/dboard/db_sbx_version3.cpp111
-rw-r--r--host/lib/usrp/dboard/db_sbx_version4.cpp122
-rw-r--r--host/lib/usrp/dboard/db_wbx_common.cpp6
-rw-r--r--host/lib/usrp/dboard/db_wbx_common.hpp14
-rw-r--r--host/lib/usrp/dboard/db_wbx_version2.cpp114
-rw-r--r--host/lib/usrp/dboard/db_wbx_version3.cpp114
-rw-r--r--host/lib/usrp/dboard/db_wbx_version4.cpp112
8 files changed, 159 insertions, 453 deletions
diff --git a/host/lib/usrp/dboard/db_sbx_common.hpp b/host/lib/usrp/dboard/db_sbx_common.hpp
index 4800bbd83..974cee114 100644
--- a/host/lib/usrp/dboard/db_sbx_common.hpp
+++ b/host/lib/usrp/dboard/db_sbx_common.hpp
@@ -16,10 +16,15 @@
//
#include <uhd/types/device_addr.hpp>
-
-#include "adf435x_common.hpp"
+#include "adf435x.hpp"
#include "max287x.hpp"
+// LO Related
+#define ADF435X_CE (1 << 3)
+#define ADF435X_PDBRF (1 << 2)
+#define ADF435X_MUXOUT (1 << 1) // INPUT!!!
+#define LOCKDET_MASK (1 << 0) // INPUT!!!
+
// Common IO Pins
#define LO_LPF_EN (1 << 15)
@@ -36,6 +41,8 @@
#define RX_LED_LD (1 << 6) // LED for RX Lock Detect
#define DIS_POWER_RX (1 << 5) // on UNIT_RX, 0 powers up RX
#define RX_DISABLE (1 << 4) // on UNIT_RX, 1 disables RX Mixer and Baseband
+#define RX_ATTN_SHIFT 8 //lsb of RX Attenuator Control
+#define RX_ATTN_MASK (63 << RX_ATTN_SHIFT) //valid bits of RX Attenuator Control
// TX Attenuator Pins
#define TX_ATTN_SHIFT 8 // lsb of TX Attenuator Control
@@ -190,6 +197,10 @@ protected:
/*! This is the registered instance of the wrapper class, sbx_base. */
sbx_xcvr *self_base;
+ private:
+ adf435x_iface::sptr _txlo;
+ adf435x_iface::sptr _rxlo;
+ void write_lo_regs(dboard_iface::unit_t unit, const std::vector<boost::uint32_t> &regs);
};
/*!
@@ -206,6 +217,10 @@ protected:
/*! This is the registered instance of the wrapper class, sbx_base. */
sbx_xcvr *self_base;
+ private:
+ adf435x_iface::sptr _txlo;
+ adf435x_iface::sptr _rxlo;
+ void write_lo_regs(dboard_iface::unit_t unit, const std::vector<boost::uint32_t> &regs);
};
/*!
diff --git a/host/lib/usrp/dboard/db_sbx_version3.cpp b/host/lib/usrp/dboard/db_sbx_version3.cpp
index b848097d1..76ad7b04f 100644
--- a/host/lib/usrp/dboard/db_sbx_version3.cpp
+++ b/host/lib/usrp/dboard/db_sbx_version3.cpp
@@ -16,9 +16,7 @@
//
-#include "adf4350_regs.hpp"
#include "db_sbx_common.hpp"
-#include "../common/adf435x_common.hpp"
#include <uhd/types/tune_request.hpp>
#include <boost/algorithm/string.hpp>
@@ -32,12 +30,21 @@ using namespace boost::assign;
sbx_xcvr::sbx_version3::sbx_version3(sbx_xcvr *_self_sbx_xcvr) {
//register the handle to our base SBX class
self_base = _self_sbx_xcvr;
+ _txlo = adf435x_iface::make_adf4350(boost::bind(&sbx_xcvr::sbx_version3::write_lo_regs, this, dboard_iface::UNIT_TX, _1));
+ _rxlo = adf435x_iface::make_adf4350(boost::bind(&sbx_xcvr::sbx_version3::write_lo_regs, this, dboard_iface::UNIT_RX, _1));
}
sbx_xcvr::sbx_version3::~sbx_version3(void){
/* NOP */
}
+void sbx_xcvr::sbx_version3::write_lo_regs(dboard_iface::unit_t unit, const std::vector<boost::uint32_t> &regs)
+{
+ BOOST_FOREACH(boost::uint32_t reg, regs)
+ {
+ self_base->get_iface()->write_spi(unit, spi_config_t::EDGE_RISE, reg, 32);
+ }
+}
/***********************************************************************
* Tuning
@@ -57,95 +64,27 @@ double sbx_xcvr::sbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar
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");
- //clip the input
- target_freq = sbx_freq_range.clip(target_freq);
-
- //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
- (0,23) //adf4350_regs_t::PRESCALER_4_5
- (1,75) //adf4350_regs_t::PRESCALER_8_9
- ;
-
- //map rf divider select output dividers to enums
- static const uhd::dict<int, adf4350_regs_t::rf_divider_select_t> rfdivsel_to_enum = map_list_of
- (1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1)
- (2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2)
- (4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4)
- (8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8)
- (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16)
- ;
-
- //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;
-
- 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); //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;
+ //Select the LO
+ adf435x_iface::sptr& lo_iface = unit == dboard_iface::UNIT_RX ? _rxlo : _txlo;
+ lo_iface->set_feedback_select(adf435x_iface::FB_SEL_DIVIDED);
+ lo_iface->set_reference_freq(self_base->get_iface()->get_clock_rate(unit));
- 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);
+ //Use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler)
+ lo_iface->set_prescaler(target_freq > 3e9 ? adf435x_iface::PRESCALER_8_9 : adf435x_iface::PRESCALER_4_5);
- //load the register values
- adf4350_regs_t regs;
+ //Configure the LO
+ double actual_freq = 0.0;
+ actual_freq = lo_iface->set_frequency(sbx_freq_range.clip(target_freq), is_int_n);
- if ((unit == dboard_iface::UNIT_TX) and (actual_freq == sbx_tx_lo_2dbm.clip(actual_freq)))
- regs.output_power = adf4350_regs_t::OUTPUT_POWER_2DBM;
- else
- regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM;
-
- 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 ?
- 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];
- regs.ldf = is_int_n ?
- adf4350_regs_t::LDF_INT_N :
- adf4350_regs_t::LDF_FRAC_N;
-
- //reset the N and R counter
- regs.counter_reset = adf4350_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 = adf4350_regs_t::COUNTER_RESET_DISABLED;
-
- //write the registers
- //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0)
- int addr;
-
- for(addr=5; addr>=0; addr--){
- UHD_LOGV(often) << boost::format(
- "SBX SPI Reg (0x%02x): 0x%08x"
- ) % 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_TX) and (actual_freq == sbx_tx_lo_2dbm.clip(actual_freq))) {
+ lo_iface->set_output_power(adf435x_iface::OUTPUT_POWER_2DBM);
+ } else {
+ lo_iface->set_output_power(adf435x_iface::OUTPUT_POWER_5DBM);
}
- //return the actual frequency
- UHD_LOGV(often) << boost::format(
- "SBX tune: actual frequency %f MHz"
- ) % (actual_freq/1e6) << std::endl;
+ //Write to hardware
+ lo_iface->commit();
+
return actual_freq;
}
diff --git a/host/lib/usrp/dboard/db_sbx_version4.cpp b/host/lib/usrp/dboard/db_sbx_version4.cpp
index 8f7e747bc..639bce250 100644
--- a/host/lib/usrp/dboard/db_sbx_version4.cpp
+++ b/host/lib/usrp/dboard/db_sbx_version4.cpp
@@ -16,9 +16,7 @@
//
-#include "adf4351_regs.hpp"
#include "db_sbx_common.hpp"
-#include "../common/adf435x_common.hpp"
#include <uhd/types/tune_request.hpp>
#include <boost/algorithm/string.hpp>
@@ -32,6 +30,8 @@ using namespace boost::assign;
sbx_xcvr::sbx_version4::sbx_version4(sbx_xcvr *_self_sbx_xcvr) {
//register the handle to our base SBX class
self_base = _self_sbx_xcvr;
+ _txlo = adf435x_iface::make_adf4351(boost::bind(&sbx_xcvr::sbx_version4::write_lo_regs, this, dboard_iface::UNIT_TX, _1));
+ _rxlo = adf435x_iface::make_adf4351(boost::bind(&sbx_xcvr::sbx_version4::write_lo_regs, this, dboard_iface::UNIT_RX, _1));
}
@@ -39,6 +39,14 @@ sbx_xcvr::sbx_version4::~sbx_version4(void){
/* NOP */
}
+void sbx_xcvr::sbx_version4::write_lo_regs(dboard_iface::unit_t unit, const std::vector<boost::uint32_t> &regs)
+{
+ BOOST_FOREACH(boost::uint32_t reg, regs)
+ {
+ self_base->get_iface()->write_spi(unit, spi_config_t::EDGE_RISE, reg, 32);
+ }
+}
+
/***********************************************************************
* Tuning
@@ -58,99 +66,27 @@ double sbx_xcvr::sbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar
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");
- //clip the input
- target_freq = sbx_freq_range.clip(target_freq);
-
- //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
- (0,23) //adf4351_regs_t::PRESCALER_4_5
- (1,75) //adf4351_regs_t::PRESCALER_8_9
- ;
-
- //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)
- ;
-
- //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler)
- adf4351_regs_t::prescaler_t prescaler = target_freq > 3.6e9 ? adf4351_regs_t::PRESCALER_8_9 : adf4351_regs_t::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); //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(
- target_freq, self_base->get_iface()->get_clock_rate(unit),
- tuning_constraints, actual_freq);
-
- //load the register values
- adf4351_regs_t regs;
-
- if ((unit == dboard_iface::UNIT_TX) and (actual_freq == sbx_tx_lo_2dbm.clip(actual_freq)))
- regs.output_power = adf4351_regs_t::OUTPUT_POWER_2DBM;
- else
- regs.output_power = adf4351_regs_t::OUTPUT_POWER_5DBM;
-
- 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 = 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];
- 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 == 0x0083) ? "SBX-120" : "SBX";
- 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
- );
+ //Select the LO
+ adf435x_iface::sptr& lo_iface = unit == dboard_iface::UNIT_RX ? _rxlo : _txlo;
+ lo_iface->set_feedback_select(adf435x_iface::FB_SEL_DIVIDED);
+ lo_iface->set_reference_freq(self_base->get_iface()->get_clock_rate(unit));
+
+ //Use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler)
+ lo_iface->set_prescaler(target_freq > 3.6e9 ? adf435x_iface::PRESCALER_8_9 : adf435x_iface::PRESCALER_4_5);
+
+ //Configure the LO
+ double actual_freq = 0.0;
+ actual_freq = lo_iface->set_frequency(sbx_freq_range.clip(target_freq), is_int_n);
+
+ if ((unit == dboard_iface::UNIT_TX) and (actual_freq == sbx_tx_lo_2dbm.clip(actual_freq))) {
+ lo_iface->set_output_power(adf435x_iface::OUTPUT_POWER_2DBM);
+ } else {
+ lo_iface->set_output_power(adf435x_iface::OUTPUT_POWER_5DBM);
}
- //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;
}
diff --git a/host/lib/usrp/dboard/db_wbx_common.cpp b/host/lib/usrp/dboard/db_wbx_common.cpp
index 0a7e1afa2..6539e798a 100644
--- a/host/lib/usrp/dboard/db_wbx_common.cpp
+++ b/host/lib/usrp/dboard/db_wbx_common.cpp
@@ -156,3 +156,9 @@ sensor_value_t wbx_base::get_locked(dboard_iface::unit_t unit){
const bool locked = (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0;
return sensor_value_t("LO", locked, "locked", "unlocked");
}
+
+void wbx_base::wbx_versionx::write_lo_regs(dboard_iface::unit_t unit, const std::vector<boost::uint32_t> &regs) {
+ BOOST_FOREACH(boost::uint32_t reg, regs) {
+ self_base->get_iface()->write_spi(unit, spi_config_t::EDGE_RISE, reg, 32);
+ }
+}
diff --git a/host/lib/usrp/dboard/db_wbx_common.hpp b/host/lib/usrp/dboard/db_wbx_common.hpp
index 6a4224048..8a003fc8c 100644
--- a/host/lib/usrp/dboard/db_wbx_common.hpp
+++ b/host/lib/usrp/dboard/db_wbx_common.hpp
@@ -19,8 +19,13 @@
#define INCLUDED_LIBUHD_USRP_DBOARD_DB_WBX_COMMON_HPP
#include <uhd/types/device_addr.hpp>
+#include "adf435x.hpp"
-#include "../common/adf435x_common.hpp"
+// LO Related
+#define ADF435X_CE (1 << 3)
+#define ADF435X_PDBRF (1 << 2)
+#define ADF435X_MUXOUT (1 << 1) // INPUT!!!
+#define LOCKDET_MASK (1 << 0) // INPUT!!!
// TX IO Pins
#define TX_PUP_5V (1 << 7) // enables 5.0V power supply
@@ -40,6 +45,9 @@
#define TX_ATTN_1 (1 << 1)
#define TX_ATTN_MASK (TX_ATTN_16|TX_ATTN_8|TX_ATTN_4|TX_ATTN_2|TX_ATTN_1) // valid bits of TX Attenuator Control
+#define RX_ATTN_SHIFT 8 //lsb of RX Attenuator Control
+#define RX_ATTN_MASK (63 << RX_ATTN_SHIFT) //valid bits of RX Attenuator Control
+
// Mixer functions
#define TX_MIXER_ENB (TXMOD_EN|ADF435X_PDBRF) // for v3, TXMOD_EN tied to ADF435X_PDBRF rather than separate
#define TX_MIXER_DIS 0
@@ -142,6 +150,10 @@ protected:
property_tree::sptr get_tx_subtree(void){
return self_base->get_tx_subtree();
}
+
+ adf435x_iface::sptr _txlo;
+ adf435x_iface::sptr _rxlo;
+ void write_lo_regs(dboard_iface::unit_t unit, const std::vector<boost::uint32_t> &regs);
};
diff --git a/host/lib/usrp/dboard/db_wbx_version2.cpp b/host/lib/usrp/dboard/db_wbx_version2.cpp
index d175ea000..18dc383b7 100644
--- a/host/lib/usrp/dboard/db_wbx_version2.cpp
+++ b/host/lib/usrp/dboard/db_wbx_version2.cpp
@@ -16,8 +16,6 @@
//
#include "db_wbx_common.hpp"
-#include "adf4350_regs.hpp"
-#include "../common/adf435x_common.hpp"
#include <uhd/types/tune_request.hpp>
#include <uhd/utils/log.hpp>
#include <uhd/types/dict.hpp>
@@ -77,6 +75,8 @@ static double tx_pga0_gain_to_dac_volts(double &gain){
wbx_base::wbx_version2::wbx_version2(wbx_base *_self_wbx_base) {
//register our handle on the primary wbx_base instance
self_base = _self_wbx_base;
+ _txlo = adf435x_iface::make_adf4350(boost::bind(&wbx_base::wbx_versionx::write_lo_regs, this, dboard_iface::UNIT_TX, _1));
+ _rxlo = adf435x_iface::make_adf4350(boost::bind(&wbx_base::wbx_versionx::write_lo_regs, this, dboard_iface::UNIT_RX, _1));
////////////////////////////////////////////////////////////////////
// Register RX properties
@@ -178,108 +178,42 @@ double wbx_base::wbx_version2::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
- (0,23) //adf4350_regs_t::PRESCALER_4_5
- (1,75) //adf4350_regs_t::PRESCALER_8_9
- ;
-
- //map rf divider select output dividers to enums
- static const uhd::dict<int, adf4350_regs_t::rf_divider_select_t> rfdivsel_to_enum = map_list_of
- (1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1)
- (2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2)
- (4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4)
- (8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8)
- (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16)
- ;
+ //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
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;
- 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, 16);
+
+ //Use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler)
+ lo_iface->set_prescaler(synth_target_freq > 3e9 ?
+ adf435x_iface::PRESCALER_8_9 : adf435x_iface::PRESCALER_4_5);
+
//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;
+ //TODO: Document why the following has to be true
+ lo_iface->set_feedback_select((target_freq > reference_freq) ?
+ 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
- adf4350_regs_t regs;
-
- if (unit == dboard_iface::UNIT_RX)
- regs.output_power = (actual_freq == wbx_rx_lo_5dbm.clip(actual_freq)) ? adf4350_regs_t::OUTPUT_POWER_5DBM
- : adf4350_regs_t::OUTPUT_POWER_2DBM;
- else
- regs.output_power = (actual_freq == wbx_tx_lo_5dbm.clip(actual_freq)) ? adf4350_regs_t::OUTPUT_POWER_5DBM
- : adf4350_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 ?
- adf4350_regs_t::FEEDBACK_SELECT_DIVIDED :
- adf4350_regs_t::FEEDBACK_SELECT_FUNDAMENTAL;
- 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 ?
- 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];
- regs.ldf = is_int_n ?
- adf4350_regs_t::LDF_INT_N :
- adf4350_regs_t::LDF_FRAC_N;
-
- //reset the N and R counter
- regs.counter_reset = adf4350_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 = adf4350_regs_t::COUNTER_RESET_DISABLED;
-
- //write the registers
- //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0)
- int addr;
-
- for(addr=5; addr>=0; addr--){
- UHD_LOGV(often) << boost::format(
- "WBX SPI Reg (0x%02x): 0x%08x"
- ) % 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(
- "WBX tune: actual frequency %f MHz"
- ) % (actual_freq/1e6) << std::endl;
+ //Write to hardware
+ lo_iface->commit();
+
return actual_freq;
}
diff --git a/host/lib/usrp/dboard/db_wbx_version3.cpp b/host/lib/usrp/dboard/db_wbx_version3.cpp
index b898a2fca..2add8d25d 100644
--- a/host/lib/usrp/dboard/db_wbx_version3.cpp
+++ b/host/lib/usrp/dboard/db_wbx_version3.cpp
@@ -16,8 +16,6 @@
//
#include "db_wbx_common.hpp"
-#include "adf4350_regs.hpp"
-#include "../common/adf435x_common.hpp"
#include <uhd/utils/log.hpp>
#include <uhd/types/dict.hpp>
#include <uhd/types/ranges.hpp>
@@ -82,6 +80,8 @@ static int tx_pga0_gain_to_iobits(double &gain){
wbx_base::wbx_version3::wbx_version3(wbx_base *_self_wbx_base) {
//register our handle on the primary wbx_base instance
self_base = _self_wbx_base;
+ _txlo = adf435x_iface::make_adf4350(boost::bind(&wbx_base::wbx_versionx::write_lo_regs, this, dboard_iface::UNIT_TX, _1));
+ _rxlo = adf435x_iface::make_adf4350(boost::bind(&wbx_base::wbx_versionx::write_lo_regs, this, dboard_iface::UNIT_RX, _1));
////////////////////////////////////////////////////////////////////
// Register RX properties
@@ -209,108 +209,42 @@ double wbx_base::wbx_version3::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
- (0,23) //adf4350_regs_t::PRESCALER_4_5
- (1,75) //adf4350_regs_t::PRESCALER_8_9
- ;
-
- //map rf divider select output dividers to enums
- static const uhd::dict<int, adf4350_regs_t::rf_divider_select_t> rfdivsel_to_enum = map_list_of
- (1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1)
- (2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2)
- (4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4)
- (8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8)
- (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16)
- ;
+ //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
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;
- 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, 16);
+
+ //Use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler)
+ lo_iface->set_prescaler(synth_target_freq > 3e9 ?
+ adf435x_iface::PRESCALER_8_9 : adf435x_iface::PRESCALER_4_5);
+
//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;
+ //TODO: Document why the following has to be true
+ lo_iface->set_feedback_select((target_freq > reference_freq) ?
+ 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
- adf4350_regs_t regs;
-
- if (unit == dboard_iface::UNIT_RX)
- regs.output_power = (actual_freq == wbx_rx_lo_5dbm.clip(actual_freq)) ? adf4350_regs_t::OUTPUT_POWER_5DBM
- : adf4350_regs_t::OUTPUT_POWER_2DBM;
- else
- regs.output_power = (actual_freq == wbx_tx_lo_5dbm.clip(actual_freq)) ? adf4350_regs_t::OUTPUT_POWER_5DBM
- : adf4350_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 ?
- adf4350_regs_t::FEEDBACK_SELECT_DIVIDED :
- adf4350_regs_t::FEEDBACK_SELECT_FUNDAMENTAL;
- 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 ?
- 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];
- regs.ldf = is_int_n ?
- adf4350_regs_t::LDF_INT_N :
- adf4350_regs_t::LDF_FRAC_N;
-
- //reset the N and R counter
- regs.counter_reset = adf4350_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 = adf4350_regs_t::COUNTER_RESET_DISABLED;
-
- //write the registers
- //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0)
- int addr;
-
- for(addr=5; addr>=0; addr--){
- UHD_LOGV(often) << boost::format(
- "WBX SPI Reg (0x%02x): 0x%08x"
- ) % 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(
- "WBX tune: actual frequency %f MHz"
- ) % (actual_freq/1e6) << std::endl;
+ //Write to hardware
+ lo_iface->commit();
+
return actual_freq;
}
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;
}