The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.
|
 |
|
Dev Shed Forums
> Programming Languages
> C Programming
|
Data Type Casting
Discuss Data Type Casting in the C Programming forum on Dev Shed. Data Type Casting C programming forum discussing all C derivatives, including C#, C++, Object-C, and even plain old vanilla C. These languages are low level languages, and used on projects such as device drivers, compilers, and even whole computer operating systems.
|
|
 |
|
|
|
|

Dev Shed Forums Sponsor:
|
|
|

March 5th, 2010, 07:25 AM
|
|
Contributing User
|
|
Join Date: Nov 2004
Location: UK
Posts: 196
Time spent in forums: 1 Day 10 h 57 m 49 sec
Reputation Power: 9
|
|
|
Data Type Casting
I am working on a Windows platform with VS 2005 C++, but the problem relates to c/c++ in general.
I have been trying to interface with a GPS software program which uses a message made up to an 20 word array of unsigned shorts;
e.g.
unsigned short messageData[20];
I have been trying to use data from a home GPS system which includes Lat and Long and heading.; these have been converted from strings to floats.
e.g.
float lat, long, heading;
My problem is that as I know the scaling factors for the lat, long and heading in the messageData buffer;
e.g.
For lat & long
LSB = 8.377E-08; Twos complement - 32 bits Max/ Min -180 to +180; top bit is the sign
For Heading
LSB 0.00549306; Twos complement - 16 bits Max/ Min -180 to +180; top bit is the sign
Setting the heading:-
Code:
unsigned short heading = (unsigned short)(newHeading/0.00549306);
messageData[10] = heading;
Getting the heading:-
Code:
bool negative;
unsigned short currentField = messageData[10];
if(currentField & 0x8000)
{
// Set the negative flag
negative = true;
}
else
negative = false;
float heading = (currentField & 0x7FFF) * g_nScalings[wordPos];
if(negative)
heading = -(180 - heading);
But this does not work as I expected; am I missing something?
As for the 32 bit latitude, I was going to this:-
Setting the Latitude:-
Code:
union
{
int lat_long;
unsigned short buff[2];
}convert;
unsigned short highWord, lowWord;
int newData = (int)(fEngValue/8.377E-08);
convert.lat_long = newData;
highWord = convert.buff[1];
lowWord = convert.buff[0];
I need to get and set data in the message that is of type unsigned short and use in my program as scaled floats.
Any suggestions please as the above code produces the wrong results; it may be a casting problem.
Andy.
|

March 5th, 2010, 02:26 PM
|
|
|
|
Your problem is that you are assuming specific representations of integral and floating point types.
It is not a C/C++ problem : C/C++ makes virtually no guarantees about how floating point types are layed out at the byte level, and almost no guarantee of how integral types are layed out (eg endianness). If your code makes such assumptions - which your code does, by doing bit fiddling - then you need to ensure the assumptions are valid.
__________________
Right 98% of the time, and don't care about the other 3%.
“It has been said that the great scientific disciplines are examples of giants standing on the shoulders of other giants. It has also been said that the software industry is an example of midgets standing on the toes of other midgets.” (Alan Cooper)
|

March 5th, 2010, 03:42 PM
|
|
Contributing User
|
|
Join Date: Nov 2004
Location: UK
Posts: 196
Time spent in forums: 1 Day 10 h 57 m 49 sec
Reputation Power: 9
|
|
Quote: | Originally Posted by LittleGrin Your problem is that you are assuming specific representations of integral and floating point types.
It is not a C/C++ problem : C/C++ makes virtually no guarantees about how floating point types are layed out at the byte level, and almost no guarantee of how integral types are layed out (eg endianness). If your code makes such assumptions - which your code does, by doing bit fiddling - then you need to ensure the assumptions are valid. |
Thanks, just to recap and get things right in my mind; if a heading value is represented as an unsigned short (16 bits) with bit 1 = 0.000030517578125; so the range is -1 to + 1 and if we multiple by 180 we get -180 to +180 degrees
Now for a test I set heading to 3.45 then the following occures.
3.45/0.000030517578125 = 1B999 in Hex; but as we can only store 16 bits the debugger shows B999 as the value.
Now when I come to decode that vaue via:-
B999 * 0.000030517578125 = 1.44998169 which is wrong and if x 180 to get into degrees then get 260.99.
I am confused!?! 
|

March 5th, 2010, 03:57 PM
|
 |
Bellevue WA, USA
|
|
Join Date: May 2004
Location: Bellevue Washington, USA
|
|
Quote: | Originally Posted by any101 I am confused!? |
Me too. Nothing you said makes any sense at all.
__________________
My worst nightmare was a pointless infinite loop.
Work in progress; don't poke the curmudgeon!
http://www.odonahue.com/
|

March 5th, 2010, 04:06 PM
|
|
Contributing User
|
|
Join Date: Nov 2004
Location: UK
Posts: 196
Time spent in forums: 1 Day 10 h 57 m 49 sec
Reputation Power: 9
|
|
|
An array of type unsigned short contains data and one item:-
messageData[10] is the heading which needs to be processed with the following information:-
LSB (bit 0) = 0.000030517578125 sign bit is bit 15,so if we have 0111 1111 1111 1111 then thats 1 and if we have
1111 1111 1111 1111 that -1
If we have 0000 0000 1111 1111 = 255
Now we need to scale it by 0.000030517578125 which gives us 0.007781982421875.
To get the heading into degrees then X 180;
= 1.40075 degrees.
Does that helps?
|

March 5th, 2010, 04:35 PM
|
 |
Contributing User
|
|
Join Date: Jan 2003
Location: USA
|
|
|
I think you should get back to the original points that LG raised about your opening post.
What is the precise specification of the format of the data messages that you are getting from the GPS receiver? Superficially, the message just appears to be a stream of bytes, one after the other. But what does each and every byte in that stream represent?
LG specifically mentioned endianness. That's a description of the byte-order of multi-byte values. Intel is little-endian because the first byte is the LSB (least-significant byte). Some processors, TCP/IP, and some serial protocols are big-endian, meaning that the first byte is the MSB. If a little-endian platform reads in a big-endian data stream and ignores the issue of endianness, then it can very easily reverse the order of the bytes in multi-byte data and thus end up with garbled data.
So again, what is the specification of the format of that data stream you're receiving from the GPS receiver? And precisely how are you reading it in?
Until you've answered those questions satisfactorily, worrying about floating-point formats is pointless. You could be doing everything else exactly correctly, but if you're garbling your data upon input, then your results are still going to be garbled.
PS
A basic electronics hardware troubleshooting technique might help you.
You have a system in which a signal is input, gets processed by a series of subsystems, and produces an output. You have an input, but no output, so you know that something's wrong. How you do narrow down which subsystem contains the fault?
Test the outputs of the subsystems and see if you're getting the signal you expect. When you've found the subsystem that gets a proper input but doesn't produce the proper output, then you've isolated the fault to that subsystem.
Test for valid data at each point in your process.
You read the data stream -- is that data stream what you expect it to be?
You convert that data stream into variable values (eg, that array of short ints) -- do those variables contain what you expect them to contain?
etc.
If you can step through the code with a debugger, it would really help you in this troubleshooting. Even if you need to use printf's to dump variable values, that would still be far better than trying to guess.
Last edited by dwise1_aol : March 5th, 2010 at 04:47 PM.
|

March 6th, 2010, 07:59 AM
|
 |
Contributing User
|
|
Join Date: Jan 2003
Location: USA
|
|
|
Here's an example of the effect of endianness.
Let's say that you have a single-precision IEEE 754 floating-point value of 100.0 being read in: 0x42C80000. The four bytes (2 short ints) that represent that value would appear in memory in one of two ways depending on the endianness of your system:
Big -- bytes(0x42, 0xC8, 0x00, 0x00), short(0x42C8, 0x0000)
Little -- bytes(0x00, 0x00, 0xC8, 0x42), short(0x42C8, 0x0000)
As you can see, the order of the bytes in little-endianness (eg, Intel, therefore Windows and most Linux boxes) is reversed from what it is in big-endianness (the most likely order in your receiver's serial protocol).
Now, if you store each byte of that 100.0f into memory in the same order in which you receive it, then your program will not interpret it as 0x42C80000 as you expect, but rather as 0x0000C842, which would be 0.0.
|

March 7th, 2010, 06:17 AM
|
|
Contributing User
|
|
Join Date: Nov 2004
Location: UK
Posts: 196
Time spent in forums: 1 Day 10 h 57 m 49 sec
Reputation Power: 9
|
|
Thanks for the info, yes I agree. This is what I am planing to do:-
Code:
union
{
int lat_long;
unsigned short buff[2];
}convert;
unsigned short highWord, lowWord;
int newData = (int)(fEngValue/4.65661287307739E-10);
convert.lat_long = newData;
highWord = convert.buff[1];
lowWord = convert.buff[0];
// Swap the words over (low to high; high to low)
newData = SwapWords(highWord, lowWord);
Now bit 0 of the 32 bit word means 4.65661287307739E-10 and if you multiple by 180 you get units of degrees.
This is were the problem is!
|

March 8th, 2010, 05:56 AM
|
|
Registered User
|
|
Join Date: Feb 2010
Posts: 16
Time spent in forums: 2 h 24 m 35 sec
Reputation Power: 0
|
|
|
Thank u
Thanks to all for your sharing. 
|
Developer Shed Advertisers and Affiliates
| Thread Tools |
Search this Thread |
|
|
|
| Display Modes |
Rate This Thread |
Linear Mode
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|