

         /***********************************************\

         |**                                           **|

         |**   DSP56200 CHIP DRIVER -ADAPTIVE FILTER   **|

         |**                        -POLLED I/O        **|

         |**                                           **|

         \***********************************************/







/************************************************************************\

*                                                                        *

*   This is an example of a program located in a host processor, used    *

*   to setup and service the DSP56200 as a real-time adaptive filter.    *

*   In this example, the host processor polls a general purpose input    *

*   pin to determine the beginning of a new sample period, signified     *

*   by the reception of a rising edge on the DSP56200's START pin. The   *

*   general purpose input pin is tied directly to the START pin of the   *

*   DSP56200.                                                            *

*                                                                        *

*   This program, written in the language "C", is provided only as an    *

*   example, and will be much faster if translated by the user into the  *

*   assembly language of the host processor.                             *

*                                                                        *

*                                                                        *

*   The example system is configured as shown below:                     *

*                                                                        *

*                                                                        *

*                               ------------                             *

*                               | DSP56200 |                             *

*                               ------------                             *

*                                     ^                                  *

*                                     |                                  *

*                                     v                                  *

*                  -------    ------------------                         *

*          d(t) -->| A/D |--->| Host Processor |                         *

*                  -------    |                |    -------              *

*                             | (contains code |--->| D/A |--> out(t)    *

*                  -------    |  found in this |    -------              *

*         x1(t) -->| A/D |--->|     file)      |                         *

*                  -------    ------------------                         *

*                                                                        *

*                                                                        *

*                    Figure 1. Adaptive Filtering System                 *

*                                                                        *

*                                                                        *

*                                                                        *

*   There is only one DSP56200 in this example (i.e., not multiple       *

*   DSP56200s in cascade), and it is configured as an adaptive filter    *

*   (see Figure 2) by writing the DSP56200's Configuration register.     *

*   Since only 16 bits of the result  are sent to the D/A Converter,     *

*   the output is rounded to a 16 bit result by the DSP56200.            * 

*                                                                        *

*                                                                        *

*                                                                        *

*                                                                        *

*         d(n) -------------------------------                           *

*                                          - |                           *

*                                            v                           *

*                    --------------     +   ---                          *

*        x1(n) ----->|    FIR     |------->| + |-----> out(n)            *

*                    |  Structure |         ---           = -1 * error   *

*                    --------------          |                           *

*                          ^                 |                           *

*                          |                 |                           *

*                          -------------------                           *

*                                                                        *

*                                                                        *

*                   Figure 2. DSP56200 Configuration                     *

*                                                                        *

*                                                                        *

*                                                                        *

*      ************************************************************      *

*      *                                                          *      *

*      *   This program originally available on the Motorola DSP  *      *

*      *   bulletin board.  It is provided under a DISCLAMER OF   *      *

*      *   WARRANTY available from  Motorola DSP Operation,       *      *

*      *     6501 Wm. Cannon Drive W., Austin, Tx., 78735.        *      *

*      *                                                          *      *

*      ************************************************************      *

*                                                                        *

*                                                                        *

*                                                                        *

*                                                                        *

*      ************************************************************      *

*      * Note on the Representation of Hex Numbers:               *      *

*      *                                                          *      *

*      *    In the programming language  "C",  hex numbers are    *      *

*      *    represented by preceding the number with "0x". For    *      *

*      *    example, e4 (hex) is represented in "C" as 0xe4.      *      *

*      *                                                          *      *

*      ************************************************************      *

*                                                                        *

\************************************************************************/







        /*** CONSTANTS ***/



#define   FOREVER     1         /* For infinite looping */







#define   X1_HI     0x0         /* Addresses (hex) of DSP56200 regs, bank 0 */

#define   X1_LO     0x1

#define   D_HI      0x2

#define   D_LO      0x3

#define   K_HI      0x4

#define   K_LO      0x5

#define   X2_HI     0x6                     /* unused -Dual FIR mode only */

#define   X2_LO     0x7                     /* unused -Dual FIR mode only */

#define   DATA_HI   0x8                     /* unused */

#define   DATA_LO   0x9                     /* unused */

#define   COEFF_HI  0xa

#define   COEFF_MD  0xb

#define   COEFF_LO  0xc

#define   RAM_ADR   0xd

#define   CONFIG    0xf



#define   OUTPUT3   0x0               /* Most  significant byte of result */

#define   OUTPUT2   0x1

#define   OUTPUT1   0x2               /* Two least significant bytes are  */

#define   OUTPUT0   0x3               /* unused since rounded to 16 bits */

#define   LTAP1_HI  0x4                     /* unused */

#define   LTAP1_LO  0x5                     /* unused */

#define   LTAP2_HI  0x6                     /* unused */

#define   LTAP2_LO  0x7                     /* unused */



#define   LEAKAGE   0x0         /* Addresses (hex) of DSP56200 regs, bank 1 */

#define   FTL       0x1







#define   LKG_VAL   0x00        /* Values (hex) written to the DSP56200 regs */

#define   FTL_VAL   0xff              /* 256 taps */

#define   DCONFIG_0 0x98              /* Updates disabled, Selects bank 0   */

#define   DCONFIG_1 0x99              /* Updates disabled, Selects bank 1   */

#define   ECONFIG_0 0x90              /* Updates enabled,  Selects bank 0   */

#define   KVAL_HI   0x04

#define   KVAL_LO   0x00              /* It may be desirable to make the K 

                                         register a variable so it can be 

                                         updated every sample period.   */







        /*** MAIN PROGRAM ***/



main()   {



        /********************************************************************\

        *                                                                    *

        *   This program is an example of the software used by a host        *

        *   processor to service a DSP56200 configured as an adaptive        *

        *   filter.  Three functions are performed:                          *

        *                                                                    *

        *         1. Initialize User's System and Configure the DSP56200.    *

        *         2. Zero the Coeff and Data RAMs of the DSP56200.           *

        *         3. Run the Adaptive Filter in a real-time environment.     *

        *                                                                    *

        *   Things to watch for when setting up an adaptive filter system:   *

        *                                                                    *

        *         - There must be NO GLITCHES on the DSP56200's START pin.   *

        *         - The SEI pin must be directly wired to the SSO pin.       *

        *         - The value of the K register must not be too large.       *

        *         - If codecs are used for the A/D or D/A conversion, see    *

        *              comments in the routines "send_da()"and "get_ad()".   *

        *         - If offset binary A/Ds or D/As are used, see comments     *

        *              in the subroutines "send_da()" and "get_ad()".        *

        *                                                                    *

        *   Note: The program assumes that the variable type "int" is at     *

        *         least 16 bits wide.                                        *

        *                                                                    *

        \********************************************************************/







        /* Program Declarations */



           int tap;                        /* filter tap number */







        /* Initialize System */



           /*  Here the user first initializes any other components of the  */

           /*  adaptive filtering system which require initialization. The  */

           /*  DSP56200 is then initialized using the program code below.   */







        /* Reset and Configure the DSP56200 */



           wait_for_start();               /* This is done to synchronize   */

                                           /* the program up to the system. */

                                           /* Ensures that no writes occur  */

                                           /* when the DSP56200's START pin */

                                           /* receives a rising edge.       */



           wrbyte(DCONFIG_1, CONFIG);      /* Configuration:                */

                                           /*    - Single Adaptive Filter   */

                                           /*    - Not Cascaded             */

                                           /*    - 16 Bit Rounding          */

                                           /*    - Coeff Update Disabled    */

                                           /*    - DC Tap Disabled          */

                                           /*    - Leakage Disabled         */

                                           /*    - Register Bank 1 Selected */

           wrbyte(FTL_VAL, FTL);           /* Writing this reg also resets   */

                                           /*    the chip at the beginning   */

                                           /*    of the next sample period,  */

                                           /*    which destroys any previous */

                                           /*    contents of the Data RAM.   */

           wrbyte(LKG_VAL, LEAKAGE);



           wrbyte(DCONFIG_0, CONFIG);      /* Switch to register bank 0 */



           wrbyte(KVAL_HI, K_HI);

           wrbyte(KVAL_LO, K_LO);



           /* Presently for initialization, there are fourteen writes */

           /* which the host processor must  perform in one sample    */

           /* period.  If all these writes cannot be performed in one */

           /* sample period, a call to the routine "wait_for_start()" */

           /* can be inserted here,  and will reduce the number of    */

           /* writes down to a maximum of eight in one sample period. */









        /* Initialize the DSP56200's Coefficient and Data RAMS */



              wrbyte(0, X1_HI);

              wrbyte(0, X1_LO);



              wrbyte(0, D_HI);

              wrbyte(0, D_LO);



              wrbyte(0, COEFF_HI);      /* Coeff_RAM[0] = 0 */

              wrbyte(0, COEFF_MD);

              wrbyte(0, COEFF_LO);



              wrbyte(0, RAM_ADR);       /* autoincrements w/ each START */



              wait_for_start();



              for (tap=1; tap<=FTL_VAL; tap=tap+1)   {



                 wrbyte(0, COEFF_HI);      /* Coeff_RAM[tap] = 0 */

                 wrbyte(0, COEFF_MD);

                 wrbyte(0, COEFF_LO);

                                       /*  Note that the Data RAM is also   */

                                       /*  cleared since the DSP56200's X1  */

                                       /*  reg is set to "0", resulting in  */

                                       /*  "0"s being "shifted" into the    */

                                       /*  filter's Data RAM (delay line)   */

                                       /*  every sample period.             */



                 wait_for_start();

              }







        /* Enable Coefficient Updates   -toggles bit 3 to a "0" */



           wrbyte(ECONFIG_0, CONFIG);







        /* Run the Adaptive Filter in Real-time */



              prealtime();

}







        /*** SUBROUTINES ***/







        /* PREALTIME */



prealtime()

{

        /****************************************************************\

        *                                                                *

        *   This routine performs the I/O servicing required when the    *

        *   DSP56200 is processing real-time samples.  Every sample      *

        *   period (signified by the reception of a rising edge on the   *

        *   DSP56200's START pin), the host processor sends two new      *

        *   samples to the DSP56200, and reads out a result from the     *

        *   DSP56200.                                                    *

        *                                                                *

        *   This routine is used only in polled I/O systems.             *

        *                                                                *

        *   Note: The routine assumes that the variable type "int" is    *

        *         at least 16 bits wide.                                 *

        *                                                                *

        *   Also: The DSP56200 outputs "-1 * error".  If the correct     *

        *         sign for the error term is required, then the host     *

        *         processor must perform a 2's complement operation      *

        *         on the 16 bit value read from the DSP56200's OUTPUT    *

        *         register (bytes 3 and 2).                              *

        *                                                                *

        *   Also: It is important that execution of the code inside the  *

        *         while loop completes before the next sample period     *

        *         begins.  This guarantees that the start of the next    *

        *         sample period is never missed because the program will *

        *         then be in the subroutine "wait_for_start()", polling  *

        *         for the rising edge of the START signal.               *

        *                                                                *

        \****************************************************************/







        /* Subroutine Declarations */

           int x1, d, out;                        /* see Figure 2 */







        while (FOREVER)   {                       /* infinite loop */



           /* Poll for Reception of the START signal */

              wait_for_start();



           /* Host Now Services the DSP56200 Since START Has Been Received */

           

              /* Read New Samples from the A/Ds and Write to the DSP56200 */



                 x1 = get_ad(1);

                 d  = get_ad(2);



                 wrbyte((x1>>8)  0x0ff, X1_HI);      /* writes upper byte */

                 wrbyte( x1      0x0ff, X1_LO);      /* writes lower byte */

                 wrbyte((d>>8)   0x0ff, D_HI);       /* writes upper byte */

                 wrbyte( d       0x0ff, D_LO);       /* writes lower byte */



              /* Read Error Term from the 56200 and Write to the D/A */

   

                 out = rdbyte(OUTPUT3);

                 out = out << 8;                      /* move to upper byte */

                 out = out + (0x0ff  rdbyte(OUTPUT2));



                 send_da(out);

        }

}







        /* WRBYTE */



wrbyte(val,adr)

int val, adr;

{

        /**************************************************************\

        *                                                              *

        *   This subroutine writes one byte to the DSP56200 register   *

        *   specified by "adr".                                        *

        *   Note that the correct register bank has already been       *

        *   selected (defined by the LSB of the Configuration reg).    *

        *                                                              *

        *   This subroutine could be defined as a macro for faster     *

        *   execution.                                                 *

        *                                                              *

        *   Inputs:                                                    *

        *      val  = bytewide value to be written to the DSP56200     *

        *      adr  = address of the DSP56200 register to be written   *

        *                                                              *

        \**************************************************************/



        /* Actual program code depends on the user's system. */

}







        /* RDBYTE */



rdbyte(adr)

int adr;

{

        /**************************************************************\

        *                                                              *

        *  This subroutine reads one byte from the DSP56200 register   *

        *  specified by "adr".                                         *

        *  Note that the correct register bank has already been        *

        *  selected (defined by the LSB of the Configuration reg).     *

        *                                                              *

        *  This subroutine could be defined as a macro for faster      *

        *   execution.                                                 *

        *                                                              *

        *   Inputs:                                                    *

        *      adr  = address of the DSP56200 register to be read      *

        *                                                              *

        *   Outputs:                                                   *

        *      The routine returns the byte read from the DSP56200     *

        *                                                              *

        \**************************************************************/



        int valread;



        /* Actual program code depends on the user's system. */



        return(valread);

}







        /* GET_AD */



get_ad(devnum)

int devnum;

{

        /******************************************************************\

        *                                                                  *

        *   This subroutine returns a 16 bit value read from one of the    *

        *   two A/D converters in the filtering system.                    *

        *                                                                  *

        *   Inputs:                                                        *

        *      devnum = A/D Converter number:  1 = x1 input, 2 = d input.  *

        *                                                                  *

        *   Outputs:                                                       *

        *      The routine returns the value read from the selected A/D.   *

        *                                                                  *

        \******************************************************************/



        int ad_val;



        /* Actual program code depends on the user's system. */



        /*  If a codec is used for A/D conversion, the 8 bit companded  */

        /*  sample must be converted into a 12 bit linear quantity and  */

        /*  then sign extended to 16 bits.                              */



        /*  If the converter uses an offset binary format, it may be  */

        /*  necessary to invert the sign bit (and any sign extension  */

        /*  bits) to obtain a 2's complement number.                  */



        return(ad_val);

}







        /* SEND_DA */



send_da(val)

int val;

{

        /**************************************************************\

        *                                                              *

        *   This subroutine sends a value to a D/A converter where it  *

        *   gets converted to an analog signal.                        *

        *                                                              *

        *   Inputs:                                                    *

        *      val = value to be sent to the D/A converter             *

        *                                                              *

        \**************************************************************/



        /* Actual program code depends on the user's system. */



        /*  If a codec is used for D/A conversion, the 16 bit linear   */

        /*  sample must be converted into a 8 bit companded quantity.  */



        /*  If the converter uses an offset binary format, it may be  */

        /*  necessary to invert the sign bit (and any sign extension  */

        /*  bits) to obtain a number in offset binary format.         */

}







        /* WAIT_FOR_START */



wait_for_start()

{

        /********************************************************************\

        *                                                                    *

        *   This routine polls a general purpose input pin for a "1",        *

        *   which indicates that a rising edge has arrived at the START pin  *

        *   of the DSP56200 and that new samples are ready to be processed.  *

        *                                                                    *

        *   Note: It may be necessary to verify that the START signal has    *

        *         returned to a "0" before polling for a "1".                *

        *                                                                    *

        *   Note: It is important that the program has completed other       *

        *         processing and is waiting in this loop when the START      *

        *         signal arrives so that no samples are lost.                *

        *                                                                    *

        \********************************************************************/



        int pin;



        pin = get_pin();



        while (pin == 0);                /* loops until "1" found on pin */

           pin = get_pin();

}







        /* GET_PIN */



get_pin()

{

        /*****************************************************************\

        *                                                                 *

        *   Returns the value read (0 or 1) from a general purpose input  *

        *   pin which is tied directly to the DSP56200's START pin.       *

        *                                                                 *

        \*****************************************************************/

        

        /* Actual program code depends on the user's system. */

}

