CCS does not monitor this forum on a regular basis. Please do not post bug Reports on this forum. Send them to support@ccsinfo.com
Author Message
iso9001

Joined: 02 Dec 2003
Posts: 262

Need some fixed point math help,
Posted: Fri Mar 03, 2006 7:25 pm

I need to read in a 16bit number from ADC and then modify it by a certain percentage. I searched but found no examples of anyone doing this, (I know, I know, keep reading)

I read that Floating point is slow and fixed point is better, but I just can't see how to do fixed point with the data I have since I need to send it over spi as the modified number when finished

ex:
 Code: int16 x; float percent = .204; //20.4% ... x = read_adc(); x = (x * percent) + x; spi_write(x);

Maybe I am missing somthing but if I did this in fixed point wouldn't I have to do this:
 Code: int16 x; int percent = 204; ... x = read_adc(); x*= 10; x = (x * percent) + x; x/=10; spi_write(x);

Which does not at all seem like a good idea. Is there any faster way add a percentage to a number ?

I don't think lookup table will work since I have over 8000 possible values coming in. Besides I think that would take more then the 32k I have for rom

But speed is VERY important.

Ideas ?
Guest

 Actually, Posted: Sat Mar 04, 2006 12:26 am I'de like to know how to do this also. I am was working on somthing like this awhile back. I used floating point but I had 100ms between samples so I really could do whatever I wanted. Did feel a little guilty using floating point
Ttelmah
Guest

Posted: Sat Mar 04, 2006 5:10 am

Normally, when working with integers like this, you keep the integer scaled. So (for instance), you might multiply the incoming number by 100, and then only divide it back at the end of whatever operations you want. For the simple scaling here, provided you are only multiplying, then staying with a float, is probably the best solution. A float multiplication, on a 40MHz PIC18, only takes typically 36uSec (remember these chips have a hardware 8*8 multiplier, which makes a big difference). There will be some overhead, converting back from float to integer, but the total from using int arithmetic is not likely to be much better. Where things improve a lot, is on things like division, where a float divide easily takes 4* the time of an int16 divide, and things like sin, where the time shoots up.
I'd suggest that the fastest solution, would be:

Note the use of '1+percent', rather than multiplying, and then performing an addition. A float addition, actually takes longer than a multiply on a PIC18, and you are already performing a multiply, so why not do the two operations in one!. Also using a constant, may save a couple of I/O cycles.

Best Wishes
rberek

Joined: 10 Jan 2005
Posts: 207

 Posted: Sat Mar 04, 2006 7:39 am You can also do a multiplication by 1.204 as a shift and add operation. It will not be exact but you can get it within 21 parts per million if you are using a 16-bit x value. x * 1.204 is approximately equal to x + x/8 + x/16 + x/64 + x/2048 + x/4096 + x/8192 or x + x>>3 + x>>4 + x>>6 + x>>11 + x>>12 + x>>13 Actually this gives you x*1.203979 which should be close enough for most people. I don't know how this works as far as speed goes, but I offer it as an alternative._________________The difference between genius and stupidity is that genius has its limits...
Ttelmah
Guest

 Posted: Sat Mar 04, 2006 10:18 am I suspect it'll be slower on the 18 chips, but might be better on the 16 chips (because of the lack of the hardware multiplier). You'd probably be better to shift a temporary store, otherwise there is a lot of 'repeat shifting' going on. Certainly in many cases, an approach like this is well worth considering. Best Wishes
iso9001

Joined: 02 Dec 2003
Posts: 262

 Posted: Sat Mar 04, 2006 1:58 pm Freakin sweet! I like both. I feel rather dumb for forgeting to * 1.204 and not *.204+x. Don't know what I was thinking. I know the 18F has the hardware multiply, but going off of CCS's chart in the help file it looks like my mulitply will take ~360 instructions like Ttelmah said. I need to do this twice in a row for two different numbers so I almost thinking 360x2 is near the time limit I have. I really like the shifting. That seems to me like it would be less then ~350, but I have no idea yet. I'll need to look closer at how you figured out the shift pattern. I don't get it but I only glanced at it for a second. Wanted to say thanks, I'll try a bunch of different ways out and time them all Ttelmah: Shift a temporary store ??
rberek

Joined: 10 Jan 2005
Posts: 207

Posted: Sat Mar 04, 2006 3:46 pm

Its just binary math.

When you do an integer binary multiplication, like 56x11, you'd do
 Code: 0111000           x                1011                    ------------                         0111000              +         01110000              +       0111000000                ----------------                      1001101000

Which is 56 + (56x2) + (56x8)

or

56 + 56<<1 + 56<<3

You do the same thing in decimal multiplication too, but you never think about it.

When you do fractions in binary, you only have available 1/2, 1/4, 1/8 etc to make up the decimal fraction. If you look at .204, it is made up of:

0.125 + 0.0625 + 0.15625 ....

you can come close to representing any decimal fraction as binary shifts, as long as the number you are shifting is large enough. Clearly you can't right-shift a 4-bit number very often before the shift results in a zero.
_________________
The difference between genius and stupidity is that genius has its limits...
Mark

Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

 Posted: Sat Mar 04, 2006 3:46 pm If your percentage is fixed at 20.4% then multiplying by 209 and dividing by 1024 will give you 20.41%. The divide by 1024 will be fast since its a binary number. If you can live with 20.3% then you could just multiply by 52 and truncate the last byte.
Holy Ghost
Guest

 Back again Posted: Sun Mar 05, 2006 7:39 pm Wow, Nice to see that Mark has made a "comeback" to the forum.. Cheers..
Mark

Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

 Posted: Mon Mar 06, 2006 7:42 pm I've been quite busy (and still am) at work and started shifting towards ARM7's which accounts for my lack of participation
 Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First
 All times are GMT - 6 Hours Page 1 of 1

 Jump to: Select a forum Software----------------General CCS C DiscussionCode LibraryEZ App Lynx Hardware----------------CCS ICD / Mach X / Load-n-Go
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