aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorDavid Raeman <david@synopticengineering.com>2022-03-08 02:50:06 +0000
committerAaron Rossetto <aaron.rossetto@ni.com>2022-04-01 13:30:05 -0700
commit7a303df8e4a9c167691ffd242424be76559a712f (patch)
tree5b7c5e0af6af20f188b84a920e7ed88ee81821b6 /host
parentacc731eeb70f948288b5ffcd64dc4b357356cc4e (diff)
downloaduhd-7a303df8e4a9c167691ffd242424be76559a712f.tar.gz
uhd-7a303df8e4a9c167691ffd242424be76559a712f.tar.bz2
uhd-7a303df8e4a9c167691ffd242424be76559a712f.zip
n320: fix issue that occasionally prevents lo_locked upon first set_freq
For certain frequencies, the LMX2592 will sporadically fail to lock upon the very first tune. When this happens, subsequent tunes (even to the same frequency) do lock. This issue seems to be resolved by programming the FCAL adjustment register fields (FCAL_LPFD_ADJ/FCAL_HPFD_ADJ) as described in the LMX2592 datasheet. These fields adjust the FCAL calibration speed to better accomodate PFD frequencies below 20MHz or above 100MHz. This patch also fixes a few name typos in the register map that were directly in the scope of this change.
Diffstat (limited to 'host')
-rwxr-xr-xhost/lib/ic_reg_maps/gen_lmx2592_regs.py4
-rw-r--r--host/lib/usrp/common/lmx2592.cpp49
2 files changed, 45 insertions, 8 deletions
diff --git a/host/lib/ic_reg_maps/gen_lmx2592_regs.py b/host/lib/ic_reg_maps/gen_lmx2592_regs.py
index 0d5f0be23..8a323928a 100755
--- a/host/lib/ic_reg_maps/gen_lmx2592_regs.py
+++ b/host/lib/ic_reg_maps/gen_lmx2592_regs.py
@@ -19,7 +19,7 @@ muxout_sel 0[2] 1 readback, lock_detect
fcal_enable 0[3] 1
acal_enable 0[4] 1
fcal_lpfd_adj 0[5:6] 0 unused, 20mhz, 10mhz, 5mhz
-fcal_hpfd_adf 0[7:8] 0 unused, 100mhz, 150mhz, 200mhz
+fcal_hpfd_adj 0[7:8] 0 unused, 100mhz, 150mhz, 200mhz
reg0_reserved0 0[9:12] 0x1
ld_enable 0[13] 1
reg0_reserved1 0[14:15] 0x0
@@ -78,7 +78,7 @@ reg12_reserved0 12[12:15] 0x7
## address 13
########################################################################
reg13_reserved0 13[0:7] 0x0
-pdf_ctl 13[8:9] 0 dual_pdf=0, single_pfd=3
+pfd_ctl 13[8:9] 0 dual_pfd=0, single_pfd=3
reg13_reserved1 13[10:13] 0x0
cp_enable 13[14] 1
reg13_reserved2 13[15] 0x0
diff --git a/host/lib/usrp/common/lmx2592.cpp b/host/lib/usrp/common/lmx2592.cpp
index 0833bc7c4..0a409f117 100644
--- a/host/lib/usrp/common/lmx2592.cpp
+++ b/host/lib/usrp/common/lmx2592.cpp
@@ -235,6 +235,8 @@ public:
pfd_freq = input_freq / _regs.pll_r;
}
+ _set_fcal_adj_values(pfd_freq);
+
// Calculate N and frac
const auto N_dot_F = target_vco_freq / (pfd_freq * prescaler);
auto N = static_cast<uint16_t>(std::floor(N_dot_F));
@@ -253,12 +255,12 @@ public:
// Calculate Fnum
const auto initial_fnum = static_cast<uint32_t>(std::round(frac * fden));
const auto fnum = (spur_dodging) ? _find_fnum(N,
- initial_fnum,
- fden,
- prescaler,
- pfd_freq,
- output_divider,
- spur_dodging_threshold)
+ initial_fnum,
+ fden,
+ prescaler,
+ pfd_freq,
+ output_divider,
+ spur_dodging_threshold)
: initial_fnum;
// Calculate mash_seed
@@ -519,6 +521,41 @@ private: // Members
}
}
+ void _set_fcal_adj_values(const double pfd_freq)
+ {
+ // Adjust FCAL speed for particularly high or low PFD frequencies
+ if (pfd_freq < 5e6) {
+ _regs.fcal_lpfd_adj = lmx2592_regs_t::fcal_lpfd_adj_t::FCAL_LPFD_ADJ_5MHZ;
+ _regs.fcal_hpfd_adj = lmx2592_regs_t::fcal_hpfd_adj_t::FCAL_HPFD_ADJ_UNUSED;
+ _regs.pfd_ctl = lmx2592_regs_t::pfd_ctl_t::PFD_CTL_DUAL_PFD;
+ } else if (pfd_freq < 10e6) {
+ _regs.fcal_lpfd_adj = lmx2592_regs_t::fcal_lpfd_adj_t::FCAL_LPFD_ADJ_10MHZ;
+ _regs.fcal_hpfd_adj = lmx2592_regs_t::fcal_hpfd_adj_t::FCAL_HPFD_ADJ_UNUSED;
+ _regs.pfd_ctl = lmx2592_regs_t::pfd_ctl_t::PFD_CTL_DUAL_PFD;
+ } else if (pfd_freq < 20e6) {
+ _regs.fcal_lpfd_adj = lmx2592_regs_t::fcal_lpfd_adj_t::FCAL_LPFD_ADJ_20MHZ;
+ _regs.fcal_hpfd_adj = lmx2592_regs_t::fcal_hpfd_adj_t::FCAL_HPFD_ADJ_UNUSED;
+ _regs.pfd_ctl = lmx2592_regs_t::pfd_ctl_t::PFD_CTL_DUAL_PFD;
+ } else if (pfd_freq <= 100e6) {
+ _regs.fcal_lpfd_adj = lmx2592_regs_t::fcal_lpfd_adj_t::FCAL_LPFD_ADJ_UNUSED;
+ _regs.fcal_hpfd_adj = lmx2592_regs_t::fcal_hpfd_adj_t::FCAL_HPFD_ADJ_UNUSED;
+ _regs.pfd_ctl = lmx2592_regs_t::pfd_ctl_t::PFD_CTL_DUAL_PFD;
+ } else if (pfd_freq <= 150e6) {
+ _regs.fcal_lpfd_adj = lmx2592_regs_t::fcal_lpfd_adj_t::FCAL_LPFD_ADJ_UNUSED;
+ _regs.fcal_hpfd_adj = lmx2592_regs_t::fcal_hpfd_adj_t::FCAL_HPFD_ADJ_100MHZ;
+ _regs.pfd_ctl = lmx2592_regs_t::pfd_ctl_t::PFD_CTL_DUAL_PFD;
+ } else if (pfd_freq <= 200e6) {
+ _regs.fcal_lpfd_adj = lmx2592_regs_t::fcal_lpfd_adj_t::FCAL_LPFD_ADJ_UNUSED;
+ _regs.fcal_hpfd_adj = lmx2592_regs_t::fcal_hpfd_adj_t::FCAL_HPFD_ADJ_150MHZ;
+ _regs.pfd_ctl = lmx2592_regs_t::pfd_ctl_t::PFD_CTL_DUAL_PFD;
+ } else {
+ // Note, this case requires single-loop PFD which increases PLL noise floor
+ _regs.fcal_lpfd_adj = lmx2592_regs_t::fcal_lpfd_adj_t::FCAL_LPFD_ADJ_UNUSED;
+ _regs.fcal_hpfd_adj = lmx2592_regs_t::fcal_hpfd_adj_t::FCAL_HPFD_ADJ_200MHZ;
+ _regs.pfd_ctl = lmx2592_regs_t::pfd_ctl_t::PFD_CTL_SINGLE_PFD;
+ }
+ }
+
// "k" is a derived value that indicates where sub-fractional spurs will be present
// at a given Fden value. A "k" value of 1 indicates there will be no spurs.
// See the LMX2592 datasheet for more information