#!/usr/bin/env python3 # from fractions import Fraction from math import floor xtal = 25 PLLa_mult = 35 print() print("# 6000.694 - 2.200 kHz on PLLa") PLLa = xtal * PLLa_mult print(f"PLLa = xtal * {PLLa_mult} = {PLLa} MHz") if PLLa < 600 or PLLa > 900: print(f"Error PLL {PLLA} out of bounds") # x/y = a + b/y # a = floor(x/y) # b = x - (a * y) f2 = (6000.694 - 2.200) / 1000 a = floor(PLLa / f2) b = PLLa - (a * f2) div1 = Fraction(round(b * 10000), round(f2 * 10000)) print(f"CLK2: f2 = PLLa / ({a} + {div1.numerator} / {div1.denominator}) = {f2}") VHF_LO = 114.285 # Fixed XTAL BAND_EDGE_LOW = 144 - VHF_LO BAND_EDGE_HIGH = 145 - VHF_LO print() print(f"# VFO between {BAND_EDGE_LOW:6.6} and {BAND_EDGE_HIGH:6.6} MHz on PLLb") def calculate(frequency): divider = floor(900000000 / frequency) # Calculate the division ratio. 900,000,000 is the maximum internal if divider % 2: divider -= 1 # Ensure an even integer division ratio pllFreq = round(divider * frequency) # Calculate the pllFrequency: the divider * desired output frequency xtalFreq = xtal * 1000000 mult = floor(pllFreq / xtalFreq) # Determine the multiplier to get to the required pllFrequency l = pllFreq % xtalFreq # It has three parts: f = floor(l) # mult is an integer that must be in the range 15..90 denom = 1048575 f *= denom # num and denom are the fractional parts, the numerator and denominator f /= xtalFreq # each is 20 bits (range 0..1048575) num = floor(f) # the actual multiplier is mult + num / denom return (divider, mult, num, denom) vfo = 23000000 for i in range(10): divider, mult, num, denom = calculate(vfo) PLLb = xtal * 1000000 * (mult + num/denom) freq = PLLb / divider delta = vfo - freq print(f"CLK0: VFO {vfo}, PLLb = xtal * ({mult} + {num} / {denom}) = {PLLb}, PLLb / {divider} = {freq}, delta = {delta:.03} Hz") vfo += 100000