From d433f6e86dd54036b9a315752a5bac50183acfc9 Mon Sep 17 00:00:00 2001 From: Etienne Wodey Date: Mon, 9 Nov 2020 18:09:50 +0100 Subject: [PATCH] coredevice: adf5355: more general PLL parameters calculation Signed-off-by: Etienne Wodey --- artiq/coredevice/adf5355.py | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/artiq/coredevice/adf5355.py b/artiq/coredevice/adf5355.py index 03a4aa2f2..3f862c54b 100644 --- a/artiq/coredevice/adf5355.py +++ b/artiq/coredevice/adf5355.py @@ -474,6 +474,18 @@ class ADF5355: return int32(r) +@portable +def gcd(a, b): + while b: + a, b = b, a % b + return a + + +@portable +def split_msb_lsb_28b(v): + return int32((v >> 14) & 0x3FFF), int32(v & 0x3FFF) + + @portable def calculate_pll(f_vco: TInt64, f_pfd: TInt64): """ @@ -489,20 +501,21 @@ def calculate_pll(f_vco: TInt64, f_pfd: TInt64): f_vco = int64(f_vco) # integral part - n = int32(f_vco / f_pfd) - r = f_vco / f_pfd - n + n, r = int32(f_vco // f_pfd), f_vco % f_pfd # main fractional part - frac1 = int32(ADF5355_MODULUS1 * r) - r = r * ADF5355_MODULUS1 - frac1 + r *= ADF5355_MODULUS1 + frac1, frac2 = int32(r // f_pfd), r % f_pfd # auxiliary fractional part - # FIXME: calculate optimal MOD2 - mod2 = ADF5355_MAX_MODULUS2 - frac2 = int32(r * mod2) + mod2 = f_pfd - # split frac2, mod2 - frac2_msb, frac2_lsb = (frac2 >> 14) & 0x3FFF, frac2 & 0x3FFF - mod2_msb, mod2_lsb = (mod2 >> 14) & 0x3FFF, mod2 & 0x3FFF + while mod2 > ADF5355_MAX_MODULUS2: + mod2 >>= 1 + frac2 >>= 1 - return n, frac1, (frac2_msb, frac2_lsb), (mod2_msb, mod2_lsb) + gcd_div = gcd(frac2, mod2) + mod2 //= gcd_div + frac2 //= gcd_div + + return n, frac1, split_msb_lsb_28b(frac2), split_msb_lsb_28b(mod2)