Waiting untill a certain time without using waitcnt, What am I doin wrong here??
In the following code I am trying to mark a point in time, then use a variable to mark 1 second past that point. i loop untill I reach the 1 second mark and increment TickCount. But It stops updating TickCount every few iterations, for a while, then continues. So what am I doing wrong, if not everything. Also what is the purpose of WMin in Clock.Spin (in obex)
My goal is to wait to do something until I reach a certain point in time without using waitcnt. I cant stop the cog.
EDIT: Solution is in Post #8 of this thread! Thanks Stefan.
My goal is to wait to do something until I reach a certain point in time without using waitcnt. I cant stop the cog.
EDIT: Solution is in Post #8 of this thread! Thanks Stefan.
{{
Continue through a loop until a certain amount of time has passed
without pausing or stopping the cog using waitcnt.
using code samples from "Clock.spin V1.1" by Jeff Martin in obex
-----
}}
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
WMin = 381 ' in Clock.spin ?? What is this for?
OBJ
' T : "Clock"
Debug : "Parallax Serial Terminal"
VAR
long Now, StartPoint, EndPoint, SyncPoint, LoopNum
byte TickNum, HitMark
PUB Main
Debug.start(115200)
Now := 0 ' the current point
StartPoint := 0 '
EndPoint := 0 ' the point equal to 1 second past SyncPoint
SyncPoint := 0 ' stores the point to sync to
LoopNum := 0 ' stores the number of time we have looped so far
TickNum := 0 ' stores how many times we hit the EndPoint
HitMark := 0 ' stores 0 or 1 to indicate if we hit the mark
repeat
LoopNum++
if SyncPoint == 0
' were at the beginning of the program
MarkSync ' sets SyncPoint
StartPoint := GetSync
EndPoint := StartPoint + (clkfreq * 1) #> WMin '??? one second from now??????
Now := cnt
else
' were in progress
if Now => EndPoint
' reset values and update the tickNum
Now := 0
StartPoint := 0
EndPoint := 0
SyncPoint := 0
TickNum++
HitMark := 1
else
HitMark := 0
Now := cnt
SendIt
PUB SendIt
NewLine
Seperator
NewLine
Debug.Str(String("StartPoint is: "))
Debug.Dec(StartPoint)
NewLine
Debug.Str(String("EndPoint is: "))
Debug.Dec(EndPoint)
NewLine
Debug.Str(String("Now is: "))
Debug.Dec(Now)
NewLine
Debug.Str(String("LoopNum is: "))
Debug.Dec(LoopNum)
NewLine
Debug.Str(String("TickNum is: "))
Debug.Dec(TickNum)
NewLine
Debug.Str(String("HitMark is: "))
Debug.Dec(HitMark)
PUB NewLine
Debug.NewLine
PUB Seperator
Debug.Chars($2D, 25) ' print 25 hyphens
PUB MarkSync
{{Mark reference time for synchronized-delay time windows.
Use one of the WaitSync methods to sync to start of next time window.
}}
SyncPoint := cnt
PUB GetSync
return SyncPoint
PUB WaitSyncSec(Width)
{{Sync to start of next second-based time window.
Must call MarkSync before calling WaitSyncSec the first time.
PARAMETERS: Width = size of time window in seconds.
}}
SyncPoint += (clkfreq * Width) #> WMin
Comments
VAR long Now, StartPoint, EndPoint, SyncPoint, LoopNum, TickNum byte HitMark
So should I shift right all negative values? Will that correct it or introduce some other error? I will play around with it a bit more, I'm just a bit bugged out on this, no puns intended.
cnt is an unsigned int but the => and <= work on signed numbers. You need to subtract the current time from the start time and then compare that to the timeout time. This subtraction will "convert" your unsigned cnt values to a signed result. You'll need to do something like this to avoid the problem with negative numbers. This still has the 53 second limit that was mentioned earlier.
timeout:=4 ' number of seconds allowed to elapse before continuing sTime := cnt repeat 'do some other things eTime := cnt until (eTime - sTime ) > (timeout * clkfreq)
I'm writing this with a 1 year old on my lap (who isn't very happy by the way). It's the right idea but might need some tweaking. The problem is it may not keep you synced. You can change the until line so that it exits the repeat loop once it is within some small amount of time of the timeout value. For example test to see if you are within 10milleseconds of the timeout. If you are DON'T repeat; exit at that point into a waitcnt where you wait for the exact timeout value. If you do this be sure the code you call when you have not timed out executes in less time than your window. In my example it would have to be less than 10 milliseconds, otherwise you could miss your timeout window and end up back in the loop where you don't want to be.My project link - http://forums.parallax.com/showthread.php?134537-PPDB-Using-the-full-PPDB-Updated-Code-Version-1.4
every 200 msec or every 10 seconds etc. I use this code that is attached to this posting.
The method is called elapsed_time_msec it just needs one long per timer and if timeevent has occured a line of code
CntSnapShot := CntSnapShot + WaitTimeTicks
to "start" timer again
The method takes care of the systemtimer-rollover from max to zero and sign-changing through that
see comment inside method elapsed_time_msec. The waiting-period can go up to 26 seconds.
For longer waitingperiods I would set up a counter variable that is counting seconds.
keep the questions coming
best regards
Stefan
I will check it out later tonight. I'm off to to catch some z's. I'll post updates and mark this thread solved then if I get it working.
Thanks again for your pointers, tips, and samples.
This is exactly what I was trying to do, I will mark this thread as solved! I would like to add credits in the project I use this in for the person who wrote the code, is it yours Stefan?
Anyways, this will help me reduce the led flicker of the display, in my above stated project, by helping me skip the RTC reads wile updating the display. I am sure it will, when I get that far, help me with reading a GPS, connected to a uM-FPU V3.1 over I2C, every few seconds or at the push of a button on the 4x4 Matrix keypad.
This is very helpful to me!
hmmm, Should I revert to unsolved until I test this more thoroughly? Or Should I continue with my own messy code and try shifting right negative values? Or, how, in my code, can I unsign the values, I'll take a look at some more math objects to see if I can find something....
P.S. Why do people say CNT is an unsigned quantity? Clearly when used in in Spin (in comparisons) it can only ever be signed. Perhaps it's just counting in an odd order.
' elapsedTime := elapsed_time_msec(CntSnapShot) ' old elapsedTime := (cnt - CntSnapShot) / (clkfreq / 1_000) ' new
very compact solution.
question: why do you not add examples with concrete numbers to show how it works?
maybe then I would have remembered it from the last time.
DAT { before after (26s) elapsed (after - before) $00000010 +/+ $7BFA4810 $7BFA4800 $7FFFFFF0 +/- $FBFA47F0 $7BFA4800 $80000010 -/- $FBFA4810 $7BFA4800 $FFFFFFF0 -/+ $7BFA47F0 $7BFA4800 (26s @80MHz) }
It will still work for what I need, If I need to keep track of lets say 1 minute with Stefan's code, I can just add an additional variable to store a count of when I hit the 20 second mark 3 times. Shouldn't that solve the ~53 second hiccup too?
Thank you for pointing out this information, without it I may have not realized it later when I least expect it! Maybe once FirstSpin.tv gets to discussing code timing later in their discussions, they can point out these things to their listeners.
Can someone explain in more of a lengthy detail as to why/how this all happens?
-- http://www.parallax.com/Portals/0/Downloads/docs/cols/nv/prop/col/nvp7.pdf