From 7a303df8e4a9c167691ffd242424be76559a712f Mon Sep 17 00:00:00 2001 From: David Raeman Date: Tue, 8 Mar 2022 02:50:06 +0000 Subject: 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. --- host/lib/ic_reg_maps/gen_lmx2592_regs.py | 4 +-- host/lib/usrp/common/lmx2592.cpp | 49 ++++++++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 8 deletions(-) (limited to 'host/lib') 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(std::floor(N_dot_F)); @@ -253,12 +255,12 @@ public: // Calculate Fnum const auto initial_fnum = static_cast(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 -- cgit v1.2.3