Shop OBEX P1 Docs P2 Docs Learn Events
C: Is it possible to send a struct serially without requiring parsing on the receiver — Parallax Forums

C: Is it possible to send a struct serially without requiring parsing on the receiver

idbruceidbruce Posts: 6,197
edited 2015-03-31 05:40 in Propeller 1
I doubt it is possible, but I would like to send a struct serially from a tramsmitter to a receiver which would fill an identical struct with the characters received without parsing. Is this possible?

Comments

  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-03-30 08:10
    Yes, this is possible. Details are a little lacking, but at very least you can always just turn off cooked mode and insert the bytes one-by-one into the struct in the same order. Use pointer magic and treat the struct's memory as if it were a byte array. Send each byte in the same order that the receiver writes the bytes back to the struct and you'll be golden.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-30 08:31
    David
    Yes, this is possible. Details are a little lacking, but at very least you can always just turn off cooked mode and insert the bytes one-by-one into the struct in the same order. Use pointer magic and treat the struct's memory as if it were a byte array. Send each byte in the same order that the receiver writes the bytes back to the struct and you'll be golden.

    That isn't exactly what I had in mind, but that definitely sounds like a plan.
  • Heater.Heater. Posts: 21,230
    edited 2015-03-30 09:16
    In general this is a really bad idea.

    In order to transmit a struct as a stream of bytes you are going to do something like create a pointer to that struct, cast it as a pointer to bytes and the transmit as many bytes as is the sizeof the struct.

    On the receive end you are going to create a pointer to the a struct, cast it as a pointer to bytes, and then write incoming bytes into the struct.

    Or, you might be tempted to use a union to overlay a byte array over whatever structure you have.

    All well and good, until:

    1) The machines at each end store their ints and such in memory in different orders. Big endian vs little endian. Then all your data is mangled.

    2) I'm not sure but I believe there there can be problems with different padding on different machines. Imagine a struct with a byte and an int, perhaps the architecture requires all ints to be on 4 byte boundaries in memory in one case but not the other. In that first case there may be 3 bytes of padding between struct members.

    3) Again I'm not sure but thater may be problems with memory alignment in some cases. Some machines like their int's on 4 byte boundaries others don't care.

    All of these issues have bitten me when porting code from machine to machine, compiler to compiler.
  • David BetzDavid Betz Posts: 14,516
    edited 2015-03-30 10:59
    Maybe we need a JSON library for PropGCC? :-)
  • mindrobotsmindrobots Posts: 6,506
    edited 2015-03-30 11:15
  • idbruceidbruce Posts: 6,197
    edited 2015-03-30 11:20
    Heater

    I am now more in line with what David (SwimDude0614) said. Instead of attempting to pass the entire struct, just pass them as one member at at a time, until the struct is filled.

    I am basically talking about two Propellers side by side, but they both need the struct. Since I have run out of memory on the Teacup port, I am now thinking of a different strategy. One prop to process the gcode and the other to run it.
  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-03-30 11:23
    David Betz wrote: »
    Maybe we need a JSON library for PropGCC? :-)

    Awesome idea. Whether or not it gets used for the teacup port, I like this idea a lot. Easy communication between Propellers and other devices?! Woh...

    An issue has been created for PropWare so I don't forget about it.
  • Heater.Heater. Posts: 21,230
    edited 2015-03-30 11:33
    idbruce,
    I am now more in line with what David (SwimDude0614) said. Instead of attempting to pass the entire struct, just pass them as one member at at a time, until the struct is filled.
    No.

    The problem still remains. If that one member is an int then you can still stumble on big endian/little endian problems.

    Of course if you are very sure that your machines at each end are compatible that way and that will always be so, go ahead. I would not do so.
  • jmgjmg Posts: 15,182
    edited 2015-03-30 11:48
    idbruce wrote: »
    I am basically talking about two Propellers side by side, but they both need the struct.
    If both ends are Props, you are safer, but expanding on Heater's comments, I would make both sides
    share the same structure definition. - and place it in memory the same way, just to be sure....
    That way, if you ever change it, both builds keep in phase.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-30 11:52
    Heater

    I ask out of ignorance :) If the serial comm is between two Propellers, how can they be different?
    If that one member is an int then you can still stumble on big endian/little endian problems.

    Is there any way to stop this from happening?
  • Heater.Heater. Posts: 21,230
    edited 2015-03-30 12:04
    If the machines and compilers at both ends are for sure always going to be the same then, yes, there is no problem with your plan.

    That is an assumption that has led to breakage that I have had to fix over the years as things change. So I would never do it.
  • TorTor Posts: 2,010
    edited 2015-03-30 12:06
    When using two propellers there won't be any big endian/little endian issues. You can even copy the whole struct between them because there won't be any alignment issues either. Of course in that case it's best to follow jmg's advice and keep the struct definition in a single, common space (a single .h file to maintain).

    The problem will come when sometime in the future you decide to replace one of the propellers with e.g. a Raspberry Pi model 6 because suddenly you need some major processing at that end.. then it won't help to just recompile the code for the new processor.
  • Heater.Heater. Posts: 21,230
    edited 2015-03-30 12:14
    Exactly.

    And as I said, spending hours mashing up the code to run on a distributed Prop system seems like a waste of life when there are many cheaper, faster, smaller, easier ways to get it working.
  • David BetzDavid Betz Posts: 14,516
    edited 2015-03-30 12:24
    idbruce wrote: »
    Heater

    I am now more in line with what David (SwimDude0614) said. Instead of attempting to pass the entire struct, just pass them as one member at at a time, until the struct is filled.

    I am basically talking about two Propellers side by side, but they both need the struct. Since I have run out of memory on the Teacup port, I am now thinking of a different strategy. One prop to process the gcode and the other to run it.
    Maybe it would be better to use a RaspberryPi with a Propeller board to handle any realtime aspect of your project. Then you could run the larger C/C++ code on the Pi and you'd probably have plenty of resources left to run the stuff that has to be fast on the Propeller.
  • potatoheadpotatohead Posts: 10,261
    edited 2015-03-30 12:24
    Setting waste of life aside...

    Can't this be done in stages? Use an SD card, and have the system be modal. Parse G-code, write movements. Load movement system, read movements, etc...

    This seems like it would be just fine, even for very large G-CODE data sets. It's just going to take a little while to process, then the majority of the time will be executing the movements.

    And once the move data is done, all sorts of things can happen with it. Plots? Or reprints? Heck, toss up a bitmap and plot a dot in 3D space, projected onto a bitmap, for every 5th move, or something. User will "see" the shape, and maybe that's good.

    Since the SD card is big, and can be written fairly quickly, just encode the movement data in ways that can be spooled from the SD card to the movement code. A spooler COG fills a buffer, then the movement COGS go to work. As the buffer drains, the spooler keeps filling it.

    Another stage might be the initial "kick off" program. It presents an interface to the user, selecting a file, whatever. Then it kicks off the parser, which returns. It can be used to origin, clean, position, the printer mechanics too.

    If you plot, or offer some representation of the things to happen, user can confirm, and then it launches the mover.

    Etc...
  • Heater.Heater. Posts: 21,230
    edited 2015-03-30 12:36
    @potatohead,
    Can't this be done in stages? Use an SD card, and have the system be modal. Parse G-code, write movements. Load movement system, read movements, etc...
    Yes, can be done. That's how we did things back in the days of expensive low memory systems.

    Instead of splitting the code over Propellers you are now splitting the code over time.

    To my mind it's still a waste of life. Instead of spending a thousand hours getting that working, just get a 5 dollar STM32 F4 or whatever. Or the the chip it is known to work on already.

    @David,
    Maybe it would be better to use a RaspberryPi with a Propeller board to handle any realtime aspect of your project.
    Sounds like a excellent idea.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-30 12:39
    Heater
    Exactly.

    And as I said, spending hours mashing up the code to run on a distributed Prop system seems like a waste of life when there are many cheaper, faster, smaller, easier ways to get it working.

    But you must take into consideration that it takes time to learn new things. Time is my most valuable commodity at the moment.

    Basically here is what I want to do.

    Prop1

    Parse GCODE and fill a struct or just a set a variables that match a struct on a second Prop. Attempt comm with second Prop, if second Prop accepts comm, then send variables, continue parsing and sending until there is no more GCODE.

    *Note: By the time the data is ready to send, all mathematical fuctions on the data have already been performed.

    Prop2

    Receive data from Prop1 and fill struct with that data. Add the contents of that struct to a queue and keep accepting data from Prop1 until queue is filled. Pop the head off the queue, opening up the tail of the queue, which would allow further comm to commence. Seperate the struct according to various axes and syncronize the start of a multi-axes movement. When the move is complete, grab the next move.
  • Heater.Heater. Posts: 21,230
    edited 2015-03-30 12:49
    Bruce,
    But you must take into consideration that it takes time to learn new things.
    So I do. You are going to have to learn a ton of new stuff whichever way you go.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-30 12:51
    I see more comments have been written.....

    The cogs gentlemen.... the cogs.

    I would like to achieve syncronized multi-axes movement, while having enough pins left over for homing, over-travel detection, and a user interface. My biggest mistake was attempting to do this one Propeller chip in the first place. Two chips were my original choice of design, but then I changed my mind, and ERNA always said two :) I should have gone with my gut in the first place and I would have probably been much further along.
  • mindrobotsmindrobots Posts: 6,506
    edited 2015-03-30 13:07
    My 3D printer (whenever it finally arrives) is coming with a Smoothieboard - the Cortex-M3 board itself costs $150 with 5 stepper drivers.

    How much is your time worth? :D
  • base2designbase2design Posts: 78
    edited 2015-03-30 13:08
    Here's an up-and-coming standard that's somewhat complimentary to JSON: http://tools.ietf.org/html/rfc7049.

    Also known as Concise Binary Object Representation (CBOR). I'm not sold yet, but it's something to consider, as CoAP (http://en.wikipedia.org/wiki/Constrained_Application_Protocol) is a client of this format as well as JSON.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-30 13:27
    Rick
    My 3D printer (whenever it finally arrives) is coming with a Smoothieboard - the Cortex-M3 board itself costs $150 with 5 stepper drivers.

    How much is your time worth?

    Well that looks and sounds very nice, I must admit. That would certainly be the easy way out for me.

    Don't tempt me..... :)
  • MicksterMickster Posts: 2,718
    edited 2015-03-30 18:02
    mindrobots wrote: »

    How much is your time worth? :D

    Yup, I would go with co-processors and be done with it: http://jrkerr.com/icproducts.html
  • TorTor Posts: 2,010
    edited 2015-03-31 04:01
    About "how much is your time worth".. Hmm.. I'm not sure if that is the right question. Depending on if it's work or not. If it's paid work, it's worth quite a lot. If it's hobby, the question should maybe be stated differently: "How can I spend my time in the most interesting way?"

    -Tor
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-03-31 05:19
    I am curious about what this TeaCup project is, that takes so much as to need a second Prop?

    I have just finished my 3D printer revised to use a Prop as the controller. It fits into a single Prop with some pins left over, and only using a total of 6 cogs (to of which are unneeded, as they are for the convenience of a NTSC display and comunicating with a second Prop for future expansions).

    I do admit that I use PASM, and do not know the limits of C on the Prop.

    For extra G-Code memory I use an external 256KB SPi SRAM.
  • Heater.Heater. Posts: 21,230
    edited 2015-03-31 05:40
    davidsaunders,
    I am curious about what this TeaCup project is, ...
    From the Teacup_Firmware page on github: "Teacup - lean and efficient firmware for RepRap printers"
    https://github.com/Traumflug/Teacup_Firmware

    It's an Arduino project in C/C++. Unsurprisingly if you can get that compiled with prop-gcc it's too big to fit in HUB memory. Hence the need for two Props or an external memory.

    We look forward to seeing you PASM version of a 3D printer driver.
Sign In or Register to comment.