B_f = (freq_khz * freq_khz)/10;

# HC08LB8 arithmetic operation

B_f = (freq_khz * freq_khz)/10;

Hello, i am working with a HC08LB8, freq_khz is a number between [40, 120], A_f, B_f are 16bit variables

My code is:

A_f = (((3 * freq_khz * freq_khz)/50)+6 * freq_khz+8432);

B_f = (freq_khz * freq_khz)/10;

B_f = (freq_khz * freq_khz)/10;

the opertion:

A_f = (((3 * freq_khz * freq_khz)/50)+6 *freq_khz+8432);

return a correct result, but in the next line:

B_f = (freq_khz * freq_khz)/10;

the result is not the right, i think that the problem is the CCR (Condition Code Register) but i do not know how make for have a correct result.

Thanks you.

- Hello rceit,A further issue may be that the variable A_f (and B_f) may need to be unsigned int for the first equation to work for all allowable values of freq_khz. This is because the partial calculation 3*freq_khz*freq_khz may overflow a signed int value. You don't specify what you are currently using.Regards,Mac
Hello rceit,

I have now actually tried out your equations in the simulator, and obtained the expected results for both A_f and B_f variables, with freq_khz firstly set for 40, and then for a value of 120. I declared all three variables as unsigned int.

The following results were obtained:

freq_khz A_f B_f

40 8768 160

120 10016 1440Regards,

Mac- Hello bigmac and rocco, thanks for your reply.

This is the complete code, in my last post i have put less code for simplify the question, but in this way the information it is not full, sorry.

this is my code :

volt_T1=ADR; // get ADR value

freq_khz =AUX_K/HRPPER; // freq_khz between [40,120]

A_f = (((3 * freq_khz * freq_khz)/50)+(6 * freq_khz+8432));

//(3 * freq_khz * freq_khz) do not causes overflow in A_f?

B_f = (((9 * freq_khz * freq_khz)/10)+(2*freq_khz+12787))/10;

// 9 * freq_khz*freq_khz causes overflow and a bad B_f value?

// what is the solution? unsigned long?

volt_pk_T1_bin = (A_f * volt_T1 + B_f)/100;

// A_f * volt_T1 also causes overflow

Declaration of variables:

tU16 volt_pk_T1_bin; typedef unsigned int tU16;

extern tU16 extern tU16 A_f;;

tU16 A_f; typedef unsigned int tU16; extern tU16 A_f;

tU16 B_f; typedef unsigned int tU16; extern tU16 B_f;

//A_f, B_f, volt_pk_T1_bin are unsigned int globalMessage Edited by rceit on 2006-06-11 05:44 AM

- Hi, Rceit:

Yes, a number of terms in your equations exceed 65535 when the frequency is 120. So unsigned integers are not large enough.

If you are doing this all in C, I would suggest using longs. It may not matter whether you use signed or unsigned, but in my math library signed is a tiny bit more efficient than unsigned. I don't know about your C, however. Longs will certainly be more efficient than switching to floats.- Hi rocco, my code is C. I have try with unsigned long but this not works.In my Sources folder i have defined basic mathematical functions:

Code:/***************************************************************************** Intrinsic functions definition*****************************************************************************/SByte Add_8(SByte x, SByte y); /* source sdkmath.asm */SByte Lim_8(SByte x, SByte limit); /* source sdkmath.c */SByte Neg_8(SByte x); /* source sdkmath.asm */SByte Shl_8(SByte x, UByte n); /* source sdkmath.asm */SByte Sub_8(SByte x, SByte y); /* source sdkmath.asm */SWord16 Add(SWord16 x, SWord16 y); /* source sdkmath.asm */SWord16 Lim(SWord16 x, SWord16 limit); /* source sdkmath.c */SWord16 Neg(SWord16 x); /* source sdkmath.asm */SWord16 Shl(SWord16 x, UByte n); /* source sdkmath.asm */SWord16 Sub(SWord16 x, SWord16 y); /* source sdkmath.asm */UWord16 Umul_16x8 (UWord16 x, UByte y); /* source sdkmath.c */SWord16 Smul_16x8 (SWord16 x, UByte y); /* source sdkmath.c */SWord16 Smul_8(SByte x, UByte y); /* source sdkmath.c */SByte Sdiv_8(SWord16 x, UByte y); /* source sdkmath.asm */UByte Udiv_16to8(UWord16 x, UWord16 y); /* source sdkmath.asm */

May be this the problem? the arithmetical operations works with this funtions? if this is correct i can not make unsigned long opertions only the operations specified in the funtions list.(Alban formatted code)Message Edited by Alban on 2006-06-12 10:18 AM

- Hello rceit,If you wish to stick with the use of unsigned int, you might modify the second formula as follows -B_f = ((((freq_khz*freq_khz)/10)*9)+(2*freq_khz+12787))/10;

This will do the division before the multiplication, and prevent overflow. There could be a slight loss of precision due to integer rounding errors, but since you are doing a final division by 10, this should not be apparent in the end result.Regards,

MacHello Mac,

The problem of overflow is solved for B_f, but it continues with :

volt_pk_T1_bin = (A_f * volt_T1 + B_f)/100;

and any change done an inaceptable loss of resolution. The problem will be the mathematical functions described in 2006-06-1202:59 AMreply?

Hello rceit,

rceit wrote:

The problem of overflow is solved for B_f, but it continues with :volt_pk_T1_bin = (A_f * volt_T1 + B_f)/100;

and any change done an inaceptable loss of resolution.

Why do you not use the CW library for integer mathematical functions where I assume long variables can be handled?

You do not mention the range of values expected for volt_T1 variable. You imply that this is equal to an address - or should this be the contents of an address - but this is not clear. According to my calculations the range of values for A_f is 8768 to 10016, and for B_f the range is 1430 to 2598. You may want to divide each of these by 100 prior to multiplying the first term by the volt_T1 value, with a maximum allowed value of about 655 when A_f and B_f have their maximum values. So the formula might be re-arranged as follows:

volt_pk_T1_bin = ((A_f + 50)/100 * volt_T1 + (B_f + 50)/100;

Note the rounding correction for the integer division process. This is probably the best result achievable with integer arithmetic on 16-bit values. The rounding correction might also be applied to the calculation of A_f and B_f (assuming the formulae do not already do this).

Regards,

Mac

How is freq_khz defined? is it an 8-bit or 16-bit value?

What do you get as an incorrect result, and for what value of freq_khz?

Can you post the generated assembly code?