LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Byte swapping float variables

How can I byte swap a four byte float variable using the format modifiers supplied with CVI?.
0 Kudos
Message 1 of 9
(4,422 Views)
The following are snippets from the NI LabWindows/CVI Help files included with CVI. I would recommend accessing the document by going to Help->Contents and doing a search for 'Format'. Click on 'Formatting Functions' in the Search Results box.

Here is the general layout of the �Fmt� function that CVI supplies.

n = Fmt (target, formatstring, source1, ..., sourcen);
�formatstring� has the following form: "target_spec < source_specs_and_literals"

% [ rep ] formatcode [[ modifiers ]]
The character '%' introduces all format specifiers. rep indicates how many times the format repeats with respect to the arguments. formatcode is a code character that indicates the nature of the data items you want to format. Modifiers is an optional, bracket-enclosed sequence of c
odes that further describes the data format.

Here is an example from the help files:

�if a GPIB instrument sends 2-byte binary data in Intel byte order, the code appears as follows:

short int instr_buf[100];
short int prog_buf[100];
status = ibrd (ud, instr_buf, 200);
Fmt (prog_buf, "%100d<%100d[b2o01]", instr_buf);

If, instead, the GPIB instrument sends two-byte binary data in Motorola byte order, Fmt appears as follows:

Fmt (prog_buf, "%100d<%100d[b2o10]", instr_buf);

In either case, you use the o modifier only on the buffer that contains the raw data from the instrument (instr_buf). LabWindows/CVI ensures that the program buffer (prog_buf) is in the proper byte order for the host processor.

The format modifier for 32 and 16 bit Intel is [o0123]and [o01] and [o3210] and [o10] for Motorola byte order.

If you need further assistance please post back. Good luck!

Craig H.
National Instruments
Message 2 of 9
(4,422 Views)
Hi,

There is one thing to watch out for here, The "o" operator for the Fmt function does not operate directly in floting point datatypes; you need to you need to put your floating point data ina holder int in order to be able to use the Fmt.

Here is a small piece of code on how to do this:


#include
#include

int main (int argc, char *argv[])
{
float f=0.12358445685687967896796780870890;
void *i;
int a;
i = &f; //copy the bytes on the float to an int
a = *((int *)i);
//print the float
printf("\nThe value is: %f", *((float*)i));
//show how the float data looks as an int
FmtOut("\nThe Floating point read as an int is: %d", a);
//Swap the byte order
Scan(&a, "%i[b4]>%i[b4o3210]", &a
);
printf("\nThe Swaped int is: %d", a);
//return the float to it's original location
i = &a;
f = *((float *)i);
printf("\nThe swaped float is: %f", f);
getchar();
return 0;
}


I hope this helps.

Regards,

Juan Carlos
N.I.
Message 3 of 9
(4,422 Views)
Hi Craig,

Many thanks for the reply. Yes I did know about the integer byte swaps but applying the "o" format modifier is illegal when applied to a float. Maybe this function could be added to the next version release for CVI?.

Cheeerio
Mike
0 Kudos
Message 4 of 9
(4,422 Views)
Hi Juan Carlos,

Many thanks for your reply. Brilliant!!. How did you ever think of that!. Is there a way of byte swapping 8 byte doubles?.

Maybe NI could put a format modifier to byte swap floats and doubles like integers in the next CVI version release.

Cheerio
Mike
0 Kudos
Message 5 of 9
(4,422 Views)
If you are using CVI 7.0 you can use a 64 bit integer, must operations are now supported. You can declare a 64 bit integer as __int64 (double underscore at the beginning) than use the same procedure that I posted before.

I would appreciate if you post your suggestion for CVI by going to http://www.ni.com/contact ans selecting prodect feedback; our developers monitor those suggestions.

Good luck with your project.

Juan Carlos
0 Kudos
Message 6 of 9
(4,422 Views)

@craigherdman wrote:
The following are snippets from the NI LabWindows/CVI Help files included with CVI.
short int instr_buf[100];
short int prog_buf[100];
status = ibrd (ud, instr_buf, 200);
Fmt (prog_buf, "%100d<%100d[b2o01]", instr_buf);

This sample code from the help file results in a "Parameter type incompatible with format specifier".  The problem is the specifier "i" assumes 4-byte normal integers.  So a modifier of [b2] must be used. Here's the correct code:

 

short int instr_buf[10] = {1234, 9421, 0x279, 0}; // sample data
short int prog_buf[10] = {0};

Fmt(prog_buf, "%10i[b2]<%10i[b2o10]", instr_buf);

 

 

 

0 Kudos
Message 7 of 9
(3,660 Views)

Or you can do it manually using a union...
Using the union you can manipulate the bytes any way you want.

union UNION_4_BYTES
{
   float          f32;
   int            i32;
   unsigned int   u32;
   int            en;    // enum type
   short          s16[2];
   unsigned char  byte[4];
};


union UNION_4_BYTES source32bitNum, target32binNum;


source32bitNum.i32 = 123;

target32bitNum.byte[0] = source32bitNum.byte[3];
target32bitNum.byte[1] = source32bitNum.byte[2];
target32bitNum.byte[2] = source32bitNum.byte[1];
target32bitNum.byte[3] = source32bitNum.byte[0];

// your target byte swapped value is in target32bitNum.i32

0 Kudos
Message 8 of 9
(3,657 Views)

I don't understand all those specifiers in the Fmt and Scan commands.  I would just do it the old-fashioned way:

 

int* i = (int*)&myFloat;
*i = ((*i & 0xff000000) >> 24) |
     ((*i & 0x00ff0000) >> 8)  |
     ((*i & 0x0000ff00) << 8)  |
     ((*i & 0x000000ff) << 24);

 

 

0 Kudos
Message 9 of 9
(3,639 Views)