PDA

View Full Version : Full Dup Serial question



T Chap
11-04-2006, 11:19 AM
If multiple methods/cog are using the ser.tx or ser.str, does the object manage what is received and send out in the order received?

The case would be two cogs want to ser.tx at the same time. I am trying to find a way to have several strings assembled together and send out, while maintaining each ones individual 0 termination so the receiver can split the parts. To have the receiver be able to identify what is coming in and write it to it's respective array or variable, this is the thought process although not execute yet until I see how the object will manage multiple sources of .tx or .str"

say Xcheck is a string(or already converted into an integer) that was just rec'd in the buffer among 3 other integers(Y,Z,R). I want to send those back where they cam from for error checking prior to any action. However, there may be a case where some activity is taking place where a cog(s) may be sending values independently of the error checking Tx getting sent. If in fact the Full Dup object can manage multiple sources of instructions, and tere will be cases where things are competing to get sent, I don't see a tidy way to simply send the error checking string out as it was received without first giving each part a unique identifier first, so that the receiver must first identify something in the batch of stuff, split it's part out and assign it back to some arrays as needed.... compare, and then resend a confimation. In other words this is a brain twister.

Here is a feeble attempt:

1. receive a string with 4 integers included
2. split the numbers out to X, Y, Z, R
3. Assemble a new string by some method:

TAB = $09
CR = $0D
ser.str("Xcheck" + TAB + X + TAB + "Ycheck" + TAB + Y + TAB + "Zcheck" + TAB + Z + TAB + "Rcheck" + TAB + R + CR)

4. The receiver looks for Xcheck, if true stores that whole string in an array ErrorCheck()

5. Split and compare the parts

On the right path or what?

Thanks

Mike Green
11-04-2006, 12:34 PM
The FullDuplexSerial object can only handle one COG putting stuff into a buffer or removing stuff from a buffer at a time. To share it among several other COGs, you'd have to use a semaphore (LOCKxxx) so that only one COG can access the buffer at a time. There really isn't a built-in way to assemble a string the way you're thinking, so just lock the transmit buffer access, then do a series of ser.str/ser.out/ser.dec, etc., then release the lock. If you need a bigger buffer, you can modify the FullDuplexSerial routines. They use a bit mask to wraparound the buffer pointer, so you'd need to go from 16 to 32 to 64, etc. You can do something similar on the receive end that can distribute different messages to different COGs. That's a whole 'nother reply.

Mike

T Chap
11-04-2006, 02:04 PM
There are 4 cogs running motors(send step outputs to = the X value), when they are done they send a ser.tx back to the app to say it is done, and how far it moved. The 4 cogs were talking all over each other, so I built a homemade Lock

This may not be kosher but here is my workaround I was about to test.




'codehere just finished sending out X steps
if S == 1
repeat while s == 1 'wait till it goes low by whoever has it high
s:= 1 'make it high again
ser.tx("x")
ser.tx(" ")
ser.tx(x)
ser.str("LED1") 'app scans for LED1 and turns on a fake LEd for feedback saying done
s:=0 'let somebody else have it now



Post Edited (originator99) : 11/4/2006 7:45:59 AM GMT

Cliff L. Biffle
11-04-2006, 02:15 PM
So, that'll be iffy because you've constructed what's called a read-modify write operation.

Between the time you check S the last time in "while S == 1" and the time you set it to 1, someone else may have already set it. In this case, both cogs would think they had set it to 1, and had taken unique ownership of it.

This will cause weird, difficult-to-track errors. (You think it's weird here, try it with a million processes.)

As Mike pointed out, use the lock operations in SPIN. You can use them exactly the same way you're using S -- there's an example in the manual that shows how. It's not complex, and it's the easiest way to do this sort of "in use" flag on the Propeller.

T Chap
11-04-2006, 02:35 PM
I will dig into the lock feature, but I had some unfounded thinking that even though there were all 4 separate cogs, that they still had to to get their turn at the variables to read or write. I'll take your advice though and adapt the lock implementaion.

So far it has solved the problem and my test feedback window that displays all incoming data to the app is now showing everything in order, not mangled parts thrown together like in a blender as before.

T Chap
11-04-2006, 03:24 PM
that lock trick was pretty simple, thanks for the tip

repeat until not lockset(SemID)

'read or write some shared junk

lockclr(SemID)

T Chap
11-04-2006, 05:20 PM
BTW Mike this does the job nicely to assemble the string from various parts:




ser.dec(x)
ser.tx(tab)
ser.dec(y)
ser.tx(tab)
ser.dec(z)
ser.tx(tab)
ser.dec(r)
ser.tx(cr)
ser.tx(0)




can be split as folows:



Xsplit = Split(RxData, CHR(9))
xsplit0.text = xsplit(0)
xsplit1.text = xsplit(1)
xsplit2.text = xsplit(2)
xsplit3.text = xsplit(3)

Cliff L. Biffle
11-05-2006, 12:37 AM
originator99 said...
I will dig into the lock feature, but I had some unfounded thinking that even though there were all 4 separate cogs, that they still had to to get their turn at the variables to read or write.


Not completely unfounded, actually -- taken literally, that statement is correct.

They have to get their turn at the variables to read or write -- but not both! A cog can read the variable and decide "Oh, great, it's clear! I will set it." Then it must wait its turn to set it -- and in the meantime, another Cog may have reached the same conclusion. *sad music plays*


originator99 said...
that lock trick was pretty simple, thanks for the tip

repeat until not lockset(SemID)

'read or write some shared junk

lockclr(SemID)


You nailed it. Good work! http://forums.parallax.com/images/smilies/smile.gif