Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of dsp by
arm_lms_q15.c
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" 00031 /** 00032 * @ingroup groupFilters 00033 */ 00034 00035 /** 00036 * @addtogroup LMS 00037 * @{ 00038 */ 00039 00040 /** 00041 * @brief Processing function for Q15 LMS filter. 00042 * @param[in] *S points to an instance of the Q15 LMS filter structure. 00043 * @param[in] *pSrc points to the block of input data. 00044 * @param[in] *pRef points to the block of reference data. 00045 * @param[out] *pOut points to the block of output data. 00046 * @param[out] *pErr points to the block of error data. 00047 * @param[in] blockSize number of samples to process. 00048 * @return none. 00049 * 00050 * \par Scaling and Overflow Behavior: 00051 * The function is implemented using a 64-bit internal accumulator. 00052 * Both coefficients and state variables are represented in 1.15 format and multiplications yield a 2.30 result. 00053 * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. 00054 * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. 00055 * After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits. 00056 * Lastly, the accumulator is saturated to yield a result in 1.15 format. 00057 * 00058 * \par 00059 * In this filter, filter coefficients are updated for each sample and the updation of filter cofficients are saturted. 00060 * 00061 */ 00062 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 00224 /** 00225 * @} end of LMS group 00226 */
Generated on Tue Jul 12 2022 19:55:43 by
1.7.2
