Shop OBEX P1 Docs P2 Docs Learn Events
How many counts does it take for the system counter, cnt, to roll over? — Parallax Forums

How many counts does it take for the system counter, cnt, to roll over?

ElectricAyeElectricAye Posts: 4,561
edited 2008-10-03 13:59 in Propeller 1
Hi all,

a simple question, the answer of which I can find nowhere in the literature.
According to my calculations, the system counter will roll over after reaching a cnt of 4294967295. Is this correct?

So cnt will go from 4294967295 to 0 as the system counter rolls over?

thanks,
Mark

Post Edited (ElectricAye) : 10/2/2008 9:21:37 PM GMT

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-10-02 21:39
    That's correct.

    -Phil

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    'Still some PropSTICK Kit bare PCBs left!
  • CarlosFandangoCarlosFandango Posts: 67
    edited 2008-10-02 22:15
    Does this mean that timing that is done using cnt will sometimes be incorrect? If this is the case, is there a (for example) wait(milliseconds) routine that is reliable, and takes this into account?
  • ElectricAyeElectricAye Posts: 4,561
    edited 2008-10-02 22:16
    Thanks Phil,

    I knew it was a 32-bit counter but I was afraid it would do something weird like roll over into negative numbers or something.

    Carlos, where this roll over phenomenon gets tricky is when you are trying to synch several cogs. If you are using repeat loops in your cogs, for example, and you are incrementing time variables to determine when to do things in synch according to the cnt, if you're not careful, your cnt can roll over on you and do funny things. For example, if you increment a TimeVariable and it happens to exceed 4294967295 whatever the actual rollover value is (see below), then if you have a command that says waitcnt (TimeVariable), the program will never get beyond this point. [noparse][[/noparse]Edit: actually I think I'm wrong about this now that I read what's been written below...]

    smile.gif

    Mark

    Post Edited (ElectricAye) : 10/3/2008 3:34:47 AM GMT
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-10-02 22:35
    ElectricAye said...
    ... I was afraid it would do something weird like roll over into negative numbers or something.
    Well, it does, actually. It's all in the interpretation, and Spin does use signed arithmetic. So if you're comparing cnt values in Spin, you have to take that into account.

    To recap, cnt goes from 0 -> ... -> $7FFF_FFFF (2147483647) -> $8000_0000 (-2147483648) -> ... -> $FFFF_FFFF (-1) -> 0.

    Typically, when used with waitcnt, you're only worrying about equality, and the signed arithmetic issue just goes away.

    -Phil

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    'Still some PropSTICK Kit bare PCBs left!

    Post Edited (Phil Pilgrim (PhiPi)) : 10/2/2008 11:34:04 PM GMT
  • Mike GreenMike Green Posts: 23,101
    edited 2008-10-02 22:51
    Usually when comparing times, you save the "old" value of CNT when you begin and calculate newTime - oldTime.· As long as the time difference is less than about 26 seconds, you will always get a positive difference which is the number of clock ticks between the two times.
  • Lord SteveLord Steve Posts: 206
    edited 2008-10-02 23:26
    Mike Green·said...
    As long as the time difference is less than about 26 seconds, you will always get a positive difference which is the number of clock ticks between the two times.


    You mean·about 26 seconds if you are running the Propeller at an 80-MHz system clock, right?
  • Mike GreenMike Green Posts: 23,101
    edited 2008-10-02 23:37
    Right, less than 2^31 with an 80MHz system clock would be roughly 26 seconds, comparable values with other system clock rates.
  • RaymanRayman Posts: 14,593
    edited 2008-10-03 00:01
    I think there are actually 2^32 states for the clock, right? So, it should take ~53.69 seconds to roll over.

    I think newtime-oldtime will always give a positive result, as long as less than 53.69 seconds.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-10-03 00:18
    Rayman,

    Not so. For example, -1 - 0 is still -1.

    -Phil

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    'Still some PropSTICK Kit bare PCBs left!
  • RaymanRayman Posts: 14,593
    edited 2008-10-03 00:35
    Phil,
    ·
    That's true, but that's a case of rolling over after 53 seconds...

    Ok, maybe you guys are right...· I guess I didn't appreciate that the difference was only good for 1/2 the range...

    Post Edited (Rayman) : 10/3/2008 12:45:06 AM GMT
  • ElectricAyeElectricAye Posts: 4,561
    edited 2008-10-03 00:48
    Okay, guys, now I don't feel so bad about getting confused about this. I'm trying to synch several cogs through some repeat loops that increment time variables, so I guess I need to come up with a fancy system for keeping the cogs working together through rollovers, etc.

    thanks,
    Mark
  • TimmooreTimmoore Posts: 1,031
    edited 2008-10-03 01:08
    Easiest way is to always compare (oldcnt-cnt) and make sure you sync more often than every 26 seconds. Then you are comparng +ve numbers without wrap
  • Ken PetersonKen Peterson Posts: 806
    edited 2008-10-03 02:25
    There's no 26 second limit. You can count differences up to 2^32-1. The only limitation is that a finite time for instruction execution needs to be accounted for, otherwise you end up passing your mark before doing the waitcnt instruction.

    Adding -1 to a number is the same as adding 2^32-1 because it's 32-bit math with no carry.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·"I have always wished that my computer would be as easy to use as my telephone.· My wish has come true.· I no longer know how to use my telephone."

    - Bjarne Stroustrup

    Post Edited (Ken Peterson) : 10/3/2008 2:30:53 AM GMT
  • hippyhippy Posts: 1,981
    edited 2008-10-03 02:50
    CarlosFandango said...
    Does this mean that timing that is done using cnt will sometimes be incorrect? If this is the case, is there a (for example) wait(milliseconds) routine that is reliable, and takes this into account?

    If you didn't catch it from the above discussion; timing with CNT will always be correct, providing the roll-over is taken into account.

    Using "WaitCnt( CLKFREQ / 1000 * ms + CNT )" will give whatever millisecond delay required with the roll-over effect taken into account.
  • Ken PetersonKen Peterson Posts: 806
    edited 2008-10-03 03:09
    You can do this:
    waitcnt(clkfreq * 50 + cnt) 
    
    


    and it will count 50 seconds. There's no 26 second limit. You can't count 54 seconds because clkfreq * 54 is greater than 2^32 (at 80 MHz).

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·"I have always wished that my computer would be as easy to use as my telephone.· My wish has come true.· I no longer know how to use my telephone."

    - Bjarne Stroustrup
  • ElectricAyeElectricAye Posts: 4,561
    edited 2008-10-03 03:15
    Hi Ken Peterson,

    I'm a little confused. If my cnt happens to be just slightly less than 2^32 when it reaches waitcnt(clkfreq * 50 + cnt) , would not the program get stuck there forever because you are now asking it to wait for a value that the cnt will never achieve due to roll over????


    confused.gifconfused.gifconfused.gif
  • Ken PetersonKen Peterson Posts: 806
    edited 2008-10-03 03:20
    ElectricAye: The value will never exceed 2^32 because the counter is a 32-bit register. In other words, 2^32 = 0 if limited to 32 bits. That's why it "rolls around". If the sum exceeds 2^32 then the carry is thrown away and you're left with a 32-bit result.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·"I have always wished that my computer would be as easy to use as my telephone.· My wish has come true.· I no longer know how to use my telephone."

    - Bjarne Stroustrup
  • ElectricAyeElectricAye Posts: 4,561
    edited 2008-10-03 03:25
    Ken Peterson,

    Thanks, Ken. Yes, I see what you mean. I keep getting confused about this register thing.


    smile.gif
  • TimmooreTimmoore Posts: 1,031
    edited 2008-10-03 03:33
    The time when you need to worry about 26 seconds is when you want to compare cnt's without using waitcnt. Dont compare them using oldcnt+clkfreq*5 < cnt, this is a bad way to see if 5 seconds as gone by but cnt-oldcnt > clkfreq*5 works for upto 26 seconds but has problems with > 26 seconds. Its possible to handle higher but takes more work.
  • ElectricAyeElectricAye Posts: 4,561
    edited 2008-10-03 04:09
    Thanks, Tim,

    With the help of you and others, I think I'm now beginning to map out the continent of my confusion on this issue.


    smile.gif

    Mark
  • StefanL38StefanL38 Posts: 2,292
    edited 2008-10-03 04:12
    hello everybody
    wooo - what a high-frequent responded threat !

    OK once again my elapsed_time_msec-method
    that takes care of the unsigned / signed and counter rollover-issues
    and a democode showing how to wait AND do other things at THE SAME TIME

    comments and sugestions for improvements are welcome


    'this democode shows how to wait userdefined amounts of time WITHOUT stopping the whole cog
    'you can do other things while waiting
    
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
      
    VAR
      long timer1
      long eTime1
    
      long timer2
      long timer3
    
    PUB Main
      'the FIRST PUB-Method inside a spinfile is ALWAYS the startpoint where the program starts to run    
    
      timer1 := cnt 'make inital snapshot of systemcounter 
      timer2 := cnt 'make inital snapshot of systemcounter 
      timer3 := cnt 'make inital snapshot of systemcounter 
    
      repeat
        'do whatever you like inside this loop
        'and what should be done with almost no delay
        
        'the method elapsed_time_msec calculates the time that has gone since
        'variable timer1 has set to the (former) value of systemcounter
        eTime1 := elapsed_time_msec(timer1) 
    
        if eTime1 => 100 '<== this is the TimePeriod of millisecs that were "waited" 'before the code below is executed 
          timer1 := cnt 'make new snapshot of systemcouner to set new startvalue
            ' code here what should be executed after the TimePeriod definded in the if condition above   
    
        if elapsed_time_msec(timer2) => 200 
          timer2 := cnt 'make new snapshot of systemcouner to set new startvalue
          'toggle LED2 or what ever    
    
        if elapsed_time_msec(timer3) => 400
          timer3 := cnt 'make new snapshot of systemcouner to set new startvalue
          'toggle LED3 or what ever    
    
    
          
    PUB elapsed_time_msec(p_TimeVar) | RightNow, ClockTicks
    'can measure up to 26843 Milliseconds
    '(2147483647 CounterTicks / 80.000.000 Hz = 26843 Milliseconds) 
    
      RightNow := cnt
    
      if RightNow < p_TimeVar                          
        ClockTicks := ||($FFFFFFFF - RightNow + p_TimeVar)  
      else
        ClockTicks := ||(RightNow - p_TimeVar)
    
      result := ClockTicks / (clkfreq / 1_000) 'calculate milliseconds
    
    
      '################################################################################
      'explanation how it works
      ' SPIN treats longs as SIGNED longs this means bit-No 32 represents the sign "+-"
      ' the systemcounter thinks of the 32bits as UNsigned meaning bit 32 is
      ' just another bit of the number and NOT a sign "+-" 
      ' if one or both values are negative it could happen
      ' that the result is negative too
      ' the command "||" calculates the absolute value of the SIGNED longs
    
      'even if the systemcounter has wrapped around since the snapshot of
      'systemcounter (value of parameter p_TimeVar),
      'this method calculates the timedifference in the right way
      
      'wrap-around example with easy numbers: counter maxvalue 1000
      'p_TimeVar containing value 980
      'time goes on counter wraps around from 1000 to 0
      'time goes on 
      'RightNow containing 300. This means 20 ticks until maximum 1000 and 300 ticks
      'since wrapping from 1000 to 0 in summary 320 ticks of time has gone
      'this is calculated by MaxCounter - p_TimeVar + RightNow
      'in numbers              1000     -   980     +   300     = 320
      'the real systemcounter has 32bits max value 2^32 -1 = 4294967295
      'hexadecimal $FFFFFFFF
      '################################################################################
     
    'end of PUB elapsed_time_msec(p_TimeVar) | RightNow, ClockTicks
    
    




    best regards

    Stefan

    Post Edited (StefanL38) : 10/3/2008 4:36:22 AM GMT
  • ElectricAyeElectricAye Posts: 4,561
    edited 2008-10-03 04:24
    Stefan,

    Yes, it seems my simple question has had a lot of interesting answers (and still counting!).

    Hey, thanks for posting this code. I'll have to study it tomorrow and grok how it works.

    cheers,
    Mark
  • ElectricAyeElectricAye Posts: 4,561
    edited 2008-10-03 13:59
    StefanL38 said...

    ' SPIN treats longs as SIGNED longs this means bit-No 32 represents the sign "+-"
    ' the systemcounter thinks of the 32bits as UNsigned meaning bit 32 is
    ' just another bit of the number and NOT a sign "+-"

    WOW, now I see why this topic is causing some confusion!

    So if you happen to be trying to synch some cogs using time variables and operators like > and =<, then methinks you could easily get into trouble.
Sign In or Register to comment.