Shop OBEX P1 Docs P2 Docs Learn Events
Looking for a good prop<->prop example project - Page 4 — Parallax Forums

Looking for a good prop<->prop example project

124

Comments

  • idbruceidbruce Posts: 6,197
    edited 2011-01-22 06:28
    Jon

    That was a pretty cool sample.

    I had one of those aha moments last night. While you, Kuroneko, and I were discussing this, he posted this source:
    repeat
      fds.dec(fds.rx)
      fds.tx(32)
    

    At first it didn't work, but then I retried, and it worked. So that was my first awakening. Then the night before last, he provided some other source code, at the time I thought it was interesting, but I truly didn't understand the significance of it or what he was truly trying to demonstrate to me. After I got the repeat above to function properly, I reviewed his prior code more thoroughly, and by altering values in that code, I now have a much more thorough understanding of what is actually happening and what I need to do to accomplish the communications I seek. From your source I was learning displaying and parsing the communications, and from his I was learning the communication protocol. I needed to understand both yours and his samples to get a good grasp on things. And I think I am truly getting there.

    I think my main problem now is attaching the CRC data and testing that. And I think it all boils done to what is the best way to do it.

    The main message as you know is <stx><command><command param><etx>

    However adding the CRC data is another issue, as Dave Hein just informed me the CRC could also contain stx or etx. Besides resolving that possibility I am wondering whether to format the transmission as:

    <stx><command><us><crc><us><command param><us><crc><etx>

    or

    <stx><command.command param><us><crc><etx>

    I would imagine that the later example would execute much faster, but it would give me an extra parsing operation of finding the period and seprating the command from the command parameter, but that should not be a problem as your code clearly demonstrates.

    Anyhow, I truly appreciate the source code that you have provided, and the patience that you and Kuroneko have had with me in this matter. I know that I have been thick headed with it, but I was just having trouble grasping the whole picture.

    Thanks Jon

    Bruce
  • kuronekokuroneko Posts: 3,623
    edited 2011-01-22 16:38
    idbruce wrote: »
    However adding the CRC data is another issue, as Dave Hein just informed me the CRC could also contain STX or ETX.

    That's easy enough to deal with. Just encode the 16 bit value into 24 bit and make sure that you never generate bytes that contain STX or ETX. Attached is an example (which borrows the encoding from UTF-8 with the exception that the encoding isn't minimal, i.e. always 3 bytes). The core functions encode a 16 bit CRC into a 24 bit STX/ETX-free CRC and vice versa.
    CON
      crc_head = %1110_0000                                 ' 4 bit tag, 4 bit payload
      crc_msk4 = %0000_1111                                 ' payload mask
      crc_tail = %10_000000                                 ' 2 bit tag, 6 bit payload
      crc_msk6 = %00_111111                                 ' payload mask
      
    PRI encodeCRC(crc16) : crcEN
    
      crcEN.byte[0] := crc_tail | crc_msk6 &  crc16         ' %----------------10cccccc
      crcEN.byte[1] := crc_tail | crc_msk6 & (crc16 >> 6)   ' %--------10cccccc--------
      crcEN.byte[2] := crc_head | crc_msk4 & (crc16 >> 12)  ' %1110cccc----------------
      
    PRI decodeCRC(crcEN) : crc16
    
      crc16 |=           crc_msk6        & crcEN            ' %----------cccccc
      crc16 |= (constant(crc_msk6 <<  8) & crcEN) >> 2      ' %----cccccc------
      crc16 |= (constant(crc_msk4 << 16) & crcEN) >> 4      ' %cccc------------
    
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 03:36
    Marko

    Sorry it took so long to get back to you on this, but I had other chores to do for a day. That sounds excellent.
    The core functions encode a 16 bit CRC into a 24 bit STX/ETX-free CRC and vice versa.

    Okay, so first I create the 16 bit CRC using the ComputeCRC, and then I run it through encodeCRC, to make it STX and ETX free?

    Bruce
  • kuronekokuroneko Posts: 3,623
    edited 2011-01-23 03:40
    That's the idea (and only one of many ways of doing it). Once you have the 24 bit value you still have to decide in which order to send the bytes (I'd start with %1110xxxx followed by %10xxxxxx) but in the end it isn't really important as long as the parameters for en/decoding are in the right format.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 04:07
    Marko

    I still have a lot of studying to do, pertaining the samples that you and Jon have provided. Windows and Perl programming was so much easier for me than this stuff :) There was an enormous amount of information available from which to learn and study. However, with your's, Jon's, and Dave Hein's examples and assistance, I believe I should have ample information at this point to accomplish a nice serial comm setup, but I truly don't believe that it will be done overnight :( There is still a lot of studying and testing to do.

    Marko, is your previous code example open source?

    Anyhow, I truly appreciate your help Marko. I would have been truly lost without your's and Jon's assistance.

    Bruce
  • kuronekokuroneko Posts: 3,623
    edited 2011-01-23 04:14
    idbruce wrote: »
    Marko, is your previous code example open source?

    Feel free to ab/use it as you see fit.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 04:21
    Marko

    I was wondering where Chigasaki was located, so I looked it up. It is actually a pretty decent sized city. So do you have one of those magnificant ocean views?

    Bruce
  • kuronekokuroneko Posts: 3,623
    edited 2011-01-23 04:41
    Not quite but it's only about 10 min walk to the beach (basically we don't live high enough to see the ocean). What I do see nearly every day is Mt Fuji.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 04:43
    Marko

    Is it a nice place to live? I always liked mountains and the ocean.

    Bruce
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 16:27
    Kuroneko

    After a discussion with Heater, I came up with a way to bypass the possible interference of parsing for ETX and getting the CRC. However, now I am having trouble getting good CRC values and comparing them. I think it is because of the BUFFER_SIZE declarations.

    Could you please take a look at the following attachment, and possibly tell me what I am doing wrong.

    Bruce
  • kuronekokuroneko Posts: 3,623
    edited 2011-01-23 16:59
    When sending the message you calculate the wrong CRC. ComputeCRC(@DataString, DataSize) should be used witout @. On the receiver side you reuse Index which means your CRC re-calculation on the payload goes wrong. Use ComputeCRC(@MessageBuffer, strsize(@MessageBuffer)) instead. One remaining issue is that the CRC is missing a byte for as yet unknown reasons. I report back.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 17:01
    Thanks Marko

    You are a very good and kind person :)

    Bruce
  • kuronekokuroneko Posts: 3,623
    edited 2011-01-23 17:06
    kuroneko wrote: »
    One remaining issue is that the CRC is missing a byte for as yet unknown reasons.
    REPEAT WHILE (Char := Receiver.Rx) <> US
        MessageBuffer[Index] := Char
        Index++
    
    ' [COLOR="red"]REPEAT UNTIL Receiver.Rx <> US[/COLOR]
      Terminal.Str(string("Unit seperator has been bypassed", CR))
    
    The red line is not required. The repeat loop right in front already consumes the US.

    That said, I don't quite see the advantage of an ASCII CRC but in the end that's your decision.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 17:30
    Marko

    That's beautiful Marko!!!!!!!!!!!!!

    Now I can go forward. THANK YOU VERY MUCH!!!!!!!

    Is the crc providing error checking for me? I am no expert, but I read that it did. At this point in the program, I would send an ACK back to the sender to indicate that the data was valid, and then both Props could proceed with other tasks. If what I read was correct, you got to keep in mind that these are machine instructions that I will be passing, I can't have errors in my instructions, because I don't want to babysit the machine.

    Thanks Marko
    Bruce
  • kuronekokuroneko Posts: 3,623
    edited 2011-01-23 17:41
    That's not what I meant. Lets say the CRC is $FFFF, so the tail of the message is sent as "65535", US, ETX (ASCII encoded). That's 5+2 bytes. If you were to get more comfortable with binary data you'd send 3 bytes + ETX ($FFFF encoded is $EFBFBF) i.e. $BF, $BF, $EF, ETX. On the receiver side you simply know that you should expect 3 bytes after the US and before ETX. I modified your example for binary transfer.

    I mean with the current code, how are you going to compare the CRC values?
  • $WMc%$WMc% Posts: 1,884
    edited 2011-01-23 17:53
    Have you thought of dropping the crc gimmick?
    '
    Most INTERNET protocols have dropped it,
    '
    I would use a NODE set-up, But there might be something I'm missing that your trying to do.
    '
    I use a NODE set-up, I send the data packet twice. the NODE I sent it to looks at the two packets and if they are the same =, They run the instruction, If the packets aren't = they request another packet send.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 18:08
    @Marko - I don't know the answer to your last question. I wish I knew that stuff but I don't. I looked at the code, but I don't understand it. With the code you suggest, how will I compare those values?

    @Walt - Good evening. At this point I am a man on a mission. This is not just for me, it is for everyone that don't know how to do it, including myself. This thread has provided me with a fairly good understanding of how serial communication is accomplished with the prop. There are no good solid examples for beginners like me. Hopefully when I am done, someone with a thick skull like me might be able to say aha. Your method sounds like a quick easy fix to get me going, but then this would go unfinished. Between Kuroneko, JonnyMac, and I, there is a lot of time devoted to this so far. I would like it to end up as a fairly decent example by tomorrow.

    Bruce
  • kuronekokuroneko Posts: 3,623
    edited 2011-01-23 18:17
    idbruce wrote: »
    @Marko - I don't know the answer to your last question. I wish I knew that stuff but I don't. I looked at the code, but I don't understand it. With the code you suggest, how will I compare those values?
    Your code does this:
    • re-calculate CRC of payload (result is long)
    • get CRC string (result is string)
    So the problem here is that you'd have to convert the long into a string and use strcomp() or convert the CRC string into a (binary) long probably by using a 3rd party object. That seems rather long-winded and inefficient (which is what MagIO2 tried to get accross in the other thread).

    With the binary transfer you get:
    • re-calculate CRC of payload (result is long)
    • get CRC binary value (result is long)
    and then all you have to do is
    if crc_expected == crc_received         ' crc_received is the [COLOR="red"]decoded[/COLOR] value (when sent encoded)
        ' very nice
    
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 18:29
    Marko

    I must be doing something wrong because they do not equal :(
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 18:37
    Marko

    You are a genius. Okay that works for me, even though I don't understand it. :) I will have to study that subject later. This is how I did it.
    IF CRCExpected == decodeCRC(CRCReceived)
        Terminal.Str(string("Success", CR))
    

    Bruce
  • kuronekokuroneko Posts: 3,623
    edited 2011-01-23 18:42
    Apologies, crc_received is meant to be the value after decoding. The code fragment was only supposed to show the simplicity of comparing two longs. I added a comment.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 18:47
    Marko

    Don't apologize, it's perfect. I just wish I understood it.

    With the code like it is, with the three different com objects, can the Receiver com now send an ACK back to the Sender com?

    Bruce
  • kuronekokuroneko Posts: 3,623
    edited 2011-01-23 18:54
    idbruce wrote: »
    With the code like it is, with the three different com objects, can the Receiver com now send an ACK back to the Sender com?

    Yes, they are cross-linked (pins 1 and 0). All the sender has to do is listen.

    As for (not) understanding, which part is giving you trouble? It all boils down to that bytes are sent over the link. Meaning is not important down there as protocol stuff happens at a higher level. So the only change is the encoding of the CRC. Previously it was sent as ASCII string (human readable), now it's sent raw. You'll get there eventually.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 19:07
    Marko

    Which part is giving me trouble? Look below :)
    repeat 3
        Sender.Tx(CRC)
        CRC >>= 8
    

    CON
      crc_head = %1110_0000                                 ' 4 bit tag, 4 bit payload
      crc_msk4 = %0000_1111                                 ' payload mask
      crc_tail = %10_000000                                 ' 2 bit tag, 6 bit payload
      crc_msk6 = %00_111111                                 ' payload mask
      
    PRI encodeCRC(crc16) : crcEN
      crcEN.byte[0] := crc_tail | crc_msk6 &  crc16         ' %----------------10cccccc
      crcEN.byte[1] := crc_tail | crc_msk6 & (crc16 >>  6)  ' %--------10cccccc--------
      crcEN.byte[2] := crc_head | crc_msk4 & (crc16 >> 12)  ' %1110cccc----------------
      
    PRI decodeCRC(crcEN) : crc16
      crc16 |=           crc_msk6        & crcEN            ' %----------cccccc
      crc16 |= (constant(crc_msk6 <<  8) & crcEN) >> 2      ' %----cccccc------
      crc16 |= (constant(crc_msk4 << 16) & crcEN) >> 4      ' %cccc------------
    

    I don't expect you to explain it to me, that would take to much time and effort on your part. Besides, I can tell that it would be a hard thing for me to grasp in a short time. I normally learn much better by reading and having numerous examples that I can study over a period of time.

    I am now going to try to fit the ACK in there and get that working (HOPEFULLY).

    As always, thank you very much Marko. I would have been lost without your gracious assistance.

    Bruce
  • kuronekokuroneko Posts: 3,623
    edited 2011-01-23 19:30
    Let's start with the loop:
    repeat 3
      Sender.Tx(CRC)
      CRC >>= 8
    

    The objective is to send 24 bits stored in CRC (3 bytes, encoded). The bytes are organised in the long like this $00KKLLMM (top byte isn't used). Furthermore the tx method expects a byte as parameter (parameters always occupy a long on the stack but only parameter.byte[0] is actually used). The loop runs 3 times.
    1. send $MM, adjust CRC by shifting it right -> $0000KKLL, CRC.byte[0] is now $LL
    2. send $LL, adjust CRC by shifting it right -> $000000KK
    3. send $KK, adjust CRC (not strictly required)
    You'd get the same effect with this version but it requires a local variable:
    repeat n from 0 to 2
      Sender.Tx(CRC.byte[n])
    
    or (we know that neither $KK, $LL nor $MM are zeroA) like this:
    repeat
      Sender.Tx(CRC)
    while CRC >>= 8
    

    A because we encoded them like this
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 19:39
    Marko

    So the actual byte value is entered into crc, but it is at the left and we want it on the right, so we keep shifting until we get it exactly where we want it?

    Bruce
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 19:43
    Okay I think I get it.

    CRC is a long, we enter a byte but it goes to the left instead of the right. So then we shift to get it to the right. Something like that?
  • kuronekokuroneko Posts: 3,623
    edited 2011-01-23 20:13
    VAR
      long  storage
    
    PUB null
    
      storage := $FF
    
    This will assign a byte value to a long. Inside the long it looks like $000000FF. So a byte assignment goes to the right. In order to fill the next one (storage.byte[1]) you can use either of the methods below:
    storage.byte[1] := $CC
    storage := ([COLOR="red"]storage & $FFFF00FF[/COLOR]) | $CC << 8
    
    The red code makes sure that the 8 bits are zero as we use an OR operation to insert our value (this can be omitted when we know that those bits are zero). The first version has to do the same but it's done by the SPIN interpreter for you (behind the scenes).

    As for getting the value where we want it, yes, we need to shift bytes on the left to the right so that the tx function finds them in the right location. Re: entering a byte, not quite sure what you mean here. CRC is a long and filled with the result of encodeCRC which returns a 24 bit value. What we want is extracting bytes (in fact all 3 of them).
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 21:34
    @Marko - Thanks for the lesson, I appreciate that.

    @All Others - I know a lot of people are looking at this thread, so I thought I would leave the latest sample before going off to sleep. Feel free to work on it and post suggestions. It is a Prop2Prop simulation program, designed to help me learn. Thanks Marko and thanks Jon.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-25 08:53
    Hello Everyone

    Here is the latest rendition. The project has been renamed to PropToPropSim. I just hope it helps someone in the future. If it does, please drop me a post.

    Bruce
Sign In or Register to comment.