compiler math - or type cast 32 bit math to 16 bit constant.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

compiler math - or type cast 32 bit math to 16 bit constant.

Jump to solution
3,466 Views
RShaich
Contributor II
I am looking for the best way to do math at the compiler level in 32 bit (unsigned long) using unsigned short #defines and assign to unsigned short constants.  I have lots of formulas that define constants that are based on values that we keep changing as the clients needs change.  I don't want to have to keep changing my code so I want formulas in the constant declarations.

The issue seems to be that if the formula, in any step exceeds the variable definition it craps out.
I guess I should think that the compiler could say do the calcs in floating point and then assign the int result to a 16 bit constant.
Or at least do it in 32bit int and assign the result to a 16 bit unsigned int constant. So for example I have this.

#define PWM_MODULUS 0x0400
#define V_PULLIN  100
#define V_HOLDING 18
const unsigned short PWM_HOLDING  =     (PWM_MODULUS *  V_HOLDING / 120)
const unsigned short PWM_PULLIN = ((PWM_MODULUS *  V_PULLIN) / 120)

PWM_HOLDING works fine and gets assigned 153. The 0.6 is lost. (I know I should do ( (PWM_MODULUS *  V_HOLDING / 125) +1) so it rounds correctly)
However even though PWM_PULLIN  should be 853, a legal value for an unsigned short, it does not work since PWM_MODULUS *  V_PULLIN is > 0xFFFF.   It seems this should work since the compiler should be able to handle the math, but it does not.  Since I keep changing V_Pullin, V_Holding, and PWM_Modulus it would be nice to get this working. How should this be done?

I assume I could make my #defines 32 bit (how do I do that can I say #define V_PULLIN  100L) but in other places in the code I need them to be just byte (char) size so I want to leave it alone.
So the question is how can I tell the compiler that for constants I want to have mixed types do the math at long (32 bit) and then save the result to a short (16 bit) constant?

Is there a compiler directive or way to state to do the math as unsigned long and assign the result as unsigned short?

Also I need to do lots of 24 bit math. I know long is 32 bit, short is 16 bit but is there a definition for a 24 bit word? I don't have that much memory so a 3 byte word would be nice over a 4 byte.

Thanx
 Rick
 
Oh this is with CW 5.1 on a 9S08AW part if that matters.



Message Edited by RShaich on 2007-05-30 06:01 PM
Labels (1)
Tags (1)
0 Kudos
Reply
1 Solution
1,189 Views
bigmac
Specialist III
Hello,
 
There are a couple of possibilities that seem to give the desired results -
 
#define PWM_MODULUS 0x0400
#define V_PULLIN  100L
#define V_HOLDING 18L
 
const unsigned short PWM_HOLDING = (PWM_MODULUS * V_HOLDING) / 120;
const unsigned short PWM_PULLIN = (PWM_MODULUS * V_PULLIN) / 120;
 
GLOBALVAR = ANOUTHERVAR / (char)V_HOLDING;

The second possibility is as follows, where PWM_MODULUS is forced to be a 32-bit value, giving the result of the multiplication also 32-bit.
 
#define PWM_MODULUS 0x0400L
#define V_PULLIN  100
#define V_HOLDING 18
 
const unsigned short PWM_HOLDING = (PWM_MODULUS * V_HOLDING) / 120;
const unsigned short PWM_PULLIN = (PWM_MODULUS * V_PULLIN) / 120;
 
GLOBALVAR = ANOUTHERVAR / V_HOLDING;
 
The final statement for either method takes the same number of bus cycles to execute (115 cycles when simulating a HC908 device).
 
Regards,
Mac
 

View solution in original post

0 Kudos
Reply
6 Replies
1,189 Views
bigmac
Specialist III
Hello Rick,
 
I found that using
#define V_PULLIN 100L
seems to work OK for me.  This eliminates the "loss of data" warning.  This would force the result of the multiplication to be a 32-bit value, which is what you require.  However, PWM_PULLIN appears to have the correct 16-bit value assigned.
 
Regards,
Mac
 
0 Kudos
Reply
1,189 Views
RShaich
Contributor II
Thanx.
That is a start I guess.
The problem is that there are other places in the code where the #define needs to be only 8 bits as defined. I had hoped I could do this in the constant declaration and not the #define macro declaration. Perhaps I am going to have to have two sets of # defines for this constant?

Interestingly enough I was not getting a loss of data error on that one.
0 Kudos
Reply
1,189 Views
bigmac
Specialist III
Hello Rick,
 
The fact that the intermediate calculations use 32-bit values shouldn't matter, provided the final result fits within the constant declaration, whether it be a 16-bit or an 8-bit value.
 
For example,
#define V_HOLDING 18L
will also work correctly, even though the intermediate calculations actually do not need to be 32-bit.
 
On this basis, I don't think you will need two sets of #define's.
 
Regards,
Mac
 
0 Kudos
Reply
1,189 Views
RShaich
Contributor II
Perhaps I was not clear.

For the example I gave you I agree with your statement.

But lets say later in the code I have

unsigned short GLOBALVAR
unsigned short ANOUTHERVAR
GLOBALVAR = ANOUTHERVAR / V_HOLDING

If V_HOLDING is only 18 then it should get assigned a byte size and the compiler can hopefully use the divide 16 bit by 8 bit op code that the S08 has. However if V_HOLDING is a type long my math just got way more complex.  This is why I think I would need two types of #defines for V_Holding if I use that approach.

Am I missing something? Will the compiler optimize that out?

Rick



Message Edited by RShaich on 2007-05-30 09:50 PM
0 Kudos
Reply
1,190 Views
bigmac
Specialist III
Hello,
 
There are a couple of possibilities that seem to give the desired results -
 
#define PWM_MODULUS 0x0400
#define V_PULLIN  100L
#define V_HOLDING 18L
 
const unsigned short PWM_HOLDING = (PWM_MODULUS * V_HOLDING) / 120;
const unsigned short PWM_PULLIN = (PWM_MODULUS * V_PULLIN) / 120;
 
GLOBALVAR = ANOUTHERVAR / (char)V_HOLDING;

The second possibility is as follows, where PWM_MODULUS is forced to be a 32-bit value, giving the result of the multiplication also 32-bit.
 
#define PWM_MODULUS 0x0400L
#define V_PULLIN  100
#define V_HOLDING 18
 
const unsigned short PWM_HOLDING = (PWM_MODULUS * V_HOLDING) / 120;
const unsigned short PWM_PULLIN = (PWM_MODULUS * V_PULLIN) / 120;
 
GLOBALVAR = ANOUTHERVAR / V_HOLDING;
 
The final statement for either method takes the same number of bus cycles to execute (115 cycles when simulating a HC908 device).
 
Regards,
Mac
 
0 Kudos
Reply
1,189 Views
RShaich
Contributor II
Thank you for your help.
It is much clearer now.

While my example was over simplified I believe you have given me enough information to get this to work. I will be back on this contract next week and will let you know if I have any more issues with this.

Thanx again for your help.

Rick

0 Kudos
Reply