Setting PLL values with the C++ DLL API


#1

When setting the PLL and clock values in the DLL API, are my assumptions below correct?

The sample code sets the PLL and output clk with something like these:

	okPLL22393_SetPLLParameters(pll, 0, 400, 48, TRUE);
	okPLL22393_SetOutputDivider(pll, 0, 4);
	okPLL22393_SetOutputSource(pll, 0, ClkSrc22393_PLL0_0);
	okPLL22393_SetOutputEnable(pll, 0, TRUE);
	okUsbXEM3010_SetPLLConfiguration(dev, pll);

So does okPLL22393_SetPLLParameters(pll, 0, 400, 48, TRUE); set the params of PLL0? Meaning if I put (pll,1,400,48,TRUE), it would set the p and q for pll1?

And for okPLL22393_SetOutputDivider(pll, 0, 4), okPLL22393_SetOutputSource(pll, 0, ClkSrc22393_PLL0_0), and okPLL22393_SetOutputEnable(pll, 0, TRUE), does the 0 mean CLKA? So 1 would refer to CLKB, 2 to CLKC and so on?


#2

[QUOTE=evanichka]
So does okPLL22393_SetPLLParameters(pll, 0, 400, 48, TRUE); set the params of PLL0? Meaning if I put (pll,1,400,48,TRUE), it would set the p and q for pll1?

And for okPLL22393_SetOutputDivider(pll, 0, 4), okPLL22393_SetOutputSource(pll, 0, ClkSrc22393_PLL0_0), and okPLL22393_SetOutputEnable(pll, 0, TRUE), does the 0 mean CLKA? So 1 would refer to CLKB, 2 to CLKC and so on?[/QUOTE]

Yes to both. The Opal Kelly numbering is PLL0, PLL1, PLL2 whereas the 22393 datasheet refers to PLL1, PLL2, PLL3. And [CLKA-CLKE] => [0-4]. When setting PLL parameters you use 0, 1, 2 to refer to the three PLLs, but when referring to PLLs as sources for clock outputs you use [0, 2-7] which matches the datasheet. For example, PLL_0_0 is 2 and PLL_0_180 is 3. (It’s not clear to me whether the 22393 actually has 180 degree outputs, the datasheet only shows that for the 22394.)

To change the subject only slightly: there are some inconsistencies at
http://www.opalkelly.com/library/FrontPanelAPI/classokCPLL22393.html
. For example, SetPLLParameters has an “enable” argument in the list of functions, but not in the example code in the green box. SetReference also has different numbers of arguments between the two. In general the PLL functions and parameters are not well documented. Fortunately most of it is decipherable from the data sheet and example code.

But getting to the real point of my post: one thing that should be pointed out which drove me crazy is that the SetOutputEnable call apparently does its thing by setting the output divisor to zero, not by setting an enable bit in the PLL (from reading the datasheet I guess there are no such bits). Thus, the following sequence, which seems like the natural way to turn a clock on and off, definitely does not do the right thing:

// Turn off CLKD output
okUsbXEM3010_GetPLLConfiguration (dev, pll);
okPLL22393_SetOutputEnable (pll, 3, 0);
okUsbXEM3010_SetPLLConfiguration (dev, pll);

… go do some other stuff

// Turn CLKD back on – NOT!
okUsbXEM3010_GetPLLConfiguration (dev, pll);
okPLL22393_SetOutputEnable (pll, 3, 1);
okUsbXEM3010_SetPLLConfiguration (dev, pll);

The divisor remains set at zero even after the last enable call, and an oscilloscope verified that the clock output is still off even though this should have turned it on. My workaround is to memorize the divisor value prior to turning off a clock output, and then restoring it as part of the enable call. In other words a SetOutputDivider call must precede any output enable if it has been previously disabled.

O-K, please clarify if this is wrong.


#3

Hi jadwin79-

I had to look into the PLL question you pose. Let me see if I can clarify.

You are correct, there is no “enable bit”. Rather, the divider is set to 0.

I would say that the “proper” way to turn on and off the PLL would be something like this:

// Turn off CLKD output
okPLL22393_SetOutputEnable (pll, 3, 0);
okUsbXEM3010_SetPLLConfiguration (dev, pll);

.. go do some other stuff

// Turn CLKD back on -- NOT!
okPLL22393_SetOutputEnable (pll, 3, 1);
okUsbXEM3010_SetPLLConfiguration (dev, pll);

The problem with your code is that you re-initialize the pll instance from the PLL configuration. The problem is a loss of information – if a PLL output is disabled, the PLL configuration holds no information about the previous divider setting.

The pll instance, however, does the following – it holds the divider value and the enable value separately. When you go to program the PLL, it then uses these two pieces of information to decide what to set the PLL’s divider to.

So basically, your workaround is something that is already done in the PLL22393 class as long as you don’t reinitialize it with a GetPLLConfiguration.

Does this make sense?


#4

Regarding the documentation question – I’ll look into consistence of the 0-reference v. 1-reference.

We had to make a call. The PLL designers preferred the 1-reference. Unfortunately, C, C++, and many other programmers prefer the 0-reference. We decided to make the translation to fit better with programming.

We also had to make a call for documenting what is a somewhat complicated PLL programming process. So complicated, in fact, that Cypress provides a standalone software tool to determine all the settings to hit the right target frequency.

We decided that the vast majority of users would want simple frequencies like 100MHz and that fiddling with the examples would be enough. The other users that want to find 91.273 MHz would be better served with the Cypress documentation rather than our own translation of it.

We briefly toyed with the idea of building the software so that it could best approximate any given frequency by computing the correct parameters. This turned out to be a fair bit of work, especially considering that so few users would end up using it.


#5

Regarding the documentation inconsistencies – you were right about the number of argumnets for SetReference(). This has been fixed for a future release. Thanks.

The arguments for SetPLLParameters, however, was correct. The example in the green box makes use of the default “true” value for the enable bool. Therefore, it is not required as an explicit parameter.


#6

[QUOTE=Opal Kelly Support]Regarding the documentation question – I’ll look into consistence of the 0-reference v. 1-reference.

We had to make a call. The PLL designers preferred the 1-reference. Unfortunately, C, C++, and many other programmers prefer the 0-reference. We decided to make the translation to fit better with programming.
[/QUOTE]

Thanks. The PLL0/1 issue is no big deal at all. I was more concerned about the inconsistencies in documentation, specifically the parameter mismatches. Since I was writing in C, your point about default parameters being omitted didn’t enter my brain :slight_smile: