Forums

Fractional Math

Started by Terry Litinas December 6, 2002
Hello,

I am working on a project with the DSP56F807, CodeWarrior 5.02, and SDK 2.5
and am fairly new to the DSP world. I have questions concerning fractional
and integer math for my application. When reading an 807 ADC channel I am
interpreting the value as a 16 bit fractional value (Frac16) which gives me
a "percent full scale" reading which would be convenient to multiply by full
scale to generate a value in units of volts, degrees, etc. For example if
full scale for the input is 10V (before hardware attenuation) and the ADC
reading is 0.5, the input voltage is 0.5 x 10V = 5V. I don't see a way to
directly implement an equation like this due to the mixture of integer and
fractional values. Is there an efficient way to do this (preferably in C) or
should I go back to 16.16 - integer part in upper 16 bits and fractional
part in lower 16? I feel that I am missing something here.

Also while experimenting, I ran across what may be a compiler bug. When
multiplying two Frac16 numbers and putting the result in a Frac32 variable I
find that the result always seems to be 1/2 of the expected value. The code
below is an example. 0.5 x 0.5 = 0.125 instead of 0.25. The compiler puts an
asr instruction following the mpy that causes the problem. Has anyone seen
this? ; 7: void Test16x16Multiply (void)
; 8: {
; 9: Frac16 a, b;
; 10: Frac32 c;
; 11:
;
0x00000000 FTest16x16Multiply:
0x00000000 0xCC02 movei #2,N
0x00000001 0xDE0F lea (SP)+N
;
; 12: a = FRAC16(.5);
;
0x00000002 0xA7B34000 moves #16384,X:0x0033
;
; 13: b = FRAC16(.5);
; 14:
;
0x00000004 0xA7B24000 moves #16384,X:0x0032
;
; 15: c = a * b;
;
0x00000006 0xB132 moves X:0x0032,Y0
0x00000007 0xB033 moves X:0x0033,X0
0x00000008 0x64C8 mpy +Y0,X0,B
0x00000009 0x7CB0 asr B
0x0000000A 0xD71F move B1,X:(SP)
0x0000000B 0xD1CBFFFF move B0,X:(SP-0x0001)
;
; 16: }
0x0000000D 0x9EFE lea (SP-0x0002)
0x0000000E 0xEDD8 rts Thanks for any help.

Terry Litinas
Project Engineer
ITW Balance Engineering
1731 Thorncroft
Troy, Mi. 48084

Ph: (248)643-2876
Fx: (248)643-2888



Terry,

One suggestion, rather than storing your result as volts store it as
hundreds of volts so that you multiply by 0.1V rather than 10V.

#include "mfr16.h" // Basic math
Frac16 adc,scaler,scaled;
adc=read_ADC();
scaler=FRAC16(.1);
scalered = mult(adc,scaler);

For the multiply try using the fixed-point math libraries as shown
above. Also, be wary of saturation, if not set properly trig
libraries don't work. Jacob

--- In motoroladsp@y..., "Terry Litinas" <tlitinas@i...> wrote:
> Hello,
>
> I am working on a project with the DSP56F807, CodeWarrior 5.02, and
SDK 2.5
> and am fairly new to the DSP world. I have questions concerning
fractional
> and integer math for my application. When reading an 807 ADC
channel I am
> interpreting the value as a 16 bit fractional value (Frac16) which
gives me
> a "percent full scale" reading which would be convenient to
multiply by full
> scale to generate a value in units of volts, degrees, etc. For
example if
> full scale for the input is 10V (before hardware attenuation) and
the ADC
> reading is 0.5, the input voltage is 0.5 x 10V = 5V. I don't see a
way to
> directly implement an equation like this due to the mixture of
integer and
> fractional values. Is there an efficient way to do this (preferably
in C) or
> should I go back to 16.16 - integer part in upper 16 bits and
fractional
> part in lower 16? I feel that I am missing something here.
>
> Also while experimenting, I ran across what may be a compiler bug.
When
> multiplying two Frac16 numbers and putting the result in a Frac32
variable I
> find that the result always seems to be 1/2 of the expected value.
The code
> below is an example. 0.5 x 0.5 = 0.125 instead of 0.25. The
compiler puts an
> asr instruction following the mpy that causes the problem. Has
anyone seen
> this? > ; 7: void Test16x16Multiply (void)
> ; 8: {
> ; 9: Frac16 a, b;
> ; 10: Frac32 c;
> ; 11:
> ;
> 0x00000000 FTest16x16Multiply:
> 0x00000000 0xCC02 movei #2,N
> 0x00000001 0xDE0F lea (SP)+N
> ;
> ; 12: a = FRAC16(.5);
> ;
> 0x00000002 0xA7B34000 moves #16384,X:0x0033
> ;
> ; 13: b = FRAC16(.5);
> ; 14:
> ;
> 0x00000004 0xA7B24000 moves #16384,X:0x0032
> ;
> ; 15: c = a * b;
> ;
> 0x00000006 0xB132 moves X:0x0032,Y0
> 0x00000007 0xB033 moves X:0x0033,X0
> 0x00000008 0x64C8 mpy +Y0,X0,B
> 0x00000009 0x7CB0 asr B
> 0x0000000A 0xD71F move B1,X:(SP)
> 0x0000000B 0xD1CBFFFF move B0,X:(SP-0x0001)
> ;
> ; 16: }
> 0x0000000D 0x9EFE lea (SP-0x0002)
> 0x0000000E 0xEDD8 rts > Thanks for any help.
>
> Terry Litinas
> Project Engineer
> ITW Balance Engineering
> 1731 Thorncroft
> Troy, Mi. 48084
> tlitinas@i...
> Ph: (248)643-2876
> Fx: (248)643-2888


Terry,

You should use the intrinsic functions that are packaged with the
CodeWarrior for DSP56800 R5.0.2 for this type of purpose. This isn't
a compiler bug because the Frac16 type is actually a "short" as
defined by the compiler. Therefore, when you use the runtime
multiply (*), the compiler generates an integer multiplication
correctly (which employs the use of an ASR, see page 3-21 of the
DSP56800 Family Manual), but it's not what you want in this case.
This is discussed in Section 3.2 of the SDK DSP Function Library
documentation. Look at pages 3-4 through 3-6 for what I am talking
about. However, for what you are having problems understanding, I
recommend you read all of Section 3 in the DSP Function Library
documentation (specifically page 3-2) as it explains the CodeWarrior
types and how the SDK interfaces to those types. CodeWarrior has a
__fixed__ type but it is specific to the CodeWarrior implementation
and not as portable. Therefore, the SDK promotes the use of short
and long types and use of the CodeWarrior intrinsic functions which
impart fractional arithmetic on implied fractional values (symbol
which has been declared as an integer type but is to be calculated as
a fractional type) for portability.

Reading this part of the documentation will probably help you in
getting to the code that you will want. I have listed the best way
to code what you are trying to do below for your reference, hope this
helps!

void Test16x16Multiply (void)
{
Frac16 a,b;
Frac32 c;

a = FRAC16(.5);
b = FRAC16(.5);

c = _L_mult(a,b);

}

Regards,
John

--- In motoroladsp@y..., "Terry Litinas" <tlitinas@i...> wrote:
> Hello,
>
> I am working on a project with the DSP56F807, CodeWarrior 5.02, and
SDK 2.5
> and am fairly new to the DSP world. I have questions concerning
fractional
> and integer math for my application. When reading an 807 ADC
channel I am
> interpreting the value as a 16 bit fractional value (Frac16) which
gives me
> a "percent full scale" reading which would be convenient to
multiply by full
> scale to generate a value in units of volts, degrees, etc. For
example if
> full scale for the input is 10V (before hardware attenuation) and
the ADC
> reading is 0.5, the input voltage is 0.5 x 10V = 5V. I don't see a
way to
> directly implement an equation like this due to the mixture of
integer and
> fractional values. Is there an efficient way to do this (preferably
in C) or
> should I go back to 16.16 - integer part in upper 16 bits and
fractional
> part in lower 16? I feel that I am missing something here.
>
> Also while experimenting, I ran across what may be a compiler bug.
When
> multiplying two Frac16 numbers and putting the result in a Frac32
variable I
> find that the result always seems to be 1/2 of the expected value.
The code
> below is an example. 0.5 x 0.5 = 0.125 instead of 0.25. The
compiler puts an
> asr instruction following the mpy that causes the problem. Has
anyone seen
> this? > ; 7: void Test16x16Multiply (void)
> ; 8: {
> ; 9: Frac16 a, b;
> ; 10: Frac32 c;
> ; 11:
> ;
> 0x00000000 FTest16x16Multiply:
> 0x00000000 0xCC02 movei #2,N
> 0x00000001 0xDE0F lea (SP)+N
> ;
> ; 12: a = FRAC16(.5);
> ;
> 0x00000002 0xA7B34000 moves #16384,X:0x0033
> ;
> ; 13: b = FRAC16(.5);
> ; 14:
> ;
> 0x00000004 0xA7B24000 moves #16384,X:0x0032
> ;
> ; 15: c = a * b;
> ;
> 0x00000006 0xB132 moves X:0x0032,Y0
> 0x00000007 0xB033 moves X:0x0033,X0
> 0x00000008 0x64C8 mpy +Y0,X0,B
> 0x00000009 0x7CB0 asr B
> 0x0000000A 0xD71F move B1,X:(SP)
> 0x0000000B 0xD1CBFFFF move B0,X:(SP-0x0001)
> ;
> ; 16: }
> 0x0000000D 0x9EFE lea (SP-0x0002)
> 0x0000000E 0xEDD8 rts > Thanks for any help.
>
> Terry Litinas
> Project Engineer
> ITW Balance Engineering
> 1731 Thorncroft
> Troy, Mi. 48084
> tlitinas@i...
> Ph: (248)643-2876
> Fx: (248)643-2888


One of our engineers put together the attached MSWord document that allowed him to better understand the concept of fractional math.  It exposes the behaviour of the intrinsic and SDK functions that are supplied with the CW 5.0.2 and SDK 2.5 Software.  It includes on the end, the sample code used to build the information in the tables.
 
I would encourage you to examine the concepts in the document, and if we have a misunderstanding of the concepts please let me know!!  While this document primarily exposes the usage of the routines using integer variables (Word32, Word16) and not the Frac32 and Frac16 representation, they are both defined in port.h to be equivalent to long and short respectively.
 
Hope this is of help.
 
Jerry
 
 
-----Original Message-----
From: Terry Litinas [mailto:t...@itwbe.com]
Sent: Friday, December 06, 2002 7:33 AM
To: m...@yahoogroups.com
Subject: [motoroladsp] Fractional Math

Hello,

I am working on a project with the DSP56F807, CodeWarrior 5.02, and SDK 2.5
and am fairly new to the DSP world. I have questions concerning fractional
and integer math for my application. When reading an 807 ADC channel I am
interpreting the value as a 16 bit fractional value (Frac16) which gives me
a "percent full scale" reading which would be convenient to multiply by full
scale to generate a value in units of volts, degrees, etc. For example if
full scale for the input is 10V (before hardware attenuation) and the ADC
reading is 0.5, the input voltage is 0.5 x 10V = 5V. I don't see a way to
directly implement an equation like this due to the mixture of integer and
fractional values. Is there an efficient way to do this (preferably in C) or
should I go back to 16.16 - integer part in upper 16 bits and fractional
part in lower 16? I feel that I am missing something here.

Also while experimenting, I ran across what may be a compiler bug. When
multiplying two Frac16 numbers and putting the result in a Frac32 variable I
find that the result always seems to be 1/2 of the expected value. The code
below is an example. 0.5 x 0.5 = 0.125 instead of 0.25. The compiler puts an
asr instruction following the mpy that causes the problem. Has anyone seen
this?;    7: void Test16x16Multiply (void)
;    8: {
;    9:       Frac16 a, b;
;   10:       Frac32 c;
;   11:
;
0x00000000                  FTest16x16Multiply:
0x00000000  0xCC02                 movei    #2,N
0x00000001  0xDE0F                 lea      (SP)+N
;
;   12:       a = FRAC16(.5);
;
0x00000002  0xA7B34000             moves    #16384,X:0x0033
;
;   13:       b = FRAC16(.5);
;   14:
;
0x00000004  0xA7B24000             moves    #16384,X:0x0032
;
;   15:       c = a * b;
;
0x00000006  0xB132                 moves    X:0x0032,Y0
0x00000007  0xB033                 moves    X:0x0033,X0
0x00000008  0x64C8                 mpy      +Y0,X0,B
0x00000009  0x7CB0                 asr      B
0x0000000A  0xD71F                 move     B1,X:(SP)
0x0000000B  0xD1CBFFFF             move     B0,X:(SP-0x0001)
;
;   16: }
0x0000000D  0x9EFE                 lea      (SP-0x0002)
0x0000000E  0xEDD8                 rtsThanks for any help.

Terry Litinas
Project Engineer
ITW Balance Engineering
1731 Thorncroft
Troy, Mi. 48084
t...@itwbe.com
Ph: (248)643-2876
Fx: (248)643-2888



_____________________________________
Note: If you do a simple "reply" with your email client, only the author of this message will receive your answer.  You need to do a "reply all" if you want your answer to be distributed to the entire group.

_____________________________________
About this discussion group:

To Join:  m...@yahoogroups.com

To Post:  m...@yahoogroups.com

To Leave: m...@yahoogroups.com

Archives: http://www.yahoogroups.com/group/motoroladsp

More Groups: http://www.dsprelated.com/groups.php3


">Yahoo! Terms of Service.

________________________________________________________________________
This email has been scanned for all viruses by the MessageLabs SkyScan
service. For more information on a proactive anti-virus service working
around the clock, around the globe, visit http://www.messagelabs.com
________________________________________________________________________


Attachment (not stored)
fracmath.doc
Type: application/msword