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_q31.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_q31.c 00009 * 00010 * Description: Processing function for the Q31 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 Q31 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 an internal 64-bit accumulator. 00052 * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. 00053 * Thus, if the accumulator result overflows it wraps around rather than clips. 00054 * In order to avoid overflows completely the input signal must be scaled down by log2(numTaps) bits. 00055 * The reference signal should not be scaled down. 00056 * After all multiply-accumulates are performed, the 2.62 accumulator is truncated to 1.32 format and then saturated to 1.31 format. 00057 * The output signal and error signal are in 1.31 format. 00058 * 00059 * \par 00060 * In this filter, filter coefficients are updated for each sample and the updation of filter cofficients are saturted. 00061 */ 00062 00063 void arm_lms_q31( 00064 const arm_lms_instance_q31 * S, 00065 q31_t * pSrc, 00066 q31_t * pRef, 00067 q31_t * pOut, 00068 q31_t * pErr, 00069 uint32_t blockSize) 00070 { 00071 q31_t *pState = S->pState; /* State pointer */ 00072 uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ 00073 q31_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ 00074 q31_t *pStateCurnt; /* Points to the current sample of the state */ 00075 q31_t mu = S->mu; /* Adaptive factor */ 00076 q31_t *px; /* Temporary pointer for state */ 00077 q31_t *pb; /* Temporary pointer for coefficient buffer */ 00078 uint32_t tapCnt, blkCnt; /* Loop counters */ 00079 q63_t acc; /* Accumulator */ 00080 q31_t e = 0; /* error of data sample */ 00081 q31_t alpha; /* Intermediate constant for taps update */ 00082 uint8_t shift = (uint8_t) (32u - (S->postShift + 1u)); /* Shift to be applied to the output */ 00083 q31_t coef; /* Temporary variable for coef */ 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 >> 2; 00108 00109 while(tapCnt > 0u) 00110 { 00111 /* Perform the multiply-accumulate */ 00112 /* acc += b[N] * x[n-N] */ 00113 acc += ((q63_t) (*px++)) * (*pb++); 00114 00115 /* acc += b[N-1] * x[n-N-1] */ 00116 acc += ((q63_t) (*px++)) * (*pb++); 00117 00118 /* acc += b[N-2] * x[n-N-2] */ 00119 acc += ((q63_t) (*px++)) * (*pb++); 00120 00121 /* acc += b[N-3] * x[n-N-3] */ 00122 acc += ((q63_t) (*px++)) * (*pb++); 00123 00124 /* Decrement the loop counter */ 00125 tapCnt--; 00126 } 00127 00128 /* If the filter length is not a multiple of 4, compute the remaining filter taps */ 00129 tapCnt = numTaps % 0x4u; 00130 00131 while(tapCnt > 0u) 00132 { 00133 /* Perform the multiply-accumulate */ 00134 acc += ((q63_t) (*px++)) * (*pb++); 00135 00136 /* Decrement the loop counter */ 00137 tapCnt--; 00138 } 00139 00140 /* Converting the result to 1.31 format */ 00141 /* Store the result from accumulator into the destination buffer. */ 00142 acc = (q31_t) (acc >> shift); 00143 00144 *pOut++ = (q31_t) acc; 00145 00146 /* Compute and store error */ 00147 e = *pRef++ - (q31_t) acc; 00148 00149 *pErr++ = (q31_t) e; 00150 00151 /* Compute alpha i.e. intermediate constant for taps update */ 00152 alpha = (q31_t) (((q63_t) e * mu) >> 31); 00153 00154 /* Initialize state pointer */ 00155 /* Advance state pointer by 1 for the next sample */ 00156 px = pState++; 00157 00158 /* Initialize coefficient pointer */ 00159 pb = pCoeffs; 00160 00161 /* Loop unrolling. Process 4 taps at a time. */ 00162 tapCnt = numTaps >> 2; 00163 00164 /* Update filter coefficients */ 00165 while(tapCnt > 0u) 00166 { 00167 /* coef is in 2.30 format */ 00168 coef = (q31_t) (((q63_t) alpha * (*px++)) >> (32)); 00169 /* get coef in 1.31 format by left shifting */ 00170 *pb = clip_q63_to_q31((q63_t) *pb + (coef << 1u)); 00171 /* update coefficient buffer to next coefficient */ 00172 pb++; 00173 00174 coef = (q31_t) (((q63_t) alpha * (*px++)) >> (32)); 00175 *pb = clip_q63_to_q31((q63_t) *pb + (coef << 1u)); 00176 pb++; 00177 00178 coef = (q31_t) (((q63_t) alpha * (*px++)) >> (32)); 00179 *pb = clip_q63_to_q31((q63_t) *pb + (coef << 1u)); 00180 pb++; 00181 00182 coef = (q31_t) (((q63_t) alpha * (*px++)) >> (32)); 00183 *pb = clip_q63_to_q31((q63_t) *pb + (coef << 1u)); 00184 pb++; 00185 00186 /* Decrement the loop counter */ 00187 tapCnt--; 00188 } 00189 00190 /* If the filter length is not a multiple of 4, compute the remaining filter taps */ 00191 tapCnt = numTaps % 0x4u; 00192 00193 while(tapCnt > 0u) 00194 { 00195 /* Perform the multiply-accumulate */ 00196 coef = (q31_t) (((q63_t) alpha * (*px++)) >> (32)); 00197 *pb = clip_q63_to_q31((q63_t) *pb + (coef << 1u)); 00198 pb++; 00199 00200 /* Decrement the loop counter */ 00201 tapCnt--; 00202 } 00203 00204 /* Decrement the loop counter */ 00205 blkCnt--; 00206 } 00207 00208 /* Processing is complete. Now copy the last numTaps - 1 samples to the 00209 satrt of the state buffer. This prepares the state buffer for the 00210 next function call. */ 00211 00212 /* Points to the start of the pState buffer */ 00213 pStateCurnt = S->pState; 00214 00215 /* Loop unrolling for (numTaps - 1u) samples copy */ 00216 tapCnt = (numTaps - 1u) >> 2u; 00217 00218 /* copy data */ 00219 while(tapCnt > 0u) 00220 { 00221 *pStateCurnt++ = *pState++; 00222 *pStateCurnt++ = *pState++; 00223 *pStateCurnt++ = *pState++; 00224 *pStateCurnt++ = *pState++; 00225 00226 /* Decrement the loop counter */ 00227 tapCnt--; 00228 } 00229 00230 /* Calculate remaining number of copies */ 00231 tapCnt = (numTaps - 1u) % 0x4u; 00232 00233 /* Copy the remaining q31_t data */ 00234 while(tapCnt > 0u) 00235 { 00236 *pStateCurnt++ = *pState++; 00237 00238 /* Decrement the loop counter */ 00239 tapCnt--; 00240 } 00241 00242 } 00243 00244 /** 00245 * @} end of LMS group 00246 */
Generated on Tue Jul 12 2022 19:55:43 by
1.7.2
