• AVR Freaks

Helpful ReplyHot!Fixed Point Multiplications and Scaling of Normalized Quantities

Author
PICrukie
New Member
  • Total Posts : 28
  • Reward points : 0
  • Joined: 2019/04/09 14:11:53
  • Location: 0
  • Status: offline
2019/06/16 16:10:49 (permalink)
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 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
#1
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)
#2
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.
#3
Jump to:
© 2019 APG vNext Commercial Version 4.5