CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

f_PICtoIEEE in ieeefloat.c question

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Oesterling



Joined: 07 Mar 2016
Posts: 13

View user's profile Send private message Visit poster's website

f_PICtoIEEE in ieeefloat.c question
PostPosted: Mon Mar 07, 2016 5:24 pm     Reply with quote

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: 1903

View user's profile Send private message

PostPosted: Mon Mar 07, 2016 5:33 pm     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Mon Mar 07, 2016 9:28 pm     Reply with quote

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: 19395

View user's profile Send private message

PostPosted: Tue Mar 08, 2016 1:50 am     Reply with quote

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: 19395

View user's profile Send private message

PostPosted: Tue Mar 08, 2016 3:26 am     Reply with quote

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. Smile
Oesterling



Joined: 07 Mar 2016
Posts: 13

View user's profile Send private message Visit poster's website

PostPosted: Tue Mar 08, 2016 9:56 am     Reply with quote

Ah the power of the union statement.

You're awesome. Thanks Ttelmah!

- Chris
Oesterling



Joined: 07 Mar 2016
Posts: 13

View user's profile Send private message Visit poster's website

PostPosted: Tue Mar 08, 2016 7:16 pm     Reply with quote

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: 19395

View user's profile Send private message

PostPosted: Wed Mar 09, 2016 1:51 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Wed Mar 09, 2016 1:00 pm     Reply with quote

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: 19395

View user's profile Send private message

PostPosted: Wed Mar 09, 2016 3:22 pm     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Wed Mar 09, 2016 3:49 pm     Reply with quote

Yeah I got it. Well I certainly appreciate your wisdom. Many thanks.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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