diff options
author | David Raeman <david@synopticengineering.com> | 2022-03-08 02:50:06 +0000 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2022-04-01 13:30:05 -0700 |
commit | 7a303df8e4a9c167691ffd242424be76559a712f (patch) | |
tree | 5b7c5e0af6af20f188b84a920e7ed88ee81821b6 /host | |
parent | acc731eeb70f948288b5ffcd64dc4b357356cc4e (diff) | |
download | uhd-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-x | host/lib/ic_reg_maps/gen_lmx2592_regs.py | 4 | ||||
-rw-r--r-- | host/lib/usrp/common/lmx2592.cpp | 49 |
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 |