a Basic trigonometric subroutines for the ADMC331 AN331-10 a Basic trigonometric subroutines for the ADMC331 AN331-10 © Analog Devices Inc., January 2000 Page 1 of 11 a Basic trigonometric subroutines for the ADMC331 AN331-10 Table of Contents SUMMARY...................................................................................................................... 3 1 THE TRIGONOMETRIC LIBRARY ROUTINES....................................................... 3 1.1 Using the Trigonometric Routines ................................................................................................................3 1.2 Formats of inputs and outputs.......................................................................................................................3 1.3 Implemented algorithms ................................................................................................................................4 1.4 Usage of the DSP registers .............................................................................................................................4 1.5 The program code...........................................................................................................................................4 1.6 Access to the library: the header file.............................................................................................................6 2 SOFTWARE EXAMPLE: GENERATION OF THREE-PHASE SINE-WAVES......... 7 2.1 The main program: main.dsp........................................................................................................................7 2.2 The main include file: main.h ........................................................................................................................8 2.3 Example output...............................................................................................................................................9 3 PRECISION OF THE ROUTINES ............................................................................ 9 3.1 Sine and Cosine functions ..............................................................................................................................9 3.2 Arctangent function......................................................................................................................................10 4 DIFFERENCES BETWEEN LIBRARY AND ADMC331 “ROM-UTILITIES” ......... 11 © Analog Devices Inc., January 2000 Page 2 of 11 AN331-10 a Basic trigonometric subroutines for the ADMC331 Summary This application note illustrates the usage of some basic trigonometric subroutines such as sine and cosine. They are implemented in a library-like module for easy access. The realisation follows the one described in chapter 4 of the DSP applications handbook1. Then, a software example will be described that may be downloaded from the accompanying zipped files. Finally, some data will be shown concerning the accuracy of the algorithms. 1 The Trigonometric Library Routines 1.1 Using the Trigonometric Routines The routines are developed as an easy-to-use library, which has to be linked to the user’s application. The library consists of two files. The file “trigono.dsp” contains the assembly code for the subroutines. This package has to be compiled and can then be linked to an application. The user simply has to include the header file “trigono.h”, which provides function-like calls to the routines. The following table summarises the set of macros that are defined in this library. Note that every trigonometric function stores the result in the ar register. Operation Usage Operands Initialisation Set_DAG_registers_for_trigonometric; none Sine Sin(angle); angle = dreg2 or constant Cosine Cos(angle); angle = dreg3 or constant Arctangent Atan(integer_part, fractional_part); integer_part = dreg4 or constant fractional_part = dreg5 or constant Table 1: Implemented routines The routines do not require any configuration constants from the main include-file “main.h” that comes with every application note. For more information about the general structure of the application notes and including libraries into user applications refer to the Library Documentation File. Section 2 shows an example of usage of this library. In the following sections each routine is explained in detail with the relevant segments of code which is found in either “trigono.h” or “trigono.dsp”. For more information see the comments in those files. 1.2 Formats of inputs and outputs The implementation of the routines is such that values for angles are expected to be in the usual scaled 1.15 format. Therefore, +1 (0x7FFF) corresponds to +π radians or 180 degrees, and –1 (0x8000) to -π radians or -180 degrees. The sine and cosine functions use this format for their input. Since the output of these functions is limited to the range [-1, 1], the scaled 1.15 format is the natural choice for it. 1 a ”Digital Signal Applications using the ADSP-2100 Family”, Volume 1, Prentice Hall, 1992 2 Any data register of the ADSP-2171 core 3 Any data register of the ADSP-2171 core 4 Any data register of the ADSP-2171 core except mr0 5 Any data register of the ADSP-2171 core except mr1 © Analog Devices Inc., January 2000 Page 3 of 11 AN331-10 a Basic trigonometric subroutines for the ADMC331 The arctan function requires a different format. Since its argument may sweep from –∞ to +∞, the scaling is no longer feasible. The argument is represented by a (signed) 32-bit value in the 16.16 format. The overall range is therefore from –32768 (0x8000.0000) to +32768-2-16 (0x7FFF.FFFF). The output value is an angle in the range from -½π to +½π, corresponding in the above-defined 1.15 format to –0.5 to +0.5. 1.3 Implemented algorithms The calculation is achieved through approximation of the functions by means of a fifth order Taylor series expansion. The equations that are used are reported hereafter: α ∈ [0,1[ sin (α ) = 3.140625α + 0.02026367α 2 − 5.325196α 3 + 0.5446778α 4 + 1.800293α 5 arctan(x ) = 0.318253 x + 0.003314 x − 0.130908 x + 0.068542 x − 0.009159 x 2 3 4 x ∈ [- 1,1] 5 st The approximation for the sine function is accurate for any angle in the 1 quadrant. Values in the other quadrants are reported the 1st quadrant for the known symmetries of the functions. The cosine is calculated with the same approximation since cos(α ) = sin (π2 − α ) . The arctangent is valid for any argument of absolute value less or equal than 1. For arguments outside this interval, the following property is used: ( ) arctan(x ) = 12 − arctan x −1 . Refer to the above-mentioned DSP applications handbook for more details. 1.4 Usage of the DSP registers The following table gives an overview of the registers that are used by the functions. It may be noted that the DAG registers M5 and L5 must be set to 1 and 0 respectively and that they are not modified by the trigonometric routines. The already mentioned call to Set_DAG_registers_for_trigonometric prepares these registers for the trigonometric functions. It now becomes clear that this routine is necessary only once if M5 and/or L5 are not modified in another part of the user’s code, as shown in the example in section 3. Subroutine Input Output Modified registers ay0, ay1, af, ar, Sin_ ax0 ar mx1, my1, mf, mr, sr, I5 ay0, ay1, af, ar, Cos_ ax0 ar mx1, my1, mf, mr, sr, I5 ax0, ax1, ay0, ay1, af, ar, Atan_ mr1, mr0 ar mx1, my0, my1, mf, mr, sr, si, I5 Other registers M5 = 1, L5 = 0 M5 = 1, L5 = 0 M5 = 1, L5 = 0 Table 2: Usage of DSP core registers 1.5 The program code The following code defines the three routines Sine, Cosine and Arctangent. © Analog Devices Inc., January 2000 Page 4 of 11 a Basic trigonometric subroutines for the ADMC331 AN331-10 The functions are declared as globally accessible to other applications. The code is almost identical to the one described in the handbook. Both the Sine and Cosine routine make use of the core sine approximation that is documented in the handbook. The coefficients have been moved into program memory instead of data memory (which implies the use of I5 instead of I3). Therefore, the initial part of these routines simply modifies the argument in order to lie within the 1st quadrant where the adopted approximation by Taylor series is valid. The final result is then obtained by making use of the well known symmetries of these functions and the relation cos(α)=sin(½π-α). {*************************************************************************************** * Routines Defined in this Module * ***************************************************************************************} .ENTRY .ENTRY .ENTRY Sin_; Cos_; Atan_; {*************************************************************************************** * Local Variables Defined in this Module * ***************************************************************************************} .VAR/PM/RAM/SEG=USER_PM1 SIN_COEFF[5]; .INIT SIN_COEFF : 0x324000, 0x005300, 0xAACC00, 0x08B700, 0x1CCE00; .VAR/PM/RAM/SEG=USER_PM1 ATN_COEFF[5]; .INIT ATN_COEFF : 0x28BD00, 0x006D00, 0xEF3E00, 0x08C600, 0xFED400; Cos_: Sin_: ar=abs ax0; ay0=0x4000; ay1=0x7fff; ar=ay0-ar; ay0=ar; ar=abs ar; jump sin_approx; { { { { { { { abs(x)} pi/2 = 0.5 } pi = 1.0 } pi/2 - |x|} store sign of result in ay0} abs value for approx } skip to Taylor series } ay0=0x4000; ay1=0x7fff; ar=ax0 and ay1; af=ay0-ar; if LT ar=ay1-ar; ay0=ax0; { { { { { { pi/2 } pi = 1 } take |x| } pi/2 - |x| check for LHS angle} if x > pi/2 x = pi -x } store sign of result in ay0} sin_approx: I5=^sin_coeff; {Pointer to coeff. buffer} my1=ar; {Coeffs in 4.12 format} mf=ar*my1 (rnd), mx1=pm(i5,m5); {mf = x**2} mr=mx1*my1 (ss), mx1=pm(i5,m5); {mr = c1*x} cntr=3; do approx1 until ce; mr=mr+mx1*mf (SS); {Do summation } approx1: mf=ar*mf (RND), mx1=PM(I5,M5); mr=mr+mx1*mf (SS); sr=ASHIFT mr1 by 3 (HI); sr=sr or LSHIFT mr0 by 3 (LO); {Convert to 1.15 format} ar=pass sr1; if LT ar=pass ay1; {Saturate if needed} af=pass ay0; if LT ar=-ar; {Negate output if needed} rts; Atan_: I5 = ^ATN_COEFF; ay0=0; ax1=mr1; ar=pass mr1; if GE jump posi; ar=-mr0; © Analog Devices Inc., January 2000 {point to coefficients} {Check for positive input} {Make negative number positive} Page 5 of 11 a Basic trigonometric subroutines for the ADMC331 AN331-10 mr0=ar; ar=ay0-mr1+c-1; mr1=ar; posi: sr=LSHIFT mr0 by -1 (LO); {Produce 1.15 value in SR0} ar=sr0; ay1=mr1; af=pass mr1; if EQ jump noinv; {If input < 1, no need to invert} se=exp mr1 (HI); {Invert input} sr=norm mr1 (HI); sr=sr or NORM mr0 (LO); ax0=sr1; si=0x0001; sr=NORM si (HI); ay1=sr1; ay0=sr0; divs ay1,ax0; divq ax0; divq ax0; divq ax0; divq ax0; divq ax0; divq ax0; divq ax0; divq ax0; divq ax0; divq ax0; divq ax0; divq ax0; divq ax0; divq ax0; divq ax0; ar=ay0; noinv: my0=ar; mf=ar*my0 (RND), my1=PM(I5,M5); mr=ar*my1 (SS), mx1=PM(I5,M5); cntr=3; do approx2 until CE; mr=mr+mx1*mf (SS), mx1=PM(I5,M5); approx2: mf=ar*mf (RND); mr=mr+mx1*mf (SS); ar=mr1; ay0=0x4000; af=pass ay1; if NE ar=ay0-mr1; af=pass ax1; if LT ar=-ar; rts; 1.6 Access to the library: the header file The library may be accessed by including the header file “trigono.h” in the application code. The header file is intended to provide function-like calls to the routines presented in the previous section. It defines the calls shown in Table 1. The file is self-explaining and needs no further comments. It is worth adding a few comments about efficiency of these routines. The first macro simply sets the DAG registers M5 and L5 to its correct values. The user may however just replace the macro with one of its instructions when the application code modifies just one of these registers. The sine and cosine subroutines expect the argument to be placed into ax0. This is what the macros do. However, if the angle is already stored in ax0, the user may just place an instruction call Sin_; instead of Sin(ax0) in order to avoid an additional instruction ax0 = ax0; in the expanded code. Similarly, a instruction Atan(mr1, mr0) should be avoided or replaced by the direct call to the subroutine Atan_. .MACRO Set_DAG_registers_for_trigonometric; M5 = 1; L5 = 0; .ENDMACRO; .MACRO Sin(%0); ax0 = %0; call Sin_; .ENDMACRO; .MACRO Cos(%0); ax0 = %0; call Cos_; © Analog Devices Inc., January 2000 Page 6 of 11 AN331-10 a Basic trigonometric subroutines for the ADMC331 .ENDMACRO; .MACRO Atan(%0, %1); mr1= %0; mr0= %1; call Atan_; .ENDMACRO; 2 Software Example: Testing the Trigonometric Functions 2.1 The main program: main.dsp The example demonstrates how to use the routines. All it does is to cycle through the whole range of definition of the sine function and converting the results by means of the digital to analog converter. The application has been adapted from two previous notes6,7. This section will only explain the few and intuitive modifications to those applications. The file “main.dsp” contains the initialisation and PWM Sync and Trip interrupt service routines. To activate, build the executable file using the attached build.bat either within your DOS prompt or clicking on it from Windows Explorer. This will create the object files and the main.exe example file. This file may be run on the Motion Control Debugger. In the following, a brief description of the additional code (put in evidence by bold characters) is given. Start of code – declaring start location in program memory .MODULE/RAM/SEG=USER_PM1/ABS=0x30 Main_Program; Next, the general systems constants and PWM configuration constants (main.h – see the next section) are included. Also included are the PWM library, the DAC interface library and the trigonometric library. {*************************************************************************************** * Include General System Parameters and Libraries * ***************************************************************************************} #include <main.h>; #include <pwm331.h>; #include <dac331.h>; #include <trigono.h>; The argument variable Theta is defined hereafter. {*************************************************************************************** * Local Variables Defined in this Module * ***************************************************************************************} .VAR/DM/RAM/SEG=USER_DM Theta; .INIT Theta : 0x0000; { Current angle } First, the PWM block is set up to generate interrupts every 100µs (see “main.h” in the next Section). The variable Theta, which stores the argument of the trigonometric functions, is set to zero. Before using the trigonometric functions, it is necessary to initialise certain registers of the data-address-generator (DAG) of the DSP core. This will be discussed in more detail in the next section. However, note that this is done only once in this example. If those registers are modified in other parts of the user’s code, then it must be repeated before a call to a trigonometric function. The main loop just waits for interrupts.. {********************************************************************************************} 6 AN331-03: Three-Phase Sine-Wave Generation using the PWM Unit of the ADMC331 7 AN331-06: Using the Serial Digital to Analog Converter of the ADMC Connector Board © Analog Devices Inc., January 2000 Page 7 of 11 AN331-10 a Basic trigonometric subroutines for the ADMC331 { Start of program code } {********************************************************************************************} Startup: PWM_Init(PWMSYNC_ISR, PWMTRIP_ISR); DAC_Init; IFC = 0x80; ay0 = 0x200; ar = IMASK; ar = ar or ay0; IMASK = ar; { Clear any pending IRQ2 inter. { unmask irq2 interrupts. } } { IRQ2 ints fully enabled here } ar = pass 0; DM(Theta)= ar; Set_DAG_registers_for_trigonometric; Main: jump Main; { Wait for interrupt to occur } rts; The interrupt service routine simply shows how to make use of the trigonometric routines. It invokes the three routines (the integer part of the Atan_ function is set to zero – it is intended to illustrate the possibility of constant arguments). The result of Sin, Cos and Atan (in register ar) are stored in channels 1, 2 and 3 respectively and send to the DAC (refer to the above mentioned application note AN331-6 for details). Then Theta is incremented, so that the whole range of definition of the sine functions is swept. Refer to Section 1.2 for the used formats of inputs and outputs. After 65536 interrupts (corresponding to approx. 6.55s) the whole period is completed. Since only the fractional part of the arctan argument is used, this function will generate the output from 0 to π/4 (hexadecimal 0x2000). {********************************************************************************************} { PWM Interrupt Service Routine } {********************************************************************************************} PWMSYNC_ISR: ax0 = dm(Theta); Sin(ax0); DAC_Put(1, ar); Cos(ax0); DAC_Put(2, ar); Atan(0, ax0); DAC_Put(3, ar); DAC_Update; ax1= DM(Theta); ar= ax1 +1; DM(Theta)= ar; rti; 2.2 The main include file: main.h This file contains the definitions of ADMC331 constants, general purpose macros and the configuration parameters of the system and library routines. It should be included in every application. For more information refer to the Library Documentation File. This file is mostly self-explaining. As already mentioned, the trigonometric library does not require any configuration parameters. The following defines the parameters for the PWM ISR used in this example. {********************************************************************************************} { Library: PWM block } { file : PWM331.dsp } { Application Note: Usage of the ADMC331 Pulse Width Modulation Block } .CONST PWM_freq = 10000; {Desired PWM switching frequency [Hz] } .CONST PWM_deadtime = 1000; {Desired deadtime [nsec] } .CONST PWM_minpulse = 1000; {Desired minimal pulse time [nsec] } .CONST PWM_syncpulse = 1540; {Desired sync pulse time [nsec] } {********************************************************************************************} © Analog Devices Inc., January 2000 Page 8 of 11 a Basic trigonometric subroutines for the ADMC331 2.3 AN331-10 Example output The signals that are generated by this demonstration program is shown in the following figure. Note that the use of only the fractional part for the arctan function limits it’s output to the range of 0 to 0.25 (corresponding to ¼π = arctan(1)). Refer to section 1.2 for details on the format of inputs and outputs. Figure 1 Produced output of the example program. The waveforms represent the signals on the DAC outputs 1 (sine), 2 (cosine) and 3 (arctangent). 3 Precision of the routines 3.1 Sine and Cosine functions The following figure plots the obtained error of the implemented sine function (16 bit fixed point arithmetic) versus the result of floating point calculations. The graph is limited to the 1st quadrant for the usual symmetry properties and may obviously be extended to the cosine function as well. Its maximum is found to be of approx. 0.016%, resulting in a precision of 12.7 bits for the sine and cosine functions. © Analog Devices Inc., January 2000 Page 9 of 11 a Basic trigonometric subroutines for the ADMC331 AN331-10 π). The x-axis is scaled to 1.15 format. Figure 2 Error of sine function in the 1st quadrant (0 to ½π 3.2 Arctangent function The following figures plot the obtained error of the implemented arctangent function (16 bit fixed point arithmetic) versus the result of floating point calculations. The analysis has been split into the two cases of the argument laying in the range of 0 to 1 (increments of 2-14 - Figure 3) and in the range from 1 to 2048 (steps of 0.5 - Figure 4). The maximum error is found to be of approx. 0.0059%, resulting in a precision of 14 bits for the arctangent function. The result may obviously be extended to negative values for the usual symmetry properties. Figure 3 Error of arctangent function in the range of 0 to 1. The y-axis is scaled to 1.15 format. © Analog Devices Inc., January 2000 Page 10 of 11 AN331-10 a Basic trigonometric subroutines for the ADMC331 Figure 4 Error of arctangent function in the range of 1 to 2048. The y-axis is scaled to 1.15 format. 4 Differences between library and ADMC331 “ROM-Utilities” The main purpose of this application note is to document, to analyse and to standardise the trigonometric functions on this part. The routines presented herein do not differ from the ones present in the ROM of the ADMC331, except for the atan_ routine, which now uses I5, M5 and L5 instead of I4, M4 and L4. This choice has been made in order to use the same pointers for all of the trigonometric functions. However, the ones present in the ROM may still be used. © Analog Devices Inc., January 2000 Page 11 of 11