dsPIC fractional Multiplication Help needed.

Thread Starter

picstudent

Joined Feb 3, 2009
91
My ADC conversion code (Courtesy This Post)

Rich (BB code):
// Pressure sensor is for 600bar in 0to 5V out - so to get a decimal place I am using 6000 ! 
PressureinBarWithOneDeciPlace=((((((unsigned long)ADCResultofPSensor*2)+1) *6000) +1024) /2048);
LoadInKNWithOneDeciplace= (unsigned int)((float)PressureinBarWithOneDeciPlace*2.2698006535F);
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
 

MrChips

Joined Oct 2, 2009
30,720
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.
 

MrChips

Joined Oct 2, 2009
30,720
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?
 

MrChips

Joined Oct 2, 2009
30,720
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).
 

Thread Starter

picstudent

Joined Feb 3, 2009
91
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"

I think your solution of
"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
Rich (BB code):
#define PTransMultiConst 6000  // or 5000 depending on transducer
PresureInBarWithOneDeciPlace=
          ((((((unsigned long)PressureTransResult*2)+1)
                *PTransMultiConst) +1024) /2048);
        Nop();
        LoadInKNWithOneDeciplace=
         (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
 

NorthGuy

Joined Jun 28, 2014
611
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:

Thread Starter

picstudent

Joined Feb 3, 2009
91
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
 
Top