|
|
View previous topic :: View next topic |
Author |
Message |
Oesterling
Joined: 07 Mar 2016 Posts: 13
|
f_PICtoIEEE in ieeefloat.c question |
Posted: Mon Mar 07, 2016 5:24 pm |
|
|
Hi guys. I'm embarrassed to ask this but I need a sanity check regarding ieeefloat.c. I must be looking at this wrong. I’m using version 5.027 of the PCD compiler. Can you tell me why f_PICtoIEEE has an unsigned int32 as the parameter and returns a float32? Shouldn't I be passing in the float32 and returning the int32? Thank you!
Code: | #ifdef __PCD__
/*
float32 f_PICtoIEEE(unsigned int32)
PURPOSE: This function converts float from CCS -PIC format to IEEE format
PARAMS: 32 bit number
RETURNS: 32 bit Floating point number
*/
float32 f_PICtoIEEE(unsigned int32 pic)
{ |
… |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Mon Mar 07, 2016 5:33 pm |
|
|
It's just a bug. That said, it will still work.
The CCS compiler doesn't care what you put in a particular address in RAM, nor does it really care what you type it as. A CCS "pic float" is 32 bits, so even though the declaration is for an int32, the function will still work (should still work) because a float and an int32 are the same size. |
|
|
Oesterling
Joined: 07 Mar 2016 Posts: 13
|
|
Posted: Mon Mar 07, 2016 9:28 pm |
|
|
Thanks for the reply newguy. I'm glad it's a bug and I'm not totally crazy but I still get the following result:
myFloat: 0.00
With my code:
Code: |
int32 ieeeValue;
float32 myFloat;
ieeeValue = f_PICtoIEEE( 98.6 );
myFloat = f_IEEEtoPIC( ieeeValue );
fprintf( rs232_stream, "myFloat: %f\n\r", myFloat ); |
Any other suggestions would be greatly appreciated! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Tue Mar 08, 2016 1:50 am |
|
|
It's not a bug.
It's relying on C's automatic ability to pass variables as they 'are'.
You call it with a float32.
The code though receives these four bytes _and treats them internally to the routine_ as an int32. This allows binary operations like rotations, bit access etc., to be done on the four bytes, which could not be done on a 'float'. The key is that this type of operation cast behaves differently to a conventional 'cast'. If the routine cast the value inside the routine to 'int32', it'd be decoded, so if called with 98.6, and was then cast to an int32, the int32, would receive '98'. The four byte value is transferred into an int32 in a union inside the routine, and they don't want this operation to be 'cast', so they use this method of passing. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Tue Mar 08, 2016 3:26 am |
|
|
The reason your code doesn't work, is again to to do with casting.
Passing a _constant_ to the function, the compiler looks at the type of what is being passed, and casts this automatically at compile time. Result it passes an int32 containing '98', which in byte terms is 0x00000060, not the bytes representing '98.6', which are 0x33334585.
I prefer to avoid any problems with this, by using a union
You need to pass 98.6 as a a sequence of bytes. So:
Code: |
typedef union {
int32 iver;
float32 fver;
} convert;
convert source;
convert ieeeValue;
convert myFloat;
source.fver=98.6;
ieeeValue.iver = f_PICtoIEEE( source.fver );
myFloat.fver = f_IEEEtoPIC( ieeeValue.iver );
fprintf( rs232_stream, "myFloat: %f\n\r", myFloat.fver );
|
This way you can at any point access the integer or float 'versions' of each set of four bytes, and pass a float value to the routine, and accept the return as a float value.
The great thing about this, is then if you want to send the int32 as bytes, you only need to add a 'byte' array to the union, and these are available for you to send from the ieee converted value. |
|
|
Oesterling
Joined: 07 Mar 2016 Posts: 13
|
|
Posted: Tue Mar 08, 2016 9:56 am |
|
|
Ah the power of the union statement.
You're awesome. Thanks Ttelmah!
- Chris |
|
|
Oesterling
Joined: 07 Mar 2016 Posts: 13
|
|
Posted: Tue Mar 08, 2016 7:16 pm |
|
|
I really think I have the code correct now but I am getting 0's! grrrr!
OUTPUT RESULTS: source.fver:98.59
source.iver:42C53333
ieeeValue.fver:0.00
ieeeValue.iver:00000000
myFloat.fver:0.00
myFloat.iver:00000000
CODE:
typedef union {
int32 iver;
float32 fver;
} convert;
convert source;
convert ieeeValue;
convert myFloat;
source.fver=98.6;
fprintf( rs232_stream, "source.fver: %f\n\r", source.fver );
fprintf( rs232_stream, "source.iver: %8LX\n\r", source.iver );
ieeeValue.iver = f_PICtoIEEE( source.fver );
fprintf( rs232_stream, "ieeeValue.fver: %f\n\r", ieeeValue.fver );
fprintf( rs232_stream, "ieeeValue.iver: %8LX\n\r", ieeeValue.iver );
myFloat.fver = f_IEEEtoPIC( ieeeValue.iver );
fprintf( rs232_stream, "myFloat.fver: %f\n\r", myFloat.fver );
fprintf( rs232_stream, "myFloat.iver: %8LX\n\r", myFloat.iver ); |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Mar 09, 2016 1:51 am |
|
|
I did check that it correctly gives the right value in memory, as posted, with 5.026, and 5.028 (nearest I have to 5.027...).
I've just tested your code as posted, with 5.026 (on a 18F4620), and get:
Code: |
source.fver: 98.60
source.iver: 33334585
ieeeValue.fver: 0.00
ieeeValue.iver: 42C53333
myFloat.fver: 98.60
myFloat.iver: 33334585
|
Cut and pasted from the terminal window!...
What processor are you using?. Maybe the code is failing on a different PIC family?.
Obviously ieeevalue.fver will not give a correct value, since printf, wants CCS ordered floats.
I realise looking at your original post, the section snipped, is from PCD.
You do realise that in PCD, the compiler already uses IEEE format?. The conversions are still there, so if you want to send/receive values from another PIC, using the CCS format, you can do so. However if you feed an IEEE float (which is what you have if you are using PCD), into the CCS to IEEE function, then you will get garbage....
In fact looking at the numbers you post, shows this. You are starting with an IEEE number (42C53333 is the hex for 98.6 in IEEE), then feeding this into CCS to IEEE, which actually gives an impossible value (the code converts this to 0)..... |
|
|
Oesterling
Joined: 07 Mar 2016 Posts: 13
|
|
Posted: Wed Mar 09, 2016 1:00 pm |
|
|
Oh snap. Yes I am using a 24F chip and no I was not aware that for PCD IEEE is the standard format for floats. In my defense I saw the PCD conversion functions in ieeefloat.c and assumed I needed to use them. That would explain why more people have not asked about the PCD functions parameter / comment inconsistences in ieeefloat.c. Not many people use the PCD functions.
Thank you so much Ttelmah! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Mar 09, 2016 3:22 pm |
|
|
The format is historical.
Back before the IEEE format was standardised, Microchip wrote a maths library for 32bit float on the PIC, optimised specifically to the hardware. So the placement of bits was designed to best suit the PIC. This library was made public domain, and CCS incorporated it as the core of their maths libraries. Later IEEE came along, and with later chips new functions meant that there was no gain in using the MicroChip float32 format, so when CCS rewrote the maths libraries for the later chips, they switched to IEEE format.
If you look at the top of ieefloat.c, you will see:
Code: |
//// This library converts IEEE float format to and from ////
//// the Microchip format used by PCB,PCM and PCH.
|
Note PCB, PCM & PCH
People who used the conversions the right way, know/find that they work, so they don't start looking for oddities in the declarations..... |
|
|
Oesterling
Joined: 07 Mar 2016 Posts: 13
|
|
Posted: Wed Mar 09, 2016 3:49 pm |
|
|
Yeah I got it. Well I certainly appreciate your wisdom. Many thanks. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|