• Forums
• Posts
Latest Posts
Active Posts
Recently Visited
Search Results
• Page Extras
• Forum Themes
• AVR Freaks

Author
PICrukie
New Member
• Total Posts : 28
• Reward points : 0
• Joined: 2019/04/09 14:11:53
• Location: 0
• Status: offline
0

# 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:
1.  Normalize each real number by a value greater than it and represent it in Q15 format.
2. Multiply both the numbers and use the __builtin_sacr rounding function to get the result in Q15.
3. 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 Q15val2 = 7.723*32768/base2;  //normalizing 7.723 on a base of 10 and converting to Q15CORCONbits.US = 1; //DSP engine multiplies are signedCORCONbits.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 numberbase3 = base1*base2;temp = __builtin_sacr(aReg,0); //result in Q15result = __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); //Q15val2 = 25.86*(32768/base2); //Q15CORCONbits.US = 1;CORCONbits.IF = 0;CORCONbits.ACCSAT = 1;CORCONbits.SATA = 1; aReg = __builtin_mpy(val1, val2, 0, 0 ,0 ,0 ,0 ,0); //Q30 numberbase3 = base1*base2; //base3 = 0x00027100temp = __builtin_sacr(aReg,0); //temp = 0x000044ACresult = __builtin_mulss(temp,base3); //result = 0x1E4FEC00 = 15519.84while(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
List Solutions Only

du00000001
Just Some Member
• Total Posts : 3065
• Reward points : 0
• Joined: 2016/05/03 13:52:42
• Location: Germany
• Status: offline
Re: Fixed Point Multiplications and Scaling of Normalized Quantities 2019/06/16 16:24:42 (permalink)
4 (1)
I didn't follow all of your elaborations, but did you notice that in your none-functional example base1*base2 is larger than 2^16? Which might well be the cause of the wrong result.

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
T Yorky
Super (Thick) Member
• Total Posts : 526
• Reward points : 0
• Joined: 2012/08/28 02:07:35
• Location: UK
• Status: offline
Re: Fixed Point Multiplications and Scaling of Normalized Quantities 2019/06/17 10:56:44 (permalink) ☄ Helpfulby PICrukie 2019/06/18 09:02:08
0
'reinventing the wheel'
Sorry PICrukie, you've not invented anything here. The PIC33F is a 'very mature' design. There is probably 10 years or more of examples to read. You may even have to get a copy of the older MPLab 8 and read some of the helpfiles.
Just as a guide there is a macro Q15() to create Q15 numbers. The (old) documentation describes all the techniques needed to use fixed point (NOT floating point) binary numbers. Don't become 'obsessed' with Q15. It is just a method of interpreting a binary number. No magic.
Good luck.
T Yorky.