Timing blocks of code with waitms in SPIN2

I'm using a P2 Eval board, revision C,
I'm expecting to see:
` set command mode.started: 30_000_000 microseconds
something just over 30 seconds
instead, I'm seeing
` set command mode.started: 1 microseconds
Code taken from the P2 Spin manual
{Object_Title_and_Purpose}
CON
_clkfreq = 250_000_000
_txpin = 16 + 6
PUB main() | time
time := getct()
pinlow(_txpin)
waitms(30_000)
pinfloat(_txpin)
time := getct() - time
time := muldiv64(time, 1_000_000, clkfreq)
debug("set command mode.started: ", sdec(time), " microseconds")
Comments
At 250 MHz, the number of ticks elapsed will exceed 32 bits in a bit over 16 seconds. So getct() alone will not be useful for timing intervals longer than that.
In addition to Eric's point about the getct() delta, the waitms() instruction is limited by the clock speed. This is from an article I wrote for Nuts & Volts magazine.
(https://www.nutsvolts.com/magazine/article/an-introduction-to-the-parallax-propeller-2)
For a 250MHz clock, the maximum delay will be about 8.589 seconds, or 8_589 milliseconds, or 8_589_934 microseconds (yes, I tested)
t := getct() waitus(8_589_934) t := getct()-t-40 term.dec(t/US_001)
The -40 accounts for the getct() instruction time. I have timing constants at the top of my programs that look like this:
con { timing } CLK_FREQ = 250_000_000 ' system freq as a constant MS_001 = CLK_FREQ / 1_000 ' ticks in 1ms US_001 = CLK_FREQ / 1_000_000 ' ticks in 1us _clkfreq = CLK_FREQ ' set system clock
@JonnyMac @cgracey : Does the standard PNut waitms() not handle long waits? It's not hard to make it work right up to 2 billion milliseconds (~23 days) by just waiting 1 second at a time, with the last one being a fractional second. With a bit of care about signed/unsigned arithmetic that can be doubled.
The current interpreter gets the clock frequency, divides by 1000 (waitms) or 1000000 (waitus) and then multiplies that by the user parameter for use by waitct. it's not ideal, but it's what we have.
' WAITUS(us) ' WAITMS(ms) ' waitus_ getct w 'get ct now to minimize error rdlong y,#@clkfreq_hub 'get clock frequency rep @.stall,#1 'use REP to stall interrupts to protect cordic operation qmul y,x 'multiply clock frequency by us/ms getqx x getqy y .stall cmp pa,#bc_waitus wz 'us or ms time unit? mov z,##1000 if_z mul z,z rep @.stall2,#1 'use REP to stall interrupts to protect cordic operation setq y 'divide by time unit qdiv x,z getqx x .stall2 add x,w 'add ct jmp #pwct 'do WAITCT
What do you think?
sample code of my stopwatch object. call sw.reset at the beginning of the code you want tested; use sw.elapsed at the end of the code you want tested...
sw.reset() pinlow(Txpin) waitms(500) pinfloat(Txpin) time_low, time_high := sw.elapsed()
The stop watch object
VAR long _low long _high PUB reset()| low, high ' Reset current start time org getct high wc getct low end _low, _high := low, high PUB elapsed() : low, high | c_low, c_high ' Get elapsed time c_low, c_high := _low, _high org getct high wc getct low sub low, c_low wcz subx high, c_high end PUB elapsedms() : low, high | c_low, c_high ' Get elapsed time in milliseconds (ms) c_low, c_high := _low, _high org getct high wc getct low sub low, c_low wcz subx high, c_high ' TODO: convert to millisecond (ms) end PUB elapsedmu() : low, high | c_low, c_high ' Get elapsed time in microseconds (mu) c_low, c_high := _low, _high org getct high wc getct low sub low, c_low wcz subx high, c_high ' TODO: convert to microseconds (mu) end
I wrote similar code a couple years ago -- before getms() was available in Spin2. Seeing your code I got mine back out and did a clean-up, especially as I have a new project coming that needs long-duration timing. What you call reset(), I call start(), and I allow an offset. In the P1 version of this code I have found it convenient to set a negative time duration and then while checking look for the timer to be 0 or higher. This object has delay routines that will break the ~10 second (at 200MHz) limit of the waitms() and waitus() instructions.
I run my P2 projects at 200MHz, hence the constants in the program that make calculating duration easy.
You might find some of this useful.