- Main Page
- Modules
- Data Structures
- Files
- Examples

- File List
- Globals

# arm_lms_q15.c

Go to the documentation of this file.

    00001 /* ----------------------------------------------------------------------
    00002 * Copyright (C) 2010 ARM Limited. All rights reserved.
    00003 *
    00004 * $Date:        29. November 2010
    00005 * $Revision:    V1.0.3
    00006 *
    00007 * Project:      CMSIS DSP Library
    00008 * Title:        arm_lms_q15.c
    00009 *
    00010 * Description:  Processing function for the Q15 LMS filter.
    00011 *
    00012 * Target Processor: Cortex-M4/Cortex-M3
    00013 *
    00014 * Version 1.0.3 2010/11/29
    00015 *    Re-organized the CMSIS folders and updated documentation.
    00016 *
    00017 * Version 1.0.2 2010/11/11
    00018 *    Documentation updated.
    00019 *
    00020 * Version 1.0.1 2010/10/05
    00021 *    Production release and review comments incorporated.
    00022 *
    00023 * Version 1.0.0 2010/09/20
    00024 *    Production release and review comments incorporated
    00025 *
    00026 * Version 0.0.7  2010/06/10
    00027 *    Misra-C changes done
    00028 * -------------------------------------------------------------------- */
    00029
    00030 #include "arm_math.h"
    00063 void arm_lms_q15(
    00064   const arm_lms_instance_q15 * S,
    00065   q15_t * pSrc,
    00066   q15_t * pRef,
    00067   q15_t * pOut,
    00068   q15_t * pErr,
    00069   uint32_t blockSize)
    00070 {
    00071   q15_t *pState = S->pState;                     /* State pointer */
    00072   uint32_t numTaps = S->numTaps;                 /* Number of filter coefficients in the filter */
    00073   q15_t *pCoeffs = S->pCoeffs;                   /* Coefficient pointer */
    00074   q15_t *pStateCurnt;                            /* Points to the current sample of the state */
    00075   q15_t mu = S->mu;                              /* Adaptive factor */
    00076   q15_t *px;                                     /* Temporary pointer for state */
    00077   q15_t *pb;                                     /* Temporary pointer for coefficient buffer */
    00078   uint32_t tapCnt, blkCnt;                       /* Loop counters */
    00079   q63_t acc;                                     /* Accumulator */
    00080   q15_t e = 0;                                   /* error of data sample */
    00081   q15_t alpha;                                   /* Intermediate constant for taps update */
    00082   uint32_t shift = S->postShift + 1u;            /* Shift to be applied to the output */
    00083   q31_t coef;                                    /* Teporary variable for coefficient */
    00084
    00085   /* S->pState points to buffer which contains previous frame (numTaps - 1) samples */
    00086   /* pStateCurnt points to the location where the new input data should be written */
    00087   pStateCurnt = &(S->pState[(numTaps - 1u)]);
    00088
    00089   /* Initializing blkCnt with blockSize */
    00090   blkCnt = blockSize;
    00091
    00092   while(blkCnt > 0u)
    00093   {
    00094     /* Copy the new input sample into the state buffer */
    00095     *pStateCurnt++ = *pSrc++;
    00096
    00097     /* Initialize state pointer */
    00098     px = pState;
    00099
    00100     /* Initialize coefficient pointer */
    00101     pb = pCoeffs;
    00102
    00103     /* Set the accumulator to zero */
    00104     acc = 0;
    00105
    00106     /* Loop unrolling.  Process 4 taps at a time. */
    00107     tapCnt = numTaps >> 2u;
    00108
    00109     while(tapCnt > 0u)
    00110     {
    00111       /* acc +=  b[N] * x[n-N] + b[N-1] * x[n-N-1] */
    00112       /* Perform the multiply-accumulate */
    00113       acc = __SMLALD(*__SIMD32(px)++, (*__SIMD32(pb)++), acc);
    00114       acc = __SMLALD(*__SIMD32(px)++, (*__SIMD32(pb)++), acc);
    00115
    00116       /* Decrement the loop counter */
    00117       tapCnt--;
    00118     }
    00119
    00120     /* If the filter length is not a multiple of 4, compute the remaining filter taps */
    00121     tapCnt = numTaps % 0x4u;
    00122
    00123     while(tapCnt > 0u)
    00124     {
    00125       /* Perform the multiply-accumulate */
    00126       acc += (q63_t) (((q31_t) (*px++) * (*pb++)));
    00127
    00128       /* Decrement the loop counter */
    00129       tapCnt--;
    00130     }
    00131
    00132     /* Converting the result to 1.15 format and saturate the output */
    00133     acc = __SSAT((acc >> (16 - shift)), 16);
    00134
    00135     /* Store the result from accumulator into the destination buffer. */
    00136     *pOut++ = (q15_t) acc;
    00137
    00138     /* Compute and store error */
    00139     e = *pRef++ - (q15_t) acc;
    00140
    00141     *pErr++ = (q15_t) e;
    00142
    00143     /* Compute alpha i.e. intermediate constant for taps update */
    00144     alpha = (q15_t) (((q31_t) e * (mu)) >> 15);
    00145
    00146     /* Initialize state pointer */
    00147     /* Advance state pointer by 1 for the next sample */
    00148     px = pState++;
    00149
    00150     /* Initialize coefficient pointer */
    00151     pb = pCoeffs;
    00152
    00153     /* Loop unrolling.  Process 4 taps at a time. */
    00154     tapCnt = numTaps >> 2u;
    00155
    00156     /* Update filter coefficients */
    00157     while(tapCnt > 0u)
    00158     {
    00159       coef = (q31_t) *pb + (((q31_t) alpha * (*px++)) >> 15);
    00160       *pb++ = (q15_t) __SSAT((coef), 16);
    00161       coef = (q31_t) *pb + (((q31_t) alpha * (*px++)) >> 15);
    00162       *pb++ = (q15_t) __SSAT((coef), 16);
    00163       coef = (q31_t) *pb + (((q31_t) alpha * (*px++)) >> 15);
    00164       *pb++ = (q15_t) __SSAT((coef), 16);
    00165       coef = (q31_t) *pb + (((q31_t) alpha * (*px++)) >> 15);
    00166       *pb++ = (q15_t) __SSAT((coef), 16);
    00167
    00168       /* Decrement the loop counter */
    00169       tapCnt--;
    00170     }
    00171
    00172     /* If the filter length is not a multiple of 4, compute the remaining filter taps */
    00173     tapCnt = numTaps % 0x4u;
    00174
    00175     while(tapCnt > 0u)
    00176     {
    00177       /* Perform the multiply-accumulate */
    00178       coef = (q31_t) *pb + (((q31_t) alpha * (*px++)) >> 15);
    00179       *pb++ = (q15_t) __SSAT((coef), 16);
    00180
    00181       /* Decrement the loop counter */
    00182       tapCnt--;
    00183     }
    00184
    00185     /* Decrement the loop counter */
    00186     blkCnt--;
    00187
    00188   }
    00189
    00190   /* Processing is complete. Now copy the last numTaps - 1 samples to the
    00191      satrt of the state buffer. This prepares the state buffer for the
    00192      next function call. */
    00193
    00194   /* Points to the start of the pState buffer */
    00195   pStateCurnt = S->pState;
    00196
    00197   /* Calculation of count for copying integer writes */
    00198   tapCnt = (numTaps - 1u) >> 2;
    00199
    00200   while(tapCnt > 0u)
    00201   {
    00202
    00203     *__SIMD32(pStateCurnt)++ = *__SIMD32(pState)++;
    00204     *__SIMD32(pStateCurnt)++ = *__SIMD32(pState)++;
    00205
    00206     tapCnt--;
    00207
    00208   }
    00209
    00210   /* Calculation of count for remaining q15_t data */
    00211   tapCnt = (numTaps - 1u) % 0x4u;
    00212
    00213   /* copy data */
    00214   while(tapCnt > 0u)
    00215   {
    00216     *pStateCurnt++ = *pState++;
    00217
    00218     /* Decrement the loop counter */
    00219     tapCnt--;
    00220   }
    00221
    00222 }
    00223

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines