Shop OBEX P1 Docs P2 Docs Learn Events
clkfreq + cnt confusion — Parallax Forums

clkfreq + cnt confusion

tobdectobdec Posts: 267
edited 2012-06-22 16:43 in Propeller 1
On page 51 of the Labs:Fundamentals book revision 1.2 in the timing delays with the system clock section. Second paragraph it says add cnt to clkfreq in the waitcnt system variable. I'm a little confused as to why I should or must do this.....what exactly is going on here? Please excuse my ignorance I'm still pretty new to Props.

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-06-20 21:09
    cnt is the current value of a 32-bit register that increments once for each "tick" of the system clock. clkfreq is the number of ticks that the system clock makes per second. So, if you add cnt to clkfreq, you get a value that equals the value of cnt one second hence. So, if you do waitcnt(cnt + clkfreq), you get a delay that equals one second, neglecting instruction overhead.

    -Phil
  • Mike GreenMike Green Posts: 23,101
    edited 2012-06-20 21:22
    If you have a complex expression that you want to add to CNT, you typically make CNT the last item in the expression so that the overhead of computing everything else occurs before CNT is added to it. That way, the total expression is closest to what you really want ... a time value a known amount in the future.
  • tobdectobdec Posts: 267
    edited 2012-06-20 21:23
    O I see, so basically this is a way to get around code overhead and get extremely time precise commands belted out?
  • Mike GreenMike Green Posts: 23,101
    edited 2012-06-20 21:39
    I wouldn't say "extremely precise". For that, you have to use assembly language where you can time things to a resolution of one clock cycle, but Spin is pretty good. Adding CNT as the last term in a WAITCNT expression gives you the best resolution that's obtainable in Spin. Do remember that you can do a lot of very precise timing using the cog counters which count at the system clock speed.
  • Cluso99Cluso99 Posts: 18,069
    edited 2012-06-20 23:11
    So..
    waitcnt(clkfreq/10 + cnt) 'means wait for 1s/10 which is 100ms
    waitcnt(clkfreq*5 + cnt) 'means wait for 1s*5 which is 5 seconds

    You can delay this way to around 56 seconds IIRC (just make sure it is <50s and you should be fine).

    There is a minimum because of the spin overhead, but IIRC 1us is fine and close enough for good resolution.
    Also, while in waitxxx the cog is in low power mode so you save power too.
  • prof_brainoprof_braino Posts: 4,313
    edited 2012-06-21 05:41
    Cluso99 wrote: »
    So..
    waitcnt(clkfreq/10 + cnt) 'means wait for 1s/10 which is 100ms
    waitcnt(clkfreq*5 + cnt) 'means wait for 1s*5 which is 5 seconds

    You can delay this way to around 56 seconds IIRC (just make sure it is <50s and you should be fine).

    Also notice that if your program appears to freeze for around a minute, there it likely an error in this area of your code. It you set it up wrong, it has to wait this long until the count rolls over.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-06-21 07:45
    Cluso99 wrote: »
    There is a minimum because of the spin overhead, but IIRC 1us is fine and close enough for good resolution.

    I think the minimun wait time is 381 clock cycles. The object "clock" in the Propeller Tool library uses this as the minimum.

    So you want to make sure if you're calculating a wait period based on the clock frequency, it doesn't fall below 381.

    Here's the way a "Duration" number of microseconds is computed in the "clock" object:
    PUB PauseUSec(Duration) 
    {{Pause execution in microseconds.
      PARAMETERS: Duration = number of microseconds to delay.
    }}
      waitcnt(((clkfreq / 1_000_000 * Duration - 3928) #> WMin) + cnt)                                 
      
    

    I think the value "3928" takes into account the system overhead of making the calculations.

    The "#> WMin" makes sure the computed value isn't less than 381 (which is the value of the constant "WMin").
  • ElectrodudeElectrodude Posts: 1,665
    edited 2012-06-22 10:50
    If you put the cnt first, I would think you would get more precise timing (but a longer minimum wait) because everything else would be evaluated during the delay. Is this correct?

    Electrodude
  • Mike GreenMike Green Posts: 23,101
    edited 2012-06-22 11:37
    The question really is "when do you want the time interval to begin?" The time interval begins when CNT is referenced. If you're doing a WAITCNT, you want the CNT to come last in any expression because the wait begins soon after that ... as the WAITCNT operation itself is executed. You will get a delay closest to what's specified in the rest of the expression when the CNT is the last operand to be accessed. For other purposes, like elapsed times, you want the CNT to be referenced last at the beginning of the interval and first at the end of the interval to get the most accurate timings.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-06-22 12:09
    One thing that hasn't been mentioned here is periodic timing, e.g. when you want to do something every X milliseconds, say. The knee-jerk way to do this is the following:
    repeat
      waitcnt(delay + cnt)
      'Do stuff.
    

    But you get precise timing if you do it this way:
    time := cnt
    repeat
      waitcnt(time += delay)
      'Do stuff
    

    The reason this is often better is that all of the "do stuff" code and overhead are included in the time interval, with waitcnt dealing only with whatever time is left over.

    -Phil
  • frank freedmanfrank freedman Posts: 1,983
    edited 2012-06-22 16:43
    Also notice that if your program appears to freeze for around a minute, there it likely an error in this area of your code. It you set it up wrong, it has to wait this long until the count rolls over.
    Hmmmmm, seem to recall great example of this in another earlier thread...........
Sign In or Register to comment.