#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2002
    Posts
    118
    Rep Power
    12

    How to extract data byte by byte


    I've got this structure:

    Code:
    typedef struct
    {
         unsigned short int sync;
         float xaxis;
         float yaxis;
         float zaxis;
    } dataChunk;
    And what I want to do is, on an interrupt, read in the appropriate data to each of the member variables of my dataChunk structure, and then pass the data across a serial line, one byte at a time, starting with the most significant byte of the unsigned short int and ending with the least significant byte of the float zaxis variable.

    How do I go about doing this? I just need a way to extract the data one byte at a time. I can't figure out how to do this.

    Thanks.
  2. #2
  3. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    243
    Look up 'union', that should help you. Be sure the machines on the ends of your serial lines are the same 'endian' or your binary transfer will wind up being garbage!

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2002
    Posts
    118
    Rep Power
    12
    I don't think I need a union, but something more like an unsigned character pointer to the address of a casted integer/float or whatever I have in my structure.

    Here's what I'm trying:

    Code:
    typedef struct
    {    
         unsigned short sync;
         float xaxis;
         float yaxis;
         float zaxis; 
          
    } dataChunk;
    
    . . .
    
    dataChunk myChunk;                   
    unsigned char *theByte;         
    
    . . .
    
    vtx = sin(PI*s_time);
         vty = sin(PI/2*s_time);
         vtx = sin(PI/4*s_time);
         myChunk.xaxis = vtx;
         myChunk.yaxis = vty;
         myChunk.zaxis = vtz;
    
         theByte = (unsigned char *)&myChunk.sync;
         printf("myChunk.sync = %2x; theByte = %2x %2x\n", myChunk.sync, theByte[0], theByte[1]);
         theByte = (unsigned char *)&myChunk.xaxis;
         printf("myChunk.xaxis = %4x; theByte = %2x %2x %2x %2x\n", myChunk.xaxis, theByte[0], theByte[1], theByte[2], theByte[3]);
    The myChunk.sync variable is printing out correctly, but I'm getting incorrect output for my myChunk.xaxis variable, which is a float. Why is this?
  6. #4
  7. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    floating point numbers are stored differently internally then ints/etc. http://poli.cs.vsb.cz/edu/num_err/sld011.htm for more.
  8. #5
  9. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    243
    When you start to get pointers and jab them into blocks of memory you need to understand how that memory is actually laid out. Most modern processors choke everytime they make a memory read that is not word aligned. I am presuming you are working on a 32 bit machine, so your word is 4 bytes long. Since the first element in your array is a short, I would expect it to have two bytes of padding in your structure. You can find the size of your structure by using the 'sizeof()' macro. You can then compare the overall size of the structure with the size of its parts and I would expect you will find that there is more to the struct than the sum of its parts. You can force the compiler to miss align structs with the appropriate flags, but you suffer a big hit on performance as you really piss off the CPU's caching and read ahead algorithms. Since you are attempting to send binary data accross a network, you have to deal with all these issues. My favored way to transmit 'binary' data is to convert it into the ASCII representation, sent that, then convert back to binary. That has the dual advantage of making debugging much less of a nightmare AND competely doing away with worrying about endian-ness and, in your case, padding.

    What infamous41md mentions about floating point data is true, but if you are sending data to/from the same OS on the same hardware, it shouldn't matter. It makes a BIG deal if you mix and match OS/hardware, so keep that in mind.

    Code:
    #include <math.h>
    #include <stdio.h>
    
    struct dataChunk{    
        unsigned short sync;
        float xaxis;
        float yaxis;
        float zaxis; 
    };
    
    int main(){
        struct dataChunk myChunk;  
        unsigned char *theByte;
        float vtx, vty, vtz;
        double s_time = 1.23456;
        double PI = 3.15149;
        int i; 
    
        printf("Sizeof(struct dataChunk): %d\n", sizeof(struct dataChunk));
    
        myChunk.sync = s_time;
        vtx = sin(PI*s_time);
        vty = sin(PI/2*s_time);
        vtz = sin(PI/4*s_time);
        myChunk.xaxis = vtx;
        myChunk.yaxis = vty;
        myChunk.zaxis = vtz;
    
        printf("\n\nDecimal:\n");
        printf("myChunk.sync: %d\n", myChunk.sync);
        printf("myChunk.xaxis: %f\n", myChunk.xaxis);
        printf("myChunk.yaxis: %f\n", myChunk.yaxis);
        printf("myChunk.zaxis: %f\n", myChunk.zaxis);
    
        printf("\n\nHex, using pointer to start of block:\n");
        theByte = (unsigned char *)&myChunk.sync;
        for (i=0; i<sizeof(struct dataChunk); i++){
            printf("%02X ", theByte[i]);
            if ((i+1) % 4 == 0) printf("\n");
        }
        printf("\n\n");
        return 0;
    }
    When running it I get this:

    Code:
    Sizeof(struct dataChunk): 16
    
    
    Decimal:
    myChunk.sync: 1
    myChunk.xaxis: -0.680988
    myChunk.yaxis: 0.930670
    myChunk.zaxis: 0.826395
    
    
    Hex, using pointer to start of block:
    01 00 CC CC
    39 55 2E BF
    6A 40 6E 3F
    A7 8E 53 3F
    I leave it to you to verify that the hex reoresentation of the floats is correct. The two CC values on the first line of hex are the padding I mentioned. It is likely to be different on your machine, as it is just the junk that happened to be on the stack when myChunk was created. If you do a memset to clear the object before you use it, you will get 00 for each location.

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2002
    Posts
    118
    Rep Power
    12
    Thanks for your help, folks. I managed to get this sucker working at about 11:30 last night.

    Here's my solution for all interested:

    Code:
    typedef struct
    {    
         unsigned short sync;
         float xaxis;
         float yaxis;
         float zaxis; 
          
    } dataChunk;
    
    . . .
    
    dataChunk myChunk;          /**< Chunk of data to be sent on every ISR.    */
    unsigned char *bp;          /**< Byte pointer for byte extraction.         */
    
    . . .
    
    /* void timerhandler(int sig, siginfo_t *siginfo, void *context) - Responds to */
    /* and handles the SIGALRM signal.                                             */
    void timerhandler(int sig, siginfo_t *siginfo, void *context)
    {
         double vtx, vty, vtz;    /**< Modeled voltage output.                       */
         int res;                 /**< Return value for write to port.               */
         short int counter;       /**< A counter.                                    */
         char readability[5] = " \n";     /**< A string for readability purposes on terminal.*/
    
         /* We will model three voltage functions in order to set values */
         /* for our x-, y-, and z-axis values in dataChunk.              */
    
         vtx = sin(PI*s_time);
         vty = sin(PI/2*s_time);
         vtx = sin(PI/4*s_time);
         myChunk.xaxis = vtx;
         myChunk.yaxis = vty;
         myChunk.zaxis = vtz;
    
         bp = (unsigned char *)&myChunk.sync;
         for(counter = 0; counter<=1; counter++)
              res = write(port_fd, (bp + counter), 1);
         printf("%x%x%x\n", myChunk.sync, *(bp), *(bp+1));
    
         bp = (unsigned char *)&myChunk.xaxis;
         for(counter = 0; counter<=3; counter++)
              res = write(port_fd, (bp + counter), 1);
    
         bp = (unsigned char *)&myChunk.yaxis;
         for(counter = 0; counter<=3; counter++)
              res = write(port_fd, (bp + counter), 1);
    
         bp = (unsigned char *)&myChunk.zaxis;
         for(counter = 0; counter<=3; counter++)
              res = write(port_fd, (bp + counter), 1);
    
         res = write(port_fd, readability, strlen(readability));
     
         timercnt = timercnt++;
         s_time = s_time + s_period;
    
    }

IMN logo majestic logo threadwatch logo seochat tools logo