# dsPIC fractional Multiplication Help needed.

Discussion in 'Embedded Systems and Microcontrollers' started by picstudent, Aug 24, 2014.

1. ### picstudent Thread Starter Well-Known Member

Feb 3, 2009
76
0
My ADC conversion code (Courtesy This Post)

Code ( (Unknown Language)):
1. // Pressure sensor is for 600bar in 0to 5V out - so to get a decimal place I am using 6000 !
2. PressureinBarWithOneDeciPlace=((((((unsigned long)ADCResultofPSensor*2)+1) *6000) +1024) /2048);
I am using dsPIC30F.
The first statement generates a code which runs in 25 cycles which is reasonable for me.
But the second line takes around 350 cycles which seems not a informed choice.
I am not that much familiar in fixed or floating point methods.
But from my reading it seems to me that there should be some economical methods to multiply by 2.2698... in fixed point library.
to multiply by 2.2698.. first I left shift once - which completes the multiplication by 2
now I need to multiply by .2695... using Q15 functions and then add.
How to do this?
Can I get a optimum method to implement my task with the help of DSP features of dsPIC30F controller.
Thanks

2. ### MrChips Moderator

Oct 2, 2009
14,282
4,195
As a general rule, if I want optimum execution speed I avoid using floating point entirely.

The fixed point method you choose will depend on the accuracy desired, number of bits used and the range of parameters.

Multiply by 581 and then divide by 256 (right shift by 8 bits).
Check to make sure that the multiplication does not result in an overflow, that is, the range of numbers and the number of bits guarantee no overflow.

picstudent likes this.
3. ### MrChips Moderator

Oct 2, 2009
14,282
4,195
To give you some more wriggle room you can multiply by 2 first and them add
69/256.

Remember, if your processor is byte oriented, dividing by 256 simply means truncating the least significant byte.

Can your processor handle 24 or 32 bit multiplications?

picstudent likes this.
4. ### MrChips Moderator

Oct 2, 2009
14,282
4,195
And just to add to your fixed point computational repertoire, suppose your processor does not have efficient hardware multiplication.

To multiply by 69, multiply by (64 + 4 + 1).

picstudent likes this.
5. ### picstudent Thread Starter Well-Known Member

Feb 3, 2009
76
0
Thanks for the tips
My processor is dsPIC30F4011, it is having a fixed point DSP engine, I suppose.
Regarding multiplication Datasheet says
"17-bit x 17-bit single-cycle hardware fractional/integer multiplier"

"Multiply by 581 and then divide by 256 (right shift by 8 bits)." is a piece of cake for this processor.
I have implemented that method in my code
Code ( (Unknown Language)):
1.
2. #define PTransMultiConst 6000  // or 5000 depending on transducer
3. PresureInBarWithOneDeciPlace=
4.           ((((((unsigned long)PressureTransResult*2)+1)
5.                 *PTransMultiConst) +1024) /2048);
6.         Nop();
8.          (unsigned int)(((unsigned long)PresureInBarWithOneDeciPlace*581)/256);
Multiply by 581 ND Divide by 256 Takes only 20cycles.
So compiler also may be using the same thing
"To multiply by 69, multiply by (64 + 4 + 1). "
I think the above method can make the code more efficient.
Thanks for the support

6. ### NorthGuy Active Member

Jun 28, 2014
611
122
This is a huge difference in accuracy between

1. multiplying by 2.2698006535F

2. multiplying by 581/256 = 2.2695312500 - x = (y*581)>>8;

3. multiply by 37189/16384 = 2.2698364258 - x = (y*37189L)>>14;

The question is what accuracy you need.

You have 16-bit processor, so either #2 or #3 should take 2 instructions (cycles), everything else is C gibberish, which you can keep if it's acceptable, or write your two instructions in asm if it is unacceptable.

EDIT: My mistake. The shift is crossing bouneries, so it'll probably take 4-6 cycles for #2 and #3 (not 2 as I previously said).

#3 can also be futher optimized (for this processor only) by pre-multiplying by 4, then you don't need a shift, then it can be done in 3-4 cycles.

Last edited: Aug 24, 2014
picstudent likes this.
7. ### picstudent Thread Starter Well-Known Member

Feb 3, 2009
76
0
Thanks for the clarifications.
Actually the solution of "37189/16384" makes me more closer to my constant.
My constant is already slightly "compromised".
It is actually (3.1415926*170*170*.1/4000).

btw I have not done anything in assembly for dsPIC. for PIC16F, I always do in assembly. So that optimization may not be worth the effort in my special case.
Thanks again