|
|
View previous topic :: View next topic |
Author |
Message |
levdev
Joined: 19 May 2010 Posts: 36 Location: UK
|
How to speed up my calculation? |
Posted: Wed May 19, 2010 8:46 am |
|
|
I am using the PIC18F26K20, running at 2Mhz (due to low power requirements). I have to calculate the following equation
Result = sqrt(X^2 + Y^2 + Z^2)
X, Y and Z are signed long integers (signed int16). The maximum values they can have in my program is ±2048.
Result is an unsigned int32
for the sqrt function I am using some code I found on this forum :
Code: | int16 Sqrt32(int32 r)
{
int32 t,b,c=0;
for (b=0x10000000;b!=0;b>>=2)
{
t = c + b;
c >>= 1;
if (t <= r)
{
r -= t;
c += b;
}
}
return(c);
} |
which gives much faster results than the standard CCS sqrt function.
I am currently using the code:
Code: | int32 ACCEL_SUM, X2, Y2, Z2;
int16 ACCEL_RES;
X2 = (signed int32)X_ACCEL * (signed int32)X_ACCEL;
Y2 = (signed int32)Y_ACCEL * (signed int32)Y_ACCEL;
Z2 = (signed int32)Z_ACCEL * (signed int32)Z_ACCEL;
ACCEL_SUM = X2 + Y2 + Z2;
ACCEL_RES = Sqrt32(ACCEL_SUM); |
Can anyone suggest some improvements to this to help it run in less clock cycles. Ideally I need to complete the calculcation in <0.5ms which on a 2MHz clock means doing it within 250 instruction cycles. Any suggestions to help me get closer to my target would be appreciated.
Oh, one other thing I forgot to ask, short of measuring the timimg of an output pin pulse before and after the calculation, is there anyway of predictng the calculation time in the compiler? I a using PCWH version 4.106. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19589
|
|
Posted: Wed May 19, 2010 9:22 am |
|
|
One really 'glaring' one. Don't convert the values to int32 before the maths. Use _mul instead.
So:
X2 = _mul(X_ACCEL,X_ACCEL);
You'll have to test if this works with signed, but it not, it'd be much faster to handle the signage yourself.
As another comment, remember that you can switch oscillators for a short code segment, so there is no reason why you can't switch to using the internal oscillator at 8MHz, just for this arithmetic, and then switch back down when this is finished. You might even find you can leave the chip at a slower rate like 500KHz, 'between' the bits needing speed.
Best Wishes |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19589
|
|
Posted: Wed May 19, 2010 9:25 am |
|
|
In fact, as you are squaring, the result must always be +ve, so don't use signed, since this will be slower than unsigned arithmetic. Make the values +ve before you start.
Best Wishes |
|
|
levdev
Joined: 19 May 2010 Posts: 36 Location: UK
|
|
Posted: Wed May 19, 2010 10:12 am |
|
|
Thanks for your help with this, I wasn't aware of the _mul function. So now I've got :
Code: |
int32 ACCEL_SUM, X2, Y2, Z2;
int16 ACCEL_RES, XT, YT, ZT;
XT = abs(X_ACCEL);
X2 = _mul(XT, XT);
YT = abs(Y_ACCEL);
Y2 = _mul(YT, YT);
ZT = abs(Z_ACCEL);
Z2 = _mul(ZT, ZT);
ACCEL_SUM = X2 + Y2 + Z2;
ACCEL_RES = Sqrt32(ACCEL_SUM);
|
Would you consider this to be as optimised as I can be?
Is there a way of predicting the calculation time within the compiler without using a hardware measurement solution?
Regarding changing the processor speed, is there any latency between switching from say 500Khz to 8Mhz then back again? |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|