Shop OBEX P1 Docs P2 Docs Learn Events
The counters — Parallax Forums

The counters

Graham StablerGraham Stabler Posts: 2,507
edited 2006-08-31 00:16 in Propeller 1
I have read and re-read the manual on the use of the on board counters, I have also stared relentlessly at the frequency synthesizer example.

I understand the concept of conditional accumulation, I understand you can define primary and secondary output pins conditionally and I understand you can set various operating modes.

Some of these modes I understand,

In NCO/PWM modes you add the number stored in FRQx to PHSx on every clock cycle, the MSB of the PHSx register PHSx[noparse][[/noparse]31] is tied directly to the output pin that has been defined. In Beau's example synthesizer for low frequencies he divides the wanted frequency by the clock frequency to give a binary fraction, that means that the MSB represents 1, the next bit is 1/2 and the next 1/4 etc. This is put into the FRQx register to be added to PHXx on every clock cycle. Once the PHSx[noparse][[/noparse]31] becomes one so does the output pin. It then carries on adding until the PHSx overflows and PHSx[noparse][[/noparse]31] goes low again.

I think that's how it works, essentially the smaller the number in FRQx the more clocks it takes to toggle PHSx[noparse][[/noparse]31] and you control the frequency seen on that pin.

I'm stating what I know in case I've got it wrong.

Now on to what I really don't get:

1. What has mode 00100 "NCO/PWM single ended" got to do with PWM?
2. What is the "Duty single-ended" mode, how does it work and what is it for? Duty to me relates to the ratio of on and off times in PWM.

I know part of my problem in understanding the counters is down to the rust collecting on my binary brain but I am a little dissapointed by the documentation, The thing is that I understand it and it makes complete sense but doesn't explain how they may be used despite the tantalizing list of possible uses.

The commenting in the examples is also from the point of view of those that understand it already. I find this true for much of the code available although I do understand the time it takes to add beginner friendly commenting.

Graham

Comments

  • parskoparsko Posts: 501
    edited 2006-08-28 13:31
    Graham,

    I'm with you.· I can ditto everything you typed.· I have been staring at the CTRA, FRQA, PHSA command pages in the manual for about a week now, to no avail.· There have been many requests in the past few months for someone to explain the counters, but no one has.· I personally think it is time to start this discussion (obviously, since I need it[noparse]:)[/noparse] ).· I haven't gone as far as to review the frequency synthesizer yet though.

    I think a good start would be to explain the simple, and most commonly used/most useful modes, with an extremely simple example spoon feeding us line-by-line commenting.

    Understandably, Parallax is not going to jump into this daunting and complex subject.· I have assumed that they would deal with it when someone asks.· Plus, there are probably other larger problems to tackle first.· But, it is to a point where even the beginners are asking for the info, so I would guess now is the time...

    I simply would like to know how to use CTRA to toggle a pin high and low.· It dawned on my that this would be WICKED useful in generating bit-banging code.



    "...but I am a little dissapointed by the documentation, The thing is that I understand it and it makes complete sense but doesn't explain how they may be used despite the tantalizing list of possible uses."

    I'm down with the "but doesn't explain" part!!!!

    I feel like I am building an arch,·and Parallax unknowingly has the keystone.· These stones are getting heavy, too!

    I have been too scared to ask myself, kudos for breakin' the seal!

    -Parsko
  • Beau SchwabeBeau Schwabe Posts: 6,559
    edited 2006-08-28 16:06
    Graham,

    The "frequency synthesizer" object I wrote was derived from an object Chip originally wrote located in the Propeller
    object Exchange library under "Lots of Objects and Demos".· Look at the file called "CTR.spin" for more detail on the
    different counter settings.

    http://ww1.parallax.com/Default.aspx?tabid=65

    http://forums.parallax.com/showthread.php?p=589195




    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.

    Post Edited (Beau Schwabe (Parallax)) : 8/28/2006 4:10:04 PM GMT
  • Graham StablerGraham Stabler Posts: 2,507
    edited 2006-08-28 19:14
    Beau,

    The documentation in the manual looks to be exactly what is seen in CTR.spin so looking at CTR.spin is not likely to help.

    As I thought I explained, it is not the registers or the counters themselves that cause the problem but how to use them, there is certainly nothing to explain the meaning of duty or how to create PWM.

    Graham
  • Tracy AllenTracy Allen Posts: 6,660
    edited 2006-08-29 06:01
    Graham,

    I'll take a stab at the questions

    1) mode 00100 NCO/PWM as you described it is correct. It generates almost symmetrical ON and OFF times that are long when FRQx is small. The highest frequency occurs when FRQx=$80000000, in which case PHSx toggles ON or OFF with every clock cycle so the output is 1/2 the clock frequency.

    Note for completeness that the period is long not only when FRQx is small, but also when FRQx is large. When FRQx increases above $80000000, the output frequency goes down again and is longest when FRQx=$ffffffff. Think of that as -1 in twos complement--Subtracting one from the accumulator at each step produces the same output frequency as adding one. FRQx=1 and FRQx=-1 = $ffffffff generate the same NCO frequency.

    Connection to PWM? It requires program intervention. The counter itself does not do PWM without intervention. For best resolution that would have to be done with pasm, although Spin could work for low frequencies. PHSx can be jammed first with a value for the LOW duration, and the pasm program can go off to manage other tasks without concern for timing, so long as it gets back to test PHS[noparse][[/noparse]31] with a Pin equal or not equal in time to jam in the value for the HIGH duration. There may be different ways to implement it, but I think that it does require intervention.

    2) Duty modes, single ended or differential, are a way of getting a certain percentage of time HIGH/LOW. It is not duty cycle control in the constant frequency sense you may be thinking of. It might more properly be called pulse density or pulse frequency modulation. 50% density is achieved by a high frequency of pulses that are 50% on and off. The lowest density comes from leaving the pin low most of the time and occasionally, at a low frequency, pulsing to the high level, and vice versa, a high density comes from leaving the pin high most of the time and occasionally pulsing low. (This is the same as PWM command on the BASIC Stamp, except with a 2^32 cycle as opposed to a 2^16 cycle).

    The duty modes result from action of the PHS-Carry bit, while the NCO/PWM modes reflect the action of the PHS(31) bit. The two are closley related. When PHS(32) changes from 1 to zero, there is a carry out. When FRQx=1, a carry will occur only once in 2^32 additions of FRQx to PHSx, so the pin tied to PHS-carry goes high only once every 2^32 cycles. Same when FRQx = -1 = $ffffffff, a carry occurs with _every_ cycle, and the pin tied to PHS-carry stays high except for one low pulse every 2^32 cycles. Again FRQx=$80000000 is the highest frequency and also 50% duty cycle.

    When the goal is a duty cycle, the values "near" 50% will be the most useful, because the 1% and 99% ends of the scale involve periods that can approach one minute.

    What is it good for? This waveform at high frequencies is easy to filter and to buffer with an op-amp to generate an analog voltage or current, so it is a digital to analog converter. The voltage can be modulated to make waveforms up to some maximum value that depends on the Prop clock frequency and on the deviation desired from the 50% value. You might not use this kind of PWM to drive something like a motor directly, which might do better on a constant frequency, duty cycle PWM.

    Understanding: It helps me to get out a piece of column paper (or write a little program) to make my own counter logic with say 4 bits instead of 32 bits. In the left column, write the sequence of values that result when adding FRQ to your PHS, and in other colums write the binary value and especially the value of PHS(31) and PHS-carry. For example:

    FRQ=3
    PHS     binary    (msb)  (carry)
    0         0000       0
    3         0011       0     0
    6         0110       0     0
    9         1001       1     0
    12        1100       1     0
    15        1111       1     0
    2         0010       0     1
    5         0101       0     0
    8         1000       1     0
    11        1011       1     0
    14        1110       1     0
    1         0001       0     1
    4         0100       0    0
    7         0111       0     0
    10        1010       1     0
    13        1101       1     0
    0         0000       0     1    <-- restarting cycle of 16 steps
    3         0011       0     0
    6         0110       0     0
    9         1001       1    0
    ...
    



    Then try it with FRQ=5, FRQ=13 and other FRQs. Note both the change in frequency in PHS(31) and the density of pulses in PHS-carry. Note what happens when FRQ includes factors of 2. Then take it to 5 or 6 bits instead of 4 bits. Doing a few of these can help a lot with an intuitive understanding of the counter operations. (huh?)


    Here is the example for FRQ=13 with a 4 bit accumulator. Note how the addition of 13 modulo 16 results in a carry with most of the steps. Adding 13 at each step, mod 16, it like subtracting 3 at each step. The carry occurs when the msb goes from 0 to 1. The pattern is the complement of FRQ=3. The output in (msb) and in (carry) are mirror images.

    FRQ=13
    PHS     binary    (msb)  (carry)
    0         0000       0
    13        1101       1     0
    10        1010      1     1
    7         0111       0     1
    4         0100       0     1
    1         0001       0     1
    14        1110       1     0
    11        1011       1     1
    8         1000       1     1
    5         0101       0     1
    2         0010       0     1
    15        1111       1     0
    12        1100       1    1
    9         1001       1     1
    6         0110       0     1
    3         0011       0     1
    0         0000       0     1    <-- restarting cycle of 16 steps
    13       1101       0     0
    10        1010       0     0
    7         0111       1    0
    ...
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Tracy Allen
    www.emesystems.com

    Post Edited (Tracy Allen) : 8/29/2006 10:19:10 PM GMT
  • Graham StablerGraham Stabler Posts: 2,507
    edited 2006-08-29 11:02
    Tracy,

    That is really helpful, thanks very much! I'll definately write some of this stuff out, I'd tried before but to be honest the example program through me off for a long time because I hadn't quite understood what the fraction function had done.

    I'm sure this stuff is obvious to those working with uPs every day but it took me a while to get to grips with it and red herrings such as the mode names made things even more difficult, I thought I was just being stupid which led to frustration and that never helps.

    I'd also mention that the Propeller is the first Parallax product I have ever used, I don't know anything about basic stamps or the commands that they have used, I find myself a bit out of the loop sometimes.

    If I can get to grips with all of this fully I'll try and write up a dummies guide.

    Cheers,

    Graham
  • Tracy AllenTracy Allen Posts: 6,660
    edited 2006-08-29 19:23
    For completeness, I edited the my last post to include the case of FRQ=13 with the 4 bit accumulator. (and corrected a couple of late night typos).

    The fraction function should be demystified. Let me give it a whirl...

    For the "duty" modes (%00110 and %00111), the duty cycle of the PWM is simply
    duty = FRQx / 2^32
    or if you need to solve for the value of FRQa to use,
    FRQx = duty * 2^32
    That can in some cases be precomputed, or it can come from a table, or the multiplication can be done in real time. Note that the master clock frequency is not a factor in this. However, jitter in the output will be less when the clock frequeny is high and when the duty is restricted to values centered around 50%. Remember that duty is more like pulse density or pulse frequency modulation, not constant frequency duty cycle modulation.

    For the NCO modes (%00100 and %00101), the value of FRQx comes from solving
    FRQx = Fout / CLKFREQ * 2^32 ' CORRECTED this formula in edit, had an extra factor of 2
    That does of course involve the clock frequency. There are two things to understand about this: How to derive the formula (for understanding), and how to compute the value on the right (very practical!).

    For derivation, here is one way to dust off the binary brain cells. Think in terms of period. The period of the Prop counter is Tclk = 1/Fclk and suppose the period of the frequency you want is Tout = 1/Fout. The ratio of those two periods is a number that tells you the total number periods of the Prop counter that have to make up the cycle of 1's and 0's out of PHS(31). That is of course the same thing as the ratio of the frequencies, but it may be easier to think of one period of, say 1/440 Hertz = 2.27 millisecond is made up of 90909 time slots of 25 nanoseconds from the counter.

    Here is a point of confusion. FRQx is a dimensionless number. It is not a frequency. It is not a period. It is just a number, and the above condition is,
    FRQx * N = 2^32
    or rearranging
    FRQx = 2^32 / N
    For example, suppose the CLKFREQ=40 mHz and the desired output is Fout=440 Hz. Then N = 90909. And FRQx = 47244. When 47244 is added to a 32 bit accumulator 90909 times it gets up to just less than 2^32, and with the next addition of 47244 it overflows (generates a carry) and starts over again at a low number. During those 90909 time slots, the msb PHS(31) is low for the first half and high for the second half. And remember, each time slot is 25 nanoseconds, and 90909 * 25 nanoseconds = 2.27 milliseconds, the period of the 440 Hertz square wave.

    When you substitute CLKFREQ and Fout back into the formula, you get:
    FRQx = 2^32 * Fout/CLKFREQ
    That is the formula that the algorithm solves by using binary long division. We can get into the division algorithm itself if you want.

    To emphasize again, FRQx is not a frequency. It is a dimensionless number. All the possible frequencies Fout can be achieved with values of FRQx from 1 (the lowest frequency) to $80000000 (the highest frequency). Values from FRQx=$80000001 up to $ffffffff are mirror images (see previous post).

    There are some remainders and slight approximations that have to be disregarded in the calculation. Those are subtleties that only cause a problem if you are after extremes of precision in frequency or spectral purity. Those issues have come up in previous threads, but for many or most purposes those subtleties will not be an issue

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Tracy Allen
    www.emesystems.com

    Post Edited (Tracy Allen) : 9/18/2006 6:48:16 PM GMT
  • parskoparsko Posts: 501
    edited 2006-08-29 21:04
    Tracy,

    Can you briefly explain what PLL does?

    Your counter example did it for me to explain what the other two modes were doing. I think I understand the concept, understand how to implement, now just have to experiment.

    I was under the impression that CRTA and CTRB could set to zero and accumulated, and one could read the value whenever one wanted to for random timing of things, I may have thought wrong though.

    -Parsko
  • Tracy AllenTracy Allen Posts: 6,660
    edited 2006-08-29 23:30
    The PLL is a frequency multiplier that is locked on to 16x the frequency of PHS(31) bit. In the PLL modes, an output pin can be tied either directly to PLL16, or to divided down from the PLL by a factor of 1, 2, 4, ... , or 128. The calculation of the necessary FRQx is the same as it is for the NCO modes, allowing for the multiplication factor. For example, PLL16 output of 100 mhz would require a 6.25 mhz frequency in PHS(31). If CLKFREQ for the Prop is 80mhz, then the required value of FRQx is
    FRQx = 2^32 * 6250000 / 80000000 = 335544320 ' CORRECTED, had extra factor of 2

    or in terms of the target frequency of 100 mhz,
    FRQx = 2^32 * 100_000_000 / 16 /80_000_000
    which can be rearranged for convenience in the calculation.

    The PLL 16x output has a limited range, something like 64 to 128 mhz, so the frequency in the PHS(31) has to be limited to 1/16 that range, something like 4 to 8 mhz. If you need an output frequency of say, 30mhz, you would use the 8x tap instead of the 16x tap, but the PLL itself always runs at 16x. According to Chip, the PLL responds within a few cycles to changes of frequency at PHS(31). So if the program changes the PHS(31) frequency from 6.25 to 6.5 mhz, the PLL16 output would change within a few cycles from 100 to 104 mhz. By the same token, if there is a little bump in the numerics of the oscillator, the slower response of the PLL will tend to smooth that out. There was some discussion in another thread about how fast or how slow the PLL response should be.

    CTRx, FRQx and PHSx registers are readable and writable to either zero or to other preset values and the program can read the values whenever.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Tracy Allen
    www.emesystems.com

    Post Edited (Tracy Allen) : 9/18/2006 6:56:31 PM GMT
  • Graham StablerGraham Stabler Posts: 2,507
    edited 2006-08-30 01:04
    I might add that the documentation only mentions the X 16 as part of the example on setting the mode. That also confused me.

    Graham
  • parskoparsko Posts: 501
    edited 2006-08-30 07:09
    Tracy,

    You are explaining the PLL mode two posts above, correct?? I'm confused as to if you are talking about the PLL mode or the PLL hardware.

    Now to ask a REALLY simple question that I am interested to have confirmed;
    During runtime, assuming you only set CTRx, FRQx, and PHSx once, the value of PHSx is the only one that changes every clock cycle (or every cycle that the mode is set to work for, I think you get the point of the question)? A.k.a. CTRx and FRQx maintain the same value in RAM, whilst PHSx is incremented accordingly?

    -Parsko
  • cgraceycgracey Posts: 14,133
    edited 2006-08-30 08:51
    That's correct: only PHSx changes automatically as the counter runs. The other registers CTRx and FRQx can only be affected by you writing to them (they're also cleared on a COG reset). You can set PHSx, too, but it's·usually accumulating FRQx into itself based on the add decision for each clock.
    parsko said...


    Now to ask a REALLY simple question that I am interested to have confirmed;
    During runtime, assuming you only set CTRx, FRQx, and PHSx once, the value of PHSx is the only one that changes every clock cycle (or every cycle that the mode is set to work for, I think you get the point of the question)? A.k.a. CTRx and FRQx maintain the same value in RAM, whilst PHSx is incremented accordingly?
    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    Chip Gracey
    Parallax, Inc.
  • Graham StablerGraham Stabler Posts: 2,507
    edited 2006-08-31 00:16
    Parkso,

    when in PLL mode the PHS[noparse][[/noparse]31] signal is fed into PLL hardware, this multiplies the frequency by 16. You can use that frequency directly or you can use the PLLDIV bits to divide the frequency down before bunging it on an output pin.

    The PLL mode and hardware are linked, when in PLL mode the hardware is used.

    Graham
Sign In or Register to comment.