Any elegant implementations of a timer in SPIN?
ags
Posts: 386
I've found cases where I'd like a timer in SPIN. Consider the case of waiting for some asynchronous user input. I'd like to set a timer (value should be a configurable parameter) when I first begin waiting for input so that I can detect a timeout condition and exit the input polling loop rather than waiting indefinitely. I am guessing there are more elegant ways of implementing this than what I've done. (In fact, I'm betting there is a simple and obvious solution that I just don't see) I'm currently using a brute-force method that handles each of four separate cases depending on whether the current system clock counter value and "future time" clock counter value are greater than or less than 0 (since the comparison is done using signed 32 bit values) and if the "future time" when the timer will expire constitutes a counter rollover. (Four cases: now>0 and future>0; now<0 and future<0; now>0 and future<0; now<0 and future>0). Or, is there an unsigned compare available in SPIN? [Clarification: for now, the timer value is limited to less than the time for the system counter to cycle once, ~52 seconds]
Comments
https://forums.parallax.com/discussion/143731/hostname-expired-ip-stil-working-dhcp-renew-leastime
Is it a typo having the assignment operator ':=' in the repeat code?
Not sure how that would evaluate...
Nate
-Phil
On the one hand, I could say that it's a lucky artifact of the way subtraction (or more accurately, addition of signed values) works, and overflows. But that seems like saying it's lucky that pants have two legs so they can be used to cover my lower half. I understand ones and twos complement representation. What isn't obvious to me is how subtracting any two values from a discontiguous sequence of numbers always results in a value that is the "shortest distance" between the values (when viewed as if the sequence was not a line but a circle wrapping back on itself). I see that given any two signed values, value1 - value2 will return a positive value if value1 is "closer" to value2 if counting from value2 up to value1 (allowing for overflow/wraparound at -1 -> 0) and a negative value if value1 is "closer" to value1 if counting from value2 backwards to value1 (with overflow/wraparound at 0 -> -1).
Clearly there is some proof, theorem, or basic property of twos complement representation that can explain this concisely (but I can't articulate it myself).
Also: I note that each of the examples cited above use "currentTime-timerTime > 0" for the test; it seems more correct to me to use "currentTime-timerTime => 0". I checked all the corner cases I could think of and this still works, but exits the loop as soon as the stop time (timer value) is reached. Any reason to use ">" instead of "=>"?
Along the same lines, my implementation is much like the example from lonesock (for the same reason - do the calculation of "timerTime" once then have a simple test loop). Any reason why this is not preferred? -
The point being that "timerTime := cnt + clkfreq/1000*millis" captures the begin time (in cnt) earlier than "timerTime := clkfreq/1000*millis + cnt" (assuming left-to-right order of evaluation) and therefore starts the timer sooner.
Interesting how much detail there is to understand for such a very simple task. Thanks for the replies.
Massimo
The outstanding questions (simplified - see post #8 for full text) are:
1) Can anyone explain the fundamentals of why this works? I have proven to myself that it does, but it can't be a coincidence.
2) Any reason why the comparison uses "> 0" instead of "=> 0" ?
@Ding-Batty: looks like you spent some time determining precise # clocks...
2) The difference between >0 and =>0 is exactly 12.5 ns with 80MHz clock. It's just a definition: Is it a timeout if you reach the time or if you are over the time?
1) It works because you subtract two 32bit numbers and get again a 32bit result. It's some kind of subtract with modulo.
The subtract operation for signed and unsigned numbers is exactly the same, the only difference is how the Carry (Borrow) is handled (and how the result is interpreted). Here we ignore the carry flag anyway.
Andy