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 |
|
Fractional Math
Started by ●December 6, 2002
Reply by ●December 6, 20022002-12-06
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 |
Reply by ●December 6, 20022002-12-06
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 |
Reply by ●December 6, 20022002-12-06
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
| |||
|