Assembly "waitcnt"
parsko
Posts: 501
Hello all,
Is the assembly instruction sequence:
The same as the following Spin instruction:
I keep reading and interpreting the assm. "waitcnt" to mean that it only aligns the assm. routine with "cnt", but not execute a pause in the COG operation.
Otherwise, would it look more like this, (which is how I can think to code it with my interpretation):
Unlitmately, I need to pause the COG for "period" clocks.
Thanks again. Never learned assm. My ears are still drenched!
-Parsko
Is the assembly instruction sequence:
add time,cnt waitcnt time,period time long period long 100
The same as the following Spin instruction:
waitcnt (100 + cnt)
I keep reading and interpreting the assm. "waitcnt" to mean that it only aligns the assm. routine with "cnt", but not execute a pause in the COG operation.
Otherwise, would it look more like this, (which is how I can think to code it with my interpretation):
mov time,#0 'Zero out time add time,cnt 'Add current cnt value to time add time,period 'Add period to wait to time waitcnt time,#0 'Wait until cnt = time = 0+cnt+period
Unlitmately, I need to pause the COG for "period" clocks.
Thanks again. Never learned assm. My ears are still drenched!
-Parsko
Comments
[noparse][[/noparse]code]
· mov· time,#500
· add·· time,cnt
··waitcnt time,#510
· ...
· waitcnt time,#510
is roughly equivalent to
· time := 500 + cnt
· waitcnt(time)
· ...
· waitcnt(time += 510)
[noparse][[/noparse]/code]
The reason is that, in assembly, the 510 gets added after the waitcnt, while in SPIN, the 510 gets added before the total is used for the waitcnt.· There's an operator in SPIN to increment by 1 after using the old value, but there's no way to increment by something else (like 510) while using the old value in the calculation (like as the value for waitcnt).· In SPIN, the "time" value is always the last value used for waiting.· In assembly, the "time" value is the next value to be used for waiting.· If you're doing a sequence of "waitcnt"s with different pauses, you always have to plan for the next pause, while, in SPIN, you can deal with the present pause.
Post Edited (Mike Green) : 8/2/2006 6:37:54 PM GMT
I would be correct is saying that:
Will yield a pause of 510 clocks? Actually, it should be about 514 if you add the command, I think.
If I were to write:
Will yield, first, a pause of 510 clocks, then a pause of 900 clocks?
-Parsko
Your second example is not quite correct. The first pause is at an absolute time of 510 cycles from the add instruction. The second pause is at a time interval of 900 cycles from the add instruction, but 390 cycles from the previous waitcnt. Both the 390 and the 510 are relative times, first from the access to cnt, then from the first waitcnt. The waitcnt essentially waits until an absolute time mark occurs (with the value wrapping around every 2^32 clock cycles).
Okay, I think I get it now. I will obviously have to experiment, but you have finally explained it in a manner my pee-brain can understand! Thank you (for the nth time!).
Hey, if you're bored, I have started to write my SPI assembly routine. It's about 80% done, I have to check values and stick the variables in there, and add "DAT" line, but the code is there. It won't compile, but you'll start to see what I'm doing.
You have been paramount to the attached file, Mike!
Time to hit the hey. P-R-O-G-R-E-S-S!!!! It helps me sleep at night.
-Luke
In the comments field·I have added the absolute clock cycle count (value of "cnt").· Are my times·correct?·
I'm sorry to keep asking, but I keep getting unpredictable waitcnt instructions.· Since I don't fully understand, I will keep asking for spoon fed answers...
Thanks,
-Luke
Why the "add Delay,#18" "sub Delay,#18"? The following waitcnt is going to absorb the time these instructions use since it's based on waiting for an absolute time tick.
I didn't check your numbers carefully, but they seem to be "in the ballpark".
Usually in coming up with an initial time value, the CNT is added last. It makes it easier to see just where the time is counted from. In your case, you'd have: "mov Time,#29" "add Time,cnt". I know that puts the time a little further into the future, but you don't want to accidentally cut it too close and have to wait for another 2^32 cycle. If your initial SCL edge has to be really close in relation to entering the loop, you may not want to use an initial waitcnt for the timing.
The "add delay,#18" and "sub delay, #18" were simply to test the requirement for having the previous "add Time, #21". I think it is supposed to be 29, but I was working from memory. I could remove them, and reduce this by 8, since it is 4 clocks each for ADD and SUB. Then it would be okay, but that isn't my question (good catch though!)
I am mostly looking to confirm the timing of the waitcnt command. I am not sure if it executes the proceeding "xor outa, Pin" command first, or waits for the WAITCNT to finish before executing the "xor outa, Pin" command.
Also, if it is the case that it waits to execute the "xor outa, Pin", then if "Time" is not reset to zero, there could be a point when the square wave goes to "infinity" then resets itself to 0, and cause the loop to fail. Notice that the value of Time keeps increasing in my sample code breakdown. Is that true?
-Luke
2) Using the increment feature of the waitcnt instruction, Time indeed keeps increasing. The value will wraparound at 2^32 as will CNT since they're all 32 bit values. Since the test in the waitcnt instruction is for equality, the wraparound is not a problem
3) Think of instruction execution as even marks on a paper tape. The waitcnt instruction is a little piece of elastic between two marks. There's a pin board with evenly spaced pins marked with successive 32-bit integers (CNT). You place the paper tape over the pins. When you find a waitcnt instruction, you have to see what's in the Time register and stretch the waitcnt until its hole goes over the appropriately numbered pin, then continue with the other holes/pins in order until the next waitcnt.
As Mike says you have to be careful not to wait for a time that has passed, I ended up adding limits to the minium times that could be set for on and off times.
Graham
You're a rock star too. <<Pertinent tangent: I bought my lady a nice pair of wireless headphones so I can PAY ATTENTION when I am playing with this stuff and not hear the TV>> So, I've been playing with the waitcnt command tonight, and making progress. I find that, all you need to do is initialize it to zero, add cnt to the value. When it is called, "waitcnt wcnt, Delay" it simply pauses the amount of the delay, no matter what. I could be wrong, but it's working for me consistently (finally). If (after a pin toggle) I do another "waitcnt wcnt, Delay2" it will pause for the delay2 value. Loop this, and it toggles and pauses expectedly.
The short version of what I'm saying looks like this...
My O-scope is still toggling with my values as I type, and has been for the better part of the last hour.
Honestly, I still cannot see the correlation between the Prop Manual "waitcnt" description and reality. So, I hope Parallax can clarify this to us assembly beginners, it would make a HUGE difference. With that said, I am continuing with my SPI object knowing that the delays should work... fingers crossed!
-Parsko
"First assembly example in manual provided inspiraton along with much staring at how mouse.spin works"
lolololo!!!!!!!!!!!
Great man, I've been bug-eyed myself over this!
-Parsko
I say roughly because I don't remember at which cycle the waitcnt hangs, the 2nd or 3rd. This is important here because
it affects how many clocks there is left in the waitcnt after execution continues. The clock counts those cycles so you need
to know that to know precisely what value CNT has when the next instruction begins. Similarly, I don't remember which
cycle is used to fetch the CNT value in the add instruction. Again, that sets the clock value used to calculate the delays.
You start by setting the wcnt to some number that is cnt plus a bit then the first "waitcnt wcnt delay" will wait until cnt = wcnt
it will then add delay to the wcnt automatically so that the next waitcnt command will have the new target of wcnt = wcnt+delay.
So in your code Parkso your delay is really your delay2 and your delay2 your first delay except on the first occasion when the delay is 13, clear [noparse]:)[/noparse]
Graham