PDA

View Full Version : Can I do this in spin?



Kye
04-03-2009, 07:34 AM
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,

mctrivia
04-03-2009, 08:49 AM
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 (http://propmodule.com) has crystal, eeprom, and programing header in a 40 pin dip 0.7" pitch module with uSD reader, and RTC options.

mpark
04-03-2009, 08:50 AM
"Propellerly" -- ha! Good one. Had to read it twice :)

$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 Green
04-03-2009, 09:18 AM
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.

Kye
04-03-2009, 09:28 AM
Ah, but I'm just trying to get the time elasped,



PUB timeSwitch(onTime, offTime) ' 5 Stack Longs

'' ┌───────────────────────────────────────────────── ────────────────────────────────────────────────── ───────────────────────┐
'' │ Switches the return value back and forth between true and false depending on the elasped time. │
'' │ │
'' │ Returns true when in on time and false when in off time. │
'' │ │
'' │ OnTime = On time for returning true condition in milliseconds. │
'' │ OffTime = Off time for returning false condition in milliseocnds. │
'' └───────────────────────────────────────────────── ────────────────────────────────────────────────── ───────────────────────┘

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 Verkaik
04-03-2009, 10:04 AM
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

Kye
04-03-2009, 12:16 PM
Mmm, I'll just have to do it in asm, luckily I have the setup for that.

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

CassLan
04-03-2009, 12:37 PM
Wow thats some Crazy ASCII Diagraming...did you do that by hand? (Manually)?

StefanL38
04-04-2009, 04:01 AM
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