Logic timing in PASM
MacTuxLin
Posts: 821
My first dig at PASM due to requirement. The logic diagram is also attached. May I request anyone to see if I've made any stupid mistakes? Thanks.
Jon, if you see this, may I check with you, how do you set a constant number of #24 to account for the setup/call/return in the pauseus routine? Is it a common known value or how should I calculate it?
Jon, if you see this, may I check with you, how do you set a constant number of #24 to account for the setup/call/return in the pauseus routine? Is it a common known value or how should I calculate it?
' ----------------- ' Write Byte to device ' ----------------- owwrbyte rdlong value, iodata ' get byte from mov bitcount, #8 ' 8 bit counter wrloop shr value, #1 wc mov usecs, #26 if_c add usecs, #9 if_c jmp #:wronebit ' Logic 1 = low or dira, owmask ' Logic 0 = low call #pause434us andn dira, owmask ' Logic 0 = high call #pause434us :wronebit or dira, owmask ' Logic 0 & 1 = low call #pause434us andn dira, owmask ' High till end Time_bit call #pauseus djnz bitcount, #wrloop wrlong ZERO, cmdsel jmp #owmain ' --------------------- ' Pause in 4.34 microseconds ' --------------------- pause434us mov ustimer, cnt ' sync with system clock sub ustimer, #24 ' <-- account for setup/call/return, value is commonly known? add ustimer, four34ustix ' set timer for 4.29 us (remove 0.05 us for waitcnt) waitcnt ustimer, four34ustix ' wait and reload pause434us_ret ret ' --------------------- ' Pause in 1 microseconds ' --------------------- pauseus mov ustimer, cnt ' sync with system clock sub ustimer, #20 ' account for setup/call/return add ustimer, oneustix ' set timer for 1 us usloop waitcnt ustimer, oneustix ' wait and reload djnz usecs, #usloop ' update delay count pauseus_ret ret
Comments
The calculation of the delays is like that because we are in integer domain. So, only dividing by 1_000 (=> shift to ms) in the first step keeps as much digits as possible whilst avoiding an overflow.
( CLKFREQ/1_000_000 * time is the general formula, but does not work good in integer domain. )
This is the quick and dirty implementation, because in the long periode you add some time to the waitcnt for the code which runs until setting the next start-bit. But this should be deviation which does not make problems because we talk about <1us.
If you want it completely perfect you can simply move the waitcnt usecs to another position and do it after all the code that gets the next bit.
Thanks Mark. So that's why its #24.
Got it. Yes, I understand now. I'll implement delay calculation in this manner instead. Thank you MagIO2.
Hey Marko! Thank you but it took me quite a while to understand ... sorry I have some questions:
1. what does this means? I thought cnt is a register & cannot be used as a destination operand?
2. I like this!
3. I'm a little confused, when its logic 0:
4. I don't see how adding #0 to waitcnt means the tail is selected?
0.1 usecs ... yeah, sorry, when I started seriously digging into PASM a few days ago, I was abs(lost) but things are starting to fall into place and the more I dig the more I like PASM!
Note "shadow RAM' is the actual RAM location that exists at the cog memory address used for some register. There's a RAM location corresponding to each of the Prop's I/O registers, but they're only accessible under some circumstances because the I/O register takes precedence when processing the source field of an instruction. When processing the destination field of an instruction, the shadow RAM location is always written. The I/O register is read when it's read-write, but the I/O register is not used when it's read-only. Instruction fetches always use the shadow RAM.
So, does it explains the reason why Marko added #9 to factor in the cycle time for the previous MOV & this WAITCNT instructions so that the pulse duration is as accurate as possible?
So, is this shadow RAM something like cache? I won't get such jems from the manual ....
And don't confuse cog RAM with hub RAM (hub RAM is byte-addressed, cog RAM is long-addressed)
The manual does describe this as far as I remember (particularly in the descriptions of the various special registers).
In PASM waitcnt works slightly different (compared to SPIN that is). It waits for a match on its dst value, then adds src for the next match.
- we start with a minimal waitcnt (ref) and set the line low (advance by short)
- the next waitcnt will block until ref+short then we drive the line high (advance by short)
- next point is ref+2*short, we drive the line according to bit value (high/low) and advance by short
- next point is ref+3*short, we drive the line high and advance by tail
- if we loop the waitcnt at the beginning will make sure we wait until ref+3*short+tail
- if we exit we explicitly wait for the final target to be reached, we don't have to advance here
HTHAfter going thru your code for long while (including talking to myself), I finally understood =D !!! Thank you very much Marko! Yes, its a very different mind-set for me. Have a good weekend All.
Thank you Mark.