# Fixed Point Multiplications and Scaling of Normalized Quantities

Hello all,

I think I'm reinventing the wheel here, but I'll go ahead and ask some of the concepts that are haunting me and my dear dsPIC33F controller!

I ran a thread a few days ago on the basics of fixed-point arithmetic and how the __builtin functions are to be used to get the desired values.

I am now, thanks to everyone's valuable insights, able to properly compute floating point math operations on the dsPIC.

Here is the procedure, I'm religiously following to get the desired results:

- Normalize each real number by a value greater than it and represent it in Q15 format.
- Multiply both the numbers and use the __builtin_sacr rounding function to get the result in Q15.
- Finally, take this intermediate result and multiply with the base values to get the actual number.

Here's a code that works:

#include <stdlib.h>

#include <stdint.h>

#include<xc.h>

int main(void)

{

volatile register int16_t aReg asm("A");

int16_t val1, val2, base1 = 400, base2 = 10, base3;

int32_t temp;

signed long result;

val1 = 257.34*32768/base1; //normalizing 257.34 on a base of 400 converting to Q15

val2 = 7.723*32768/base2; //normalizing 7.723 on a base of 10 and converting to Q15

CORCONbits.US = 1; //DSP engine multiplies are signed

CORCONbits.IF = 0; //DSP engine in fractional mode

CORCONbits.ACCSAT = 1;// 9.31 saturation

aReg = __builtin_mpy(val1, val2, 0, 0 ,0 ,0 ,0 ,0); //Q30 number

base3 = base1*base2;

temp = __builtin_sacr(aReg,0); //result in Q15

result = __builtin_mulss(temp,base3); //result = 0x3E1A700 (Q15) = 1987.304688 <<<---- Expected Answer

while(1);

}

This works well for smaller numbers. But the very same recipe doesn't work when significantly larger numbers are involved.

For example,

#include <stdlib.h>

#include <stdint.h>

#include<xc.h>

int main(void)

{

volatile register int16_t aReg asm("A");

int16_t val1, val2, base1 = 4000, base2 = 40, base3;

int32_t temp;

signed long result;

val1 = 3400*(32768/base1); //Q15

val2 = 25.86*(32768/base2); //Q15

CORCONbits.US = 1;

CORCONbits.IF = 0;

CORCONbits.ACCSAT = 1;

CORCONbits.SATA = 1;

aReg = __builtin_mpy(val1, val2, 0, 0 ,0 ,0 ,0 ,0); //Q30 number

base3 = base1*base2; //base3 = 0x00027100

temp = __builtin_sacr(aReg,0); //temp = 0x000044AC

result = __builtin_mulss(temp,base3); //result = 0x1E4FEC00 = 15519.84

while(1);

}

Now, 15519.84 is clearly not the correct answer because the actual answer of this computation must be, 87924. Can anyone tell me what might be the reason for such erroneous results?

Thank you.

post edited by PICrukie - 2019/06/16 16:15:40