3

I'm currently using Microchip's Fixed Point Library, but I think this applies to most fixed point libraries. It supports Q15 and Q15.16 types, respectively 16-bit and 32-bit data.

One thing I noticed is that it does not include add, subtract, multiply or divide functions.

How am I supposed to do these? Is it as simple as just adding/subtracting/multiplying/dividing them together using integer math? I can see addition and subtraction working, but multiplying or dividing wouldn't take care of the fractional part...?

Thomas O
  • 6,026
  • 12
  • 42
  • 60
  • 2
    If it can't add, subtract, multiply or divide, what can it do? – robert Dec 05 '10 at 00:28
  • @robert, All trig functions and inverses, exp, power, sqrt, log - as well as pretty much all floating point functions. – Thomas O Dec 05 '10 at 00:31
  • Are `_Q16mac` and `_Q16reciprocal` no use to you? `_Q15add' and '_Q16neg' should facilitate add / subtract. – Will A Dec 05 '10 at 00:39
  • @WillA, They might be, but MAC will be slower than plain old multiply and reciprocal would lose precision with large denominators. – Thomas O Dec 05 '10 at 00:40
  • @Thomas - take a look here http://www.microchip.com/forums/m450988.aspx for a divide function. Worth giving _Q16mac a go - if it's too slow it's too slow, but it may well be quick enough. – Will A Dec 05 '10 at 00:42
  • @Will A So it doesn't support divide... hmm, confirms my suspicions. Will have to use reciprocal... – Thomas O Dec 05 '10 at 00:48

2 Answers2

1

The Microsoft library includes functions for adding and subtracting that deal with underflow/overflow (_Q15add and _Q15sub).

Multiplication can be implemented as an assembly function (I think the code is good - this is from memory).

C calling prototype is:

extern _Q15 Q15mpy(_Q15 a, _Q15 b);

The routine (placed in a .s source file in your project) is:

.global _Q15mpy
_Q15mpy:
mul.ss w0, w1, w2        ; signed multiple parameters, result in w2:w3
SL w2, w2            ; place most significant bit of W2 in carry
RLC w3, w0           ; rotate left carry into w3; result in W0
return                        ; return value in W0

.end

Remember to include libq.h

This routine does a left-shift of one bit rather than a right-shift of 15 bit on the result. There are no overflow concerns because Q15 numbers always have a magnitude <= 1.

EBlake
  • 735
  • 7
  • 14
0

It turns out that all basic arithmetic functions are performed by using the native operators due to how the numbers are represented. e.g. divide uses the / operator and multiply the * operator, and these compile to simple 32-bit divides and multiplies.

Thomas O
  • 6,026
  • 12
  • 42
  • 60