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

float to int32 typecasting

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



Joined: 18 Feb 2004
Posts: 12

View user's profile Send private message Send e-mail

float to int32 typecasting
PostPosted: Wed Feb 18, 2004 4:57 pm     Reply with quote

Hello,

I am using the 3.185 compiler, and have run into a small problem with a function I have written. The problematic function, called correct_adc_value(), is given below:

int32 correct_adc_value(int32 RawValue)
{
int i;
int32 Answer;

for (i = 0; i < 4; i++)
{
C.hValue[i] = read_eeprom(16 + i);
D.hValue[i] = read_eeprom(20 + i);
}
convert_ieee_to_microchip(&C.hValue[0]);
convert_ieee_to_microchip(&D.hValue[0]);
Correct.fValue = (C.fValue * RawValue) + D.fValue;
Answer = (int32) Correct.fValue;
return Answer;
}


the variables C, D, and Correct are actually unions as shown below:

union float_temp
{
float fValue;
int hValue[4];
} A, B, C, D, Correct;


Here's is what I am doing...
I retrieve an unsigned 24-bit A/D conversion value, and use make32() to create an int32 variable representing that value, which I then pass to correct_adc_value as RawValue (MSB always 0). The idea is to apply an Cx + D style correction to the RawValue to account for reference voltage differences, part tolerances, etc. basically, anything that can hinder the performance of the A/D.

The coefficients for the algorithm, C and D, are loaded into the union from the PIC's eeprom memory using the .hValue[i] variables, as shown in the first part of the function. This part works correctly. The same goes for the IEEE-754 to Microchip conversion. I am including that conversion code as well below, in case anyone is interested.

void convert_ieee_to_microchip(int *Value)
{
int1 Temp;

Temp = shift_left(&Value[1], 1, 0);
Temp = shift_left(&Value[0], 1, Temp);
shift_right(&Value[1], 1, Temp);
}

void convert_microchip_to_ieee(int *Value)
{
int1 Temp;

Temp = shift_left(&Value[1], 1, 0);
Temp = shift_right(&Value[0], 1, Temp);
shift_right(&Value[1], 1, Temp);
}


Now to the problem...

The type cast at the end seems to clip to only the 2 LSBs. In testing this, I pass 0x00456789 as RawValue into the routine, and if C is 0x3F800000 (IEEE-754 for 1.0) and D is 0x00000000 (IEEE-754 for 0), the returned value is 0x00006789, where I expected 0x00456789.

It should be noted that I do a similar correction to a 16bit (long) d/a value and it works without issue.

Thanks in advance for your help.
plehman



Joined: 18 Feb 2004
Posts: 12

View user's profile Send private message Send e-mail

PostPosted: Sun Feb 22, 2004 2:51 pm     Reply with quote

I finally seem to have found a solution to my problem. It seems if I add a typecast for RawValue to a float in the third line from the end, the calculation for Correct.fValue. This line would then look like the following:

Correct.fValue = (C.fValue * (float) RawValue) + D.fValue;

Hopefully this will help anyone who runs into this problem in the future.
Ttelmah
Guest







PostPosted: Sun Feb 22, 2004 3:32 pm     Reply with quote

plehman wrote:
I finally seem to have found a solution to my problem. It seems if I add a typecast for RawValue to a float in the third line from the end, the calculation for Correct.fValue. This line would then look like the following:

Correct.fValue = (C.fValue * (float) RawValue) + D.fValue;

Hopefully this will help anyone who runs into this problem in the future.

Yes.
This particular behaviour has been mentioned in many threads in the past. The CCS compiler, performs 'slow' automatic casting, in that it only propogates to a higher type, when either commanded to do so (with a cast), or when a higher type is involved in a maths component. So, where most C compilers would look at the whole statement, and propogate to the highest type used in the whole statement, the CCS compiler, will keep the types to the smaller sizes, by default. the advantage, is that it helps to ensure that larger/slower maths operations are not used unnecessarily, but the downside, is that when some operations are performed data will be lost.
There have been many posts in the past advising that when explicit use of a larger arithmetic type is required, you should allways cast.
You have now found this, and hopefully will serve to remind others of this behaviour...

Best Wishes
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