Any Spin2 code existing for determining PLL parameters?
rogloh
Posts: 5,787
Does anyone have any working SPIN2 code that (optimally?) determines the divider parameters for the MMM...MM, PPPP and DDDDDD fields in the clock mode related to setting up the PLL?
I am considering modifying my video driver timing code such that it would allow systems with different crystals by just taking the desired final P2 frequency required for the desired resolution and then working out the necessary clock mode value automatically. Currently it just uses predefined clock mode constants assuming 20MHz crystals for example, and it won't work with other values unless you go manually patch this yourself which could get tedious. If I can't find code I might just keep it like that, but I vaguely thought there were some samples of code around the forums that did this - had a bit of a search but couldn't find it.
I am considering modifying my video driver timing code such that it would allow systems with different crystals by just taking the desired final P2 frequency required for the desired resolution and then working out the necessary clock mode value automatically. Currently it just uses predefined clock mode constants assuming 20MHz crystals for example, and it won't work with other values unless you go manually patch this yourself which could get tedious. If I can't find code I might just keep it like that, but I vaguely thought there were some samples of code around the forums that did this - had a bit of a search but couldn't find it.
CLK297MHz = %1_010011_0100101000_1111_10_00 '(20MHz/20)*297/1 = 297 MHz CLK252MHz = %1_000100_0000111110_1111_10_00 '(20MHz/5) * 63/1 = 252 MHz CLK250MHz = %1_000011_0000110001_1111_10_00 '(20MHz/4) * 50/1 = 250 MHz CLK240MHz = %1_000100_0000111011_1111_10_00 '(20MHz/5) * 60/1 = 240 MHz CLK220MHz = %1_000001_0000010101_1111_10_00 '(20MHz/2) * 22/1 = 220 MHz CLK216MHz = %1_000100_0000110101_1111_10_00 '(20MHz/5) * 54/1 = 216 MHz CLK200MHz = %1_000100_0000110001_1111_10_00 '(20MHz/5) * 50/1 = 200 MHz ...
Comments
Usually for design-time, I use a calculator like consoleCalc and enter
fVCO = 216
fXTAL = 20
then
N=0;;N=N+1;fVCO/(fXTAL/N)
hit <cr> 5 times or until a close to integer result appears
ans = 10.8
ans = 21.6
ans = 32.4
ans = 43.2
ans = 54
N = 5
that one is simple, so let's try 26MHz
fXTAL = 26
N=0;; N=N+1;fVCO/(fXTAL/N)
hit <cr> 13 times
ans = 8.30769230769230769230769230769
ans = 16.6153846153846153846153846154
ans = 24.9230769230769230769230769231
ans = 33.2307692307692307692307692308
ans = 41.5384615384615384615384615385
ans = 49.8461538461538461538461538462
ans = 58.1538461538461538461538461538
ans = 66.4615384615384615384615384615
ans = 74.7692307692307692307692307692
ans = 83.0769230769230769230769230769
ans = 91.3846153846153846153846153846
ans = 99.6923076923076923076923076923
ans = 108
N = 13
An exact solution is possible for 2MHz PFD,
or you can extract the error as ratio
N=0;;N=N+1;ni=round(fVCO/(fXTAL/N));1-fVCO/(ni*fXTAL/N)
hit <cr> 13 times
ans = -0.0384615384615384615384615384615
ans = 0.0226244343891402714932126696833
ans = 0.00307692307692307692307692307692
ans = -0.00699300699300699300699300699301
ans = 0.010989010989010989010989010989
ans = 0.00307692307692307692307692307692
ans = -0.00265251989389920424403183023873
ans = -0.00699300699300699300699300699301
ans = 0.00307692307692307692307692307692
ans = -9.2678405931417979610750695088e-4
ans = -0.0042265426880811496196111580727
ans = 0.00307692307692307692307692307692
ans = 0
fXTAL/13 is 0ppm error, but fXTAL/10 is 926ppm low, in some cases, that may be ok.
I loop through P values, starting at 1, then use 2-30 by 2's.
Then I loop through the D values from 1-64, computing the nearest M, and M+1 required to obtain the VCO freq, for this D, P and desiredFreq.
Then I compute the resulting output frequency with these P,D,M values, check the error and retain the best values encountered so far. If the error ever hits 0 I exit with those values. I also skip when VCO<100MHz or VCO > 350MHz. I also probably should skip to the next value once the PLL input is less than 250-500kHz perhaps? I heard jitter becomes bad then...?
At the end I check the error tolerance is within spec and then return the successful clock mode value or 0 = failure.
https://forums.parallax.com/discussion/comment/1483060/#Comment_1483060
What would be the lowest input frequency we could still input to the P2 PLL that would be "reasonable" to still reliably scale up in the PLL for video use without jitter? I am assuming around 250kHz but perhaps this is too low. Is 500kHz a better value, or something else?
This sample harness could be ported over to official SPIN2 if there was a nice serial object that could do tx/rx to replace SmartSerial, though that one is a bit nicer because it adds the printf capability. The clock mode computation method should port as is.