aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
authormichael-west <michael.west@ettus.com>2021-01-12 11:21:49 -0800
committerAaron Rossetto <aaron.rossetto@ni.com>2021-02-04 13:48:46 -0600
commit6a5807ecab1c8580b2b187da441017735189fd53 (patch)
treeca52e938344a89c2cf21e3183813b3a6bb3b887a /host/lib
parente115e046eca7b7485edb59abe794b24290195c75 (diff)
downloaduhd-6a5807ecab1c8580b2b187da441017735189fd53.tar.gz
uhd-6a5807ecab1c8580b2b187da441017735189fd53.tar.bz2
uhd-6a5807ecab1c8580b2b187da441017735189fd53.zip
TwinRX: Spur cleanup
- Reduce FRAC2 and MOD2 values on ADF5356 - Add write to register 10 and delay during retune on ADF5356 - Make negative bleed conditional on integer or fractional N mode for ADF5356 - Tune unused LOs out of band to remove interference Signed-off-by: michael-west <michael.west@ettus.com>
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/include/uhdlib/usrp/common/adf535x.hpp17
-rw-r--r--host/lib/usrp/dboard/twinrx/twinrx_ctrl.cpp10
-rw-r--r--host/lib/usrp/dboard/twinrx/twinrx_experts.cpp33
3 files changed, 49 insertions, 11 deletions
diff --git a/host/lib/include/uhdlib/usrp/common/adf535x.hpp b/host/lib/include/uhdlib/usrp/common/adf535x.hpp
index 736018da1..61dd88451 100644
--- a/host/lib/include/uhdlib/usrp/common/adf535x.hpp
+++ b/host/lib/include/uhdlib/usrp/common/adf535x.hpp
@@ -112,6 +112,7 @@ public:
, _wait_fn(std::move(wait_fn))
, _regs()
, _rewrite_regs(true)
+ , _neg_bleed_changed(false)
, _wait_time_us(0)
, _ref_freq(0.0)
, _pfd_freq(0.0)
@@ -350,6 +351,7 @@ private: // Members
wait_fn_t _wait_fn;
adf535x_regs_t _regs;
bool _rewrite_regs;
+ bool _neg_bleed_changed;
uint32_t _wait_time_us;
double _ref_freq;
double _pfd_freq;
@@ -602,6 +604,14 @@ inline double adf535x_impl<adf5356_regs_t>::_set_frequency(
_regs.mod2_msb = narrow_cast<uint16_t>(MOD2 >> 14);
_regs.phase_24_bit = 0;
+ auto negative_bleed = FRAC1 != 0 or FRAC2 != 0 ?
+ adf5356_regs_t::NEGATIVE_BLEED_ENABLED :
+ adf5356_regs_t::NEGATIVE_BLEED_DISABLED;
+ if (negative_bleed != _regs.negative_bleed) {
+ _regs.negative_bleed = negative_bleed;
+ _neg_bleed_changed = true;
+ }
+
if (flush)
commit();
return coerced_out_freq;
@@ -630,9 +640,14 @@ inline void adf535x_impl<adf5356_regs_t>::_commit()
} else {
// Frequency update sequence from data sheet
_write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(13)));
- _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(6)));
+ _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(10)));
+ if (_neg_bleed_changed) {
+ _write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(6)));
+ }
_write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(2)));
_write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(1)));
+ _wait_fn(_wait_time_us);
_write_fn(addr_vtr_t(ONE_REG, _regs.get_reg(0)));
}
+ _neg_bleed_changed = false;
}
diff --git a/host/lib/usrp/dboard/twinrx/twinrx_ctrl.cpp b/host/lib/usrp/dboard/twinrx/twinrx_ctrl.cpp
index 3686f4348..315861cd9 100644
--- a/host/lib/usrp/dboard/twinrx/twinrx_ctrl.cpp
+++ b/host/lib/usrp/dboard/twinrx/twinrx_ctrl.cpp
@@ -121,7 +121,7 @@ public:
[this](uint32_t microseconds) {
_db_iface->sleep(boost::chrono::microseconds(microseconds));
});
- _lo1_iface[i]->set_pfd_freq(TWINRX_REV_C_PFD_FREQ);
+ _lo1_pfd_freq = TWINRX_REV_C_PFD_FREQ;
} else {
_lo1_iface[i] = adf535x_iface::make_adf5355(
[this](const std::vector<uint32_t>& regs) {
@@ -130,13 +130,14 @@ public:
[this](uint32_t microseconds) {
_db_iface->sleep(boost::chrono::microseconds(microseconds));
});
- _lo1_iface[i]->set_pfd_freq(TWINRX_REV_AB_PFD_FREQ);
+ _lo1_pfd_freq = TWINRX_REV_AB_PFD_FREQ;
}
+ _lo1_iface[i]->set_pfd_freq(_lo1_pfd_freq);
_lo1_iface[i]->set_output_power(adf535x_iface::OUTPUT_POWER_5DBM);
_lo1_iface[i]->set_reference_freq(
_db_iface->get_clock_rate(dboard_iface::UNIT_TX));
_lo1_iface[i]->set_muxout_mode(adf535x_iface::MUXOUT_DLD);
- _lo1_iface[i]->set_frequency(3e9, 1.0e3);
+ _lo1_iface[i]->set_frequency(3e9, _lo1_pfd_freq / 2);
// LO2
_lo2_iface[i] =
@@ -561,7 +562,7 @@ public:
double set_lo1_synth_freq(channel_t ch, double freq, bool commit = true)
{
boost::lock_guard<boost::mutex> lock(_mutex);
- static const double RESOLUTION = 1e3;
+ static const double RESOLUTION = _lo1_pfd_freq / 2;
double coerced_freq = 0.0;
if (ch == CH1 or ch == BOTH) {
@@ -852,6 +853,7 @@ private: // Members
twinrx_gpio::sptr _gpio_iface;
twinrx_cpld_regmap::sptr _cpld_regs;
spi_config_t _spi_config;
+ double _lo1_pfd_freq;
adf535x_iface::sptr _lo1_iface[NUM_CHANS];
adf435x_iface::sptr _lo2_iface[NUM_CHANS];
lo_source_t _lo1_src[NUM_CHANS];
diff --git a/host/lib/usrp/dboard/twinrx/twinrx_experts.cpp b/host/lib/usrp/dboard/twinrx/twinrx_experts.cpp
index d196d99e2..8d3ba591b 100644
--- a/host/lib/usrp/dboard/twinrx/twinrx_experts.cpp
+++ b/host/lib/usrp/dboard/twinrx/twinrx_experts.cpp
@@ -617,7 +617,10 @@ void twinrx_settings_expert::_resolve_lox_freq(lo_stage_t lo_stage,
bool hopping_enabled)
{
if (ch0_lo_source == twinrx_ctrl::LO_EXTERNAL) {
- // If the LO is external then we don't need to program any synthesizers
+ if (synth0_mapping != MAPPING_CH1) {
+ // Tune the internal LO away to avoid interference
+ _set_lox_synth_freq(lo_stage, twinrx_ctrl::CH1, ch0_freq_d + 100e6);
+ }
ch0_freq_c = ch0_freq_d;
} else {
// When in hopping mode, only attempt to write the LO frequency if it is actually
@@ -631,15 +634,24 @@ void twinrx_settings_expert::_resolve_lox_freq(lo_stage_t lo_stage,
ch0_freq_c = _set_lox_synth_freq(lo_stage, twinrx_ctrl::CH2, ch0_freq_d);
} else if (synth0_mapping == MAPPING_SHARED or synth1_mapping == MAPPING_SHARED) {
// If any synthesizer is being shared then we are not in hopping mode
+ // Tune the LO being shared
twinrx_ctrl::channel_t ch =
(synth0_mapping == MAPPING_SHARED) ? twinrx_ctrl::CH1 : twinrx_ctrl::CH2;
ch0_freq_c = _set_lox_synth_freq(lo_stage, ch, ch0_freq_d);
ch1_freq_c = ch0_freq_c;
+
+ // Tune the synthesizer of the other channel away to avoid interference
+ twinrx_ctrl::channel_t other_ch =
+ (synth0_mapping == MAPPING_SHARED) ? twinrx_ctrl::CH2 : twinrx_ctrl::CH1;
+ _set_lox_synth_freq(lo_stage, other_ch, ch0_freq_d + 100e6);
}
}
if (ch1_lo_source == twinrx_ctrl::LO_EXTERNAL) {
- // If the LO is external then we don't need to program any synthesizers
+ if (synth1_mapping != MAPPING_CH0) {
+ // Tune the internal LO away to avoid interference
+ _set_lox_synth_freq(lo_stage, twinrx_ctrl::CH2, ch1_freq_d + 100e6);
+ }
ch1_freq_c = ch1_freq_d;
} else {
// When in hopping mode, only attempt to write the LO frequency if it is actually
@@ -655,10 +667,19 @@ void twinrx_settings_expert::_resolve_lox_freq(lo_stage_t lo_stage,
ch1_freq_c = _set_lox_synth_freq(lo_stage, twinrx_ctrl::CH2, ch1_freq_d);
} else if (synth0_mapping == MAPPING_SHARED or synth1_mapping == MAPPING_SHARED) {
// If any synthesizer is being shared then we are not in hopping mode
- twinrx_ctrl::channel_t ch =
- (synth0_mapping == MAPPING_SHARED) ? twinrx_ctrl::CH1 : twinrx_ctrl::CH2;
- ch0_freq_c = _set_lox_synth_freq(lo_stage, ch, ch0_freq_d);
- ch1_freq_c = ch0_freq_c;
+ // Tuning has already been done above if CH0 LO source is not external
+ if (ch0_lo_source == twinrx_ctrl::LO_EXTERNAL) {
+ // Tune the LO being shared
+ twinrx_ctrl::channel_t ch =
+ (synth0_mapping == MAPPING_SHARED) ? twinrx_ctrl::CH1 : twinrx_ctrl::CH2;
+ ch0_freq_c = _set_lox_synth_freq(lo_stage, ch, ch0_freq_d);
+ ch1_freq_c = ch0_freq_c;
+
+ // Tune the synthesizer of the other channel away to avoid interference
+ twinrx_ctrl::channel_t other_ch =
+ (synth0_mapping == MAPPING_SHARED) ? twinrx_ctrl::CH2 : twinrx_ctrl::CH1;
+ _set_lox_synth_freq(lo_stage, other_ch, ch0_freq_d + 100e6);
+ }
}
}
}