Forums

Using FRAC16

Started by Oscar Jaramillo March 12, 2004
Greetings.
 
I need your help understanding the use of FRAC16 format in the C CodeWarrior programation.
 
When I have a quantity, for example, 15 how I transform this number to FRAC16 format?
 
I make this this question because I want to know like making this calculation:
 
Isensed = Value form ADC; (in FRAC16 type or form)
V = Isensed * Resistance; /*But Resistance = 15 Ohm*/
 
/*how transform Resistance to FRAC16 format, to obtain V in FRAC16 format?*/


Cordialmete,

Oscar Javier Tadeo Jaramillo Galeano.
Nit: 98665185-4

Telefono. 300-779-60-62



car.gif Busc un auto?
Encontralo en Yahoo! Autos
M de 4000 clasificados todos los ds!
Usados - 0 km - Vendel tuyo


--- In , Oscar Jaramillo <ojataga@y...>
wrote:
> Greetings.
>
> I need your help understanding the use of FRAC16 format in the C
CodeWarrior programation.
>
> When I have a quantity, for example, 15 how I transform this number
to FRAC16 format?
>
> I make this this question because I want to know like making this
calculation:
>
> Isensed = Value form ADC; (in FRAC16 type or form)
> V = Isensed * Resistance; /*But Resistance = 15 Ohm*/
>
> /*how transform Resistance to FRAC16 format, to obtain V in FRAC16
format?*/
>

The first thing you have to realize is that C doesn't support fixed
point, it simply isn't in the standard. So instead we typecast
Frac16 to signed short integers. So instead of an integer between
-32768 and 32767 we think of a fraction between -1 and 1-2^(-15) by
simply dividing by 32768.

This works great as long as you are adding, since adding integers is
the same as adding fractions. (You add the numerators...) So a line
of C code such as
Z = X + Y;
works regardless of whether X,Y, and Z are thought of as fractions or
integers.

But Z = X*Y won't produce what you want. Since X and Y are both
fractions in the range [-1,1) their product will also be in this
range. But the product of two 16 bit numbers is a 32 bit number. So
what C does in Z = X*Y is calculate the product of two 16 bit
integers and then truncate the result by assigning the lower 16 bits
into Z. That's exactly not what you want. What you want is for C to
assign to Z the upper part.

There is also the issue of the redundant sign bit. So if you
declared a long integer and then did the calculation it would still
be off by a factor of two:

long ZBig;

ZBig = X*Y;
Z = ZBig >> 16;

So if X=1/2, Y = 1/4 then you want X*Y = 1/8. But Z = 1/16 in the
calculation above. The reason for this is that the product of two
short integers produces a long integer (16x16 bits = 32 bits) which
has a redundant sign bit. So infact you need to do the following:

ZBig = X*Y;
Z = ZBig >> 15;

It is simply easier (and safer) to use one of the multiply primitives
from SDK/Processor Expert:

Z = mult_r(X,Y);

O.K. - So adding in C is fine, but multiplying is dangerous unless
you use the right primitives.

The other trick to converting an algorithm in floating point to fixed
point is to realize that in fixed point you don't carry the exponent
in the calculation, just the mantissa. So each term of your
calculation is just a mantissa in the range [-1,1). The exponent you
have to keep in your head or calculate separately. "Block floating
point" is a technique of scaling all the terms to have the same
exponent, calculating with just the mantissas (fractions) and
maintaining the exponent separately (either in your head or as a
separate calculation).