Shop OBEX P1 Docs P2 Docs Learn Events
Can I do this in spin? — Parallax Forums

Can I do this in spin?

KyeKye Posts: 2,200
edited 2009-04-03 20:01 in Propeller 1
Looking to see if I can preform sigend math with the cnt register for counter wrap arround.

  result := (cnt - timeSwitchCounter)

  timeSwitchCounter := cnt
 
  if(result < 0)
    result += $FFFF_FFFF

The idea is that result holds the delta since the last time the method was called and "timeSwitchCounter" is a global variable.

But, I'm not sure if I can compute the wrap arround propellerly since the spin does signed math only.

Any help?



▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nyamekye,

Comments

  • mctriviamctrivia Posts: 3,772
    edited 2009-04-03 00:49
    correct me if I am wrong but isn't signed and unsigned addition and subtraction the same. the only difference being the overflow flags

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Need to make your prop design easier or secure? Get a PropMod has crystal, eeprom, and programing header in a 40 pin dip 0.7" pitch module with uSD reader, and RTC options.
  • mparkmpark Posts: 1,305
    edited 2009-04-03 00:50
    "Propellerly" -- ha! Good one. Had to read it twice [noparse]:)[/noparse]

    $FFFF_FFFF is the same as -1 so I doubt that adding it to result will help much.

    What do you want to do with result?
  • Mike GreenMike Green Posts: 23,101
    edited 2009-04-03 01:18
    With an 80MHz clock, CNT rolls around in approximately 50 seconds. A 31 bit time is around 25 seconds. You can easily manipulate elapsed times up to about 25 seconds. Beyond that you get into the signed / unsigned arithmetic issue, particularly with Spin calculations all done with signed arithmetic (for comparisons mostly). If you need periods greater than 25 seconds or so, use double precision arithmetic, maybe with one long holding times up to 1 second and the other holding a count of the number of seconds involved.
  • KyeKye Posts: 2,200
    edited 2009-04-03 01:28
    Ah, but I'm just trying to get the time elasped,

    PUB timeSwitch(onTime, offTime) ' 5 Stack Longs
     
    '' &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
    '' &#9474; Switches the return value back and forth between true and false depending on the elasped time.                           &#9474;
    '' &#9474;                                                                                                                          &#9474;
    '' &#9474; Returns true when in on time and false when in off time.                                                                 &#9474;
    '' &#9474;                                                                                                                          &#9474;
    '' &#9474; OnTime  = On time for returning true condition in milliseconds.                                                          &#9474;
    '' &#9474; OffTime = Off time for returning false condition in milliseocnds.                                                        &#9474;
    '' &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
     
      result := (cnt - timeSwitchCounter)
    
      timeSwitchCounter := cnt
     
      if(result < 0)
        result += $FFFF_FFFF
     
      if(timeSwitchBuffer)
     
        if(result => (onTime * (clkfreq / 1000)))
          timeSwitchBuffer~
      else
     
        if(result => (offTime * (clkfreq / 1000)))
          timeSwitchBuffer~~
     
      return timeSwitchBuffer
     
    VAR
     
      byte timeSwitchBuffer
      long timeSwitchCounter
    


    This is the full piece of code.

    The code allows you to use the system counter to make a return value go from true to false on a set on seconds and offseconds·timer.

    The:

    · result := (cnt - timeSwitchCounter)

    · timeSwitchCounter := cnt

    · if(result < 0)
    ··· result += $FFFF_FFFF

    part is supposed to produce the true delta when looking at the delta that can occur in a circular counter, I then compare the delta with the time specified in milliseconds and flip the switch back and forth.

    I'm not trying to add -1, I'm trying to add (2^32 -1).


    Using this piece of code, it would be easy to make a blinking LED or feed a logical condition to any other method, the logical condition would then alternate within a specified time in ms.



    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,

    Post Edited (Kye) : 4/3/2009 1:38:21 AM GMT
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2009-04-03 02:04
    Kye,

    Adding $FFFF_FFFF is no solution.
    Here is an analysis for 16bit signed values, but the results also apply
    to 32bit values.
     * Timeout areas.
     * The following shows the different possibilities on start and stop being < 0 or > 0.
     * S marks start and P marks stop. Timeout time equals stop - start. A timeout occurs
     * whenever the current time is in a marked area.
     *
     *          S    P
     *     +----------------+----------------+      timeout if
     *     |////|    |//////|////////////////|      (curr >= stop) || (curr < start)
     *     +----------------+----------------+
     *     0             0x8000           0xFFFF
     *
     *          P    S
     *     +----------------+----------------+      timeout if
     *     |    |////|      |                |      (curr >= stop) && (curr < start)
     *     +----------------+----------------+
     *     0             0x8000           0xFFFF
     *
     *                             S    P
     *     +----------------+----------------+      timeout if
     *     |////////////////|//////|    |////|      (curr >= stop) || (curr < start)
     *     +----------------+----------------+
     *     0             0x8000           0xFFFF
     *
     *                             P    S
     *     +----------------+----------------+      timeout if
     *     |                |      |////|    |      (curr >= stop) && (curr < start)
     *     +----------------+----------------+
     *     0             0x8000           0xFFFF
     *
     *          S                  P
     *     +----------------+----------------+      timeout if
     *     |////|           |      |/////////|      (curr >= stop) && (curr < start)
     *     +----------------+----------------+
     *     0             0x8000           0xFFFF
     *
     *          P                  S
     *     +----------------+----------------+      timeout if
     *     |    |///////////|//////|         |      (curr >= stop) || (curr < start)
     *     +----------------+----------------+
     *     0             0x8000           0xFFFF
     *
     * Analyzing the above yields the following timeout test:
     *
     *     if (start < stop) timeout = (curr >= stop) || (curr < start);
     *     else timeout = (curr >= stop) && (curr < start);
     
    

    You need several functions:

      /**
       * Remember the current time and calculate the stop time.
       */
      public void mark(int timeout_ticks) {
        start = currentTick();
        stop = start + timeout_ticks;
      }
    

      /**
       * Get the number of passed ticks since the last call to mark().
       *
       * @return Passed time in ticks (unsigned)
       */
      public int passedTicks() {
        return currentTick() - start;
      }
    

      /**
       * Test for timeout using the start and stop time remembered
       * by the last call to mark().
       *
       * @return true if the timeout period has expired.
       */
      public boolean timeout() {
        int curr = currentTick();
        return (start < stop) ? ((curr >= stop) || (curr < start)) : ((curr >= stop) && (curr < start));
      }
    

    Sorry about the java but you should understand it.
    Replace currentTick() by CNT.
    Start and stop are global vars.

    regards peter

    Post Edited (Peter Verkaik) : 4/3/2009 2:21:00 AM GMT
  • KyeKye Posts: 2,200
    edited 2009-04-03 04:16
    Mmm, I'll just have to do it in asm, luckily I have the setup for that.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • CassLanCassLan Posts: 586
    edited 2009-04-03 04:37
    Wow thats some Crazy ASCII Diagraming...did you do that by hand? (Manually)?
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-04-03 20:01
    Hello Kye,

    some time ago I coded a elapsed_time-function

    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
    
      '#####################################################################################
      'explanatio how it works
      ' SPIN treats longs as SIGNED longs meaning bit 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
    
      'if the systemcounter has wrapped around since 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
      '#####################################################################################
    
    
    
    



    somebody else posted a VERY SHORT an elegant derivate for the calculating but I don't remember the name

    if you bitshift the countervalue one bit to the right the precision goes from one clocktick to two clockticks but then
    the bit no 32 = sign-bit is ALWAYS zero and all values stay positive
    the method above can handle the wrap around to zero

    best regards

    Stefan
Sign In or Register to comment.