My 1st PASM Snippet (which doesn't work). Help?
But at least it compiles...
I'm working on a routine that interprets 24 bits of gated synchronous serial data. Spin doesn't seem to be fast enough to catch the clock edges so I thought I'd try to do the input side in PASM before wimping out and adding a hardware shift register.
After browsing and swiping a lot of the examples found here, I came up with this:
The glitch is that datin is forever 0. The ADD line is definitely suspect, but the whole attempt may be riddled with mistakes and misinterpretations...can't tell.
If someone could kindly point out the folly of my ways, I'd be ecstatic. Any other comments or criticisms would certainly be welcome too.
As an aside, I sure wish that the ASM section of the manual contained as many command usage examples as the SPIN section. But I think I understand why it doesn't...
I'm working on a routine that interprets 24 bits of gated synchronous serial data. Spin doesn't seem to be fast enough to catch the clock edges so I thought I'd try to do the input side in PASM before wimping out and adding a hardware shift register.
After browsing and swiping a lot of the examples found here, I came up with this:
VAR
long datin '24 bits of incoming serial data
'lots more variables
Pub main 'Main loop
dira[3]~
dira[9]~
dira[10]~
cognew(@input,@datin) 'launch data input routine (ASM)
'oodles of non-relevant code
'the datin variable gets sent out via RS-232.
dat
org 0 'Begin at cog addr 0
input mov p,par 'p=address of datin variable in hub
:loop waitpeq state0, #mask0 'wait for A0 (P3) to go high
mov count, #24 'set loop counter to 24
mov in, #0 'reset input variable
jmp #:loop1 'do the loop1 routine. Necessary?
:loop1 shl in, #1 'shift input variable left 1 bit
waitpeq state1, #mask1 'wait for clock (P9) to go high
add in, ina&mask3 'capture level of data pin (P10)
waitpeq state1, #mask2 'wait for clock (P9) to go low
djnz count, #:loop1 'loop until count=0
jmp #:writemem 'do writemem routine. Necessary?
:writemem wrlong in, p 'write input data to datin variable
waitpeq state0, #mask2 'wait for A0 (P3) to go low
jmp #:loop 'goto beginning of loop
state0 long %0000_0000_0000_0000_0000_0000_0000_1000
mask0 long %0000_0000_0000_0000_0000_0000_0000_1000
state1 long %0000_0000_0000_0000_0000_0010_0000_0000
mask1 long %0000_0000_0000_0000_0000_0010_0000_0000
mask2 long %0000_0000_0000_0000_0000_0000_0000_0000
mask3 long %0000_0000_0000_0000_0000_0100_0000_0000
p res 1
count res 1
in res 1
The glitch is that datin is forever 0. The ADD line is definitely suspect, but the whole attempt may be riddled with mistakes and misinterpretations...can't tell.
If someone could kindly point out the folly of my ways, I'd be ecstatic. Any other comments or criticisms would certainly be welcome too.
As an aside, I sure wish that the ASM section of the manual contained as many command usage examples as the SPIN section. But I think I understand why it doesn't...

Comments
>add in, ina&mask3
You can not use pre calculation in pasm, the ide will do the math on this and put a number there.
One of the pitfall of learning Pasm is what is pre inline math and what is runtime math.
test mask3, ina wc if_c add in, #1waitpeq state, #mask
or
waitpeq state, mask
?
wouldn't that count the number of bits set in the input? - Edit: nevermind, I spaced out on the shl command.
Here's my very quick and untested take on the problem:
DAT org input mov count,#24 ' count 24 bits mov in,#0 ' initialize the in register waitpeq P3,P3 ' wait for P3 to go high :loop waitpeq P9,P9 ' wait for P9 to go high test ina,P10 wc ' test the state of P10, set C if input is high rcl in,#1 ' rotate C into the in register waitpne P9,P9 ' wait for P9 to go low djnz count,#:loop ' loop 24 times :writemem wrlong in,par ' write the in register to the address in par waitpne P3,P3 ' wait for P3 to go low jmp #input P3 long 1 << 3 P9 long 1 << 9 P10 long 1 << 10 count res 1 in res 1I implemented it but the routine still doesn't function as desired.
Is it time to procure a copy of ViewPort? Will that tell me what's going on in there?
Using Chris's myriad of tricks and shortcuts and architectural finesse, and Jon's pin level detection snippet, it works. Probably. I'll know when I start to parse the data at the other end. But it certainly works better than it did. Here's what I ended up with:
DAT org 'get 24 bits of serial in input mov count,#24 ' count 24 bits mov in,#0 ' initialize the in register waitpeq P3,P3 ' wait for P3 to go high :loop shl in, #1 'shift input long left 1 bit waitpeq P9,P9 'wait for P9 to go high test P10, ina wc 'check level of data pin (P10) if_c add in, #1 'if it's high, add 1 to input variable waitpne P9,P9 'wait for P9 to go low djnz count,#:loop 'loop 24 times :writemem wrlong in,par 'write the in register to the address in par waitpne P3,P3 'wait for P3 to go low jmp #input 'back to beginning P3 long 1 << 3 P9 long 1 << 9 P10 long 1 << 10 count res 1 in res 1Thanks, guys.
I had some fun seeing what I could do with ViewPort and your code....
Here's your code with some additional spin code to repeatedly send data to be decoded.
var long out 'data sent out long inp 'result decoded in pasm pub main cognew(@input, @inp) repeat repeat out from 0 to 10 send(out) waitcnt(cnt+clkfreq) pub send(x) 'output 24 bits using p3,p9,p10 dira[3]~~ dira[9..10]~~ outa[3]~~ 'indicated 24 bits are coming repeat 24 if(x & (1<<23)) 'ready data bit outa[10]~~ else outa[10]~ x<<=1 outa[9]~~ 'pulse data is there bit outa[9]~ outa[3]~ DAT org 'get 24 bits of serial in input mov count,#24 ' count 24 bits mov in,#0 ' initialize the in register waitpeq P3,P3 ' wait for P3 to go high :loop shl in, #1 'shift input long left 1 bit waitpeq P9,P9 'wait for P9 to go high test P10, ina wc 'check level of data pin (P10) if_c add in, #1 'if it's high, add 1 to input variable waitpne P9,P9 'wait for P9 to go low djnz count,#:loop 'loop 24 times :writemem wrlong in,par 'write the in register to the address in par waitpne P3,P3 'wait for P3 to go low jmp #input 'back to beginning P3 long 1 << 3 P9 long 1 << 9 P10 long 1 << 10 count res 1 in res 1This is what it looks like in ViewPort:
Pressing "Run" will run the code and show you variables "inp" and "out":
So far we haven't instrumented our code for ViewPort. You can confirm that your code is successfully decoding different numbers by seeing both inp and out change in realtime.
You can use the LSA view already to look at the pin activity, but by letting ViewPort instrument our code and using quickstart we view the pin activity at a faster rate- up to 80msps.
Here's the instrumented code:
Here's the LSA view showing p3 being high, p10 corresponds to the data, and p9 clocking out the data:
Hanno