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_iir_lattice_f32.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_iir_lattice_f32.c 00009 * 00010 * Description: Floating-point IIR Lattice filter processing function. 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 /** 00033 * @ingroup groupFilters 00034 */ 00035 00036 /** 00037 * @defgroup IIR_Lattice Infinite Impulse Response (IIR) Lattice Filters 00038 * 00039 * This set of functions implements lattice filters 00040 * for Q15, Q31 and floating-point data types. Lattice filters are used in a 00041 * variety of adaptive filter applications. The filter structure has feedforward and 00042 * feedback components and the net impulse response is infinite length. 00043 * The functions operate on blocks 00044 * of input and output data and each call to the function processes 00045 * <code>blockSize</code> samples through the filter. <code>pSrc</code> and 00046 * <code>pDst</code> point to input and output arrays containing <code>blockSize</code> values. 00047 00048 * \par Algorithm: 00049 * \image html IIRLattice.gif "Infinite Impulse Response Lattice filter" 00050 * <pre> 00051 * fN(n) = x(n) 00052 * fm-1(n) = fm(n) - km * gm-1(n-1) for m = N, N-1, ...1 00053 * gm(n) = km * fm-1(n) + gm-1(n-1) for m = N, N-1, ...1 00054 * y(n) = vN * gN(n) + vN-1 * gN-1(n) + ...+ v0 * g0(n) 00055 * </pre> 00056 * \par 00057 * <code>pkCoeffs</code> points to array of reflection coefficients of size <code>numStages</code>. 00058 * Reflection coefficients are stored in time-reversed order. 00059 * \par 00060 * <pre> 00061 * {kN, kN-1, ....k1} 00062 * </pre> 00063 * <code>pvCoeffs</code> points to the array of ladder coefficients of size <code>(numStages+1)</code>. 00064 * Ladder coefficients are stored in time-reversed order. 00065 * \par 00066 * <pre> 00067 * {vN, vN-1, ...v0} 00068 * </pre> 00069 * <code>pState</code> points to a state array of size <code>numStages + blockSize</code>. 00070 * The state variables shown in the figure above (the g values) are stored in the <code>pState</code> array. 00071 * The state variables are updated after each block of data is processed; the coefficients are untouched. 00072 * \par Instance Structure 00073 * The coefficients and state variables for a filter are stored together in an instance data structure. 00074 * A separate instance structure must be defined for each filter. 00075 * Coefficient arrays may be shared among several instances while state variable arrays cannot be shared. 00076 * There are separate instance structure declarations for each of the 3 supported data types. 00077 * 00078 * \par Initialization Functions 00079 * There is also an associated initialization function for each data type. 00080 * The initialization function performs the following operations: 00081 * - Sets the values of the internal structure fields. 00082 * - Zeros out the values in the state buffer. 00083 * 00084 * \par 00085 * Use of the initialization function is optional. 00086 * However, if the initialization function is used, then the instance structure cannot be placed into a const data section. 00087 * To place an instance structure into a const data section, the instance structure must be manually initialized. 00088 * Set the values in the state buffer to zeros and then manually initialize the instance structure as follows: 00089 * <pre> 00090 *arm_iir_lattice_instance_f32 S = {numStages, pState, pkCoeffs, pvCoeffs}; 00091 *arm_iir_lattice_instance_q31 S = {numStages, pState, pkCoeffs, pvCoeffs}; 00092 *arm_iir_lattice_instance_q15 S = {numStages, pState, pkCoeffs, pvCoeffs}; 00093 * </pre> 00094 * \par 00095 * where <code>numStages</code> is the number of stages in the filter; <code>pState</code> points to the state buffer array; 00096 * <code>pkCoeffs</code> points to array of the reflection coefficients; <code>pvCoeffs</code> points to the array of ladder coefficients. 00097 * \par Fixed-Point Behavior 00098 * Care must be taken when using the fixed-point versions of the IIR lattice filter functions. 00099 * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. 00100 * Refer to the function specific documentation below for usage guidelines. 00101 */ 00102 00103 /** 00104 * @addtogroup IIR_Lattice 00105 * @{ 00106 */ 00107 00108 /** 00109 * @brief Processing function for the floating-point IIR lattice filter. 00110 * @param[in] *S points to an instance of the floating-point IIR lattice structure. 00111 * @param[in] *pSrc points to the block of input data. 00112 * @param[out] *pDst points to the block of output data. 00113 * @param[in] blockSize number of samples to process. 00114 * @return none. 00115 */ 00116 00117 void arm_iir_lattice_f32( 00118 const arm_iir_lattice_instance_f32 * S, 00119 float32_t * pSrc, 00120 float32_t * pDst, 00121 uint32_t blockSize) 00122 { 00123 float32_t fcurr, fnext, gcurr, gnext; /* Temporary variables for lattice stages */ 00124 float32_t acc; /* Accumlator */ 00125 uint32_t blkCnt, tapCnt; /* temporary variables for counts */ 00126 float32_t *px1, *px2, *pk, *pv; /* temporary pointers for state and coef */ 00127 uint32_t numStages = S->numStages; /* number of stages */ 00128 float32_t *pState; /* State pointer */ 00129 float32_t *pStateCurnt; /* State current pointer */ 00130 00131 gcurr = 0.0f; 00132 blkCnt = blockSize; 00133 00134 pState = &S->pState[0]; 00135 00136 /* Sample processing */ 00137 while(blkCnt > 0u) 00138 { 00139 /* Read Sample from input buffer */ 00140 /* fN(n) = x(n) */ 00141 fcurr = *pSrc++; 00142 00143 /* Initialize state read pointer */ 00144 px1 = pState; 00145 /* Initialize state write pointer */ 00146 px2 = pState; 00147 /* Set accumulator to zero */ 00148 acc = 0.0f; 00149 /* Initialize Ladder coeff pointer */ 00150 pv = &S->pvCoeffs[0]; 00151 /* Initialize Reflection coeff pointer */ 00152 pk = &S->pkCoeffs[0]; 00153 00154 00155 /* Process sample for first tap */ 00156 gcurr = *px1++; 00157 /* fN-1(n) = fN(n) - kN * gN-1(n-1) */ 00158 fnext = fcurr - ((*pk) * gcurr); 00159 /* gN(n) = kN * fN-1(n) + gN-1(n-1) */ 00160 gnext = (fnext * (*pk++)) + gcurr; 00161 /* write gN(n) into state for next sample processing */ 00162 *px2++ = gnext; 00163 /* y(n) += gN(n) * vN */ 00164 acc += (gnext * (*pv++)); 00165 00166 /* Update f values for next coefficient processing */ 00167 fcurr = fnext; 00168 00169 /* Loop unrolling. Process 4 taps at a time. */ 00170 tapCnt = (numStages - 1u) >> 2; 00171 00172 while(tapCnt > 0u) 00173 { 00174 /* Process sample for 2nd, 6th ...taps */ 00175 /* Read gN-2(n-1) from state buffer */ 00176 gcurr = *px1++; 00177 /* Process sample for 2nd, 6th .. taps */ 00178 /* fN-2(n) = fN-1(n) - kN-1 * gN-2(n-1) */ 00179 fnext = fcurr - ((*pk) * gcurr); 00180 /* gN-1(n) = kN-1 * fN-2(n) + gN-2(n-1) */ 00181 gnext = (fnext * (*pk++)) + gcurr; 00182 /* y(n) += gN-1(n) * vN-1 */ 00183 /* process for gN-5(n) * vN-5, gN-9(n) * vN-9 ... */ 00184 acc += (gnext * (*pv++)); 00185 /* write gN-1(n) into state for next sample processing */ 00186 *px2++ = gnext; 00187 00188 00189 /* Process sample for 3nd, 7th ...taps */ 00190 /* Read gN-3(n-1) from state buffer */ 00191 gcurr = *px1++; 00192 /* Process sample for 3rd, 7th .. taps */ 00193 /* fN-3(n) = fN-2(n) - kN-2 * gN-3(n-1) */ 00194 fcurr = fnext - ((*pk) * gcurr); 00195 /* gN-2(n) = kN-2 * fN-3(n) + gN-3(n-1) */ 00196 gnext = (fcurr * (*pk++)) + gcurr; 00197 /* y(n) += gN-2(n) * vN-2 */ 00198 /* process for gN-6(n) * vN-6, gN-10(n) * vN-10 ... */ 00199 acc += (gnext * (*pv++)); 00200 /* write gN-2(n) into state for next sample processing */ 00201 *px2++ = gnext; 00202 00203 00204 /* Process sample for 4th, 8th ...taps */ 00205 /* Read gN-4(n-1) from state buffer */ 00206 gcurr = *px1++; 00207 /* Process sample for 4th, 8th .. taps */ 00208 /* fN-4(n) = fN-3(n) - kN-3 * gN-4(n-1) */ 00209 fnext = fcurr - ((*pk) * gcurr); 00210 /* gN-3(n) = kN-3 * fN-4(n) + gN-4(n-1) */ 00211 gnext = (fnext * (*pk++)) + gcurr; 00212 /* y(n) += gN-3(n) * vN-3 */ 00213 /* process for gN-7(n) * vN-7, gN-11(n) * vN-11 ... */ 00214 acc += (gnext * (*pv++)); 00215 /* write gN-3(n) into state for next sample processing */ 00216 *px2++ = gnext; 00217 00218 00219 /* Process sample for 5th, 9th ...taps */ 00220 /* Read gN-5(n-1) from state buffer */ 00221 gcurr = *px1++; 00222 /* Process sample for 5th, 9th .. taps */ 00223 /* fN-5(n) = fN-4(n) - kN-4 * gN-1(n-1) */ 00224 fcurr = fnext - ((*pk) * gcurr); 00225 /* gN-4(n) = kN-4 * fN-5(n) + gN-5(n-1) */ 00226 gnext = (fcurr * (*pk++)) + gcurr; 00227 /* y(n) += gN-4(n) * vN-4 */ 00228 /* process for gN-8(n) * vN-8, gN-12(n) * vN-12 ... */ 00229 acc += (gnext * (*pv++)); 00230 /* write gN-4(n) into state for next sample processing */ 00231 *px2++ = gnext; 00232 00233 tapCnt--; 00234 00235 } 00236 00237 fnext = fcurr; 00238 00239 /* If the filter length is not a multiple of 4, compute the remaining filter taps */ 00240 tapCnt = (numStages - 1u) % 0x4u; 00241 00242 while(tapCnt > 0u) 00243 { 00244 gcurr = *px1++; 00245 /* Process sample for last taps */ 00246 fnext = fcurr - ((*pk) * gcurr); 00247 gnext = (fnext * (*pk++)) + gcurr; 00248 /* Output samples for last taps */ 00249 acc += (gnext * (*pv++)); 00250 *px2++ = gnext; 00251 fcurr = fnext; 00252 00253 tapCnt--; 00254 00255 } 00256 00257 00258 /* y(n) += g0(n) * v0 */ 00259 acc += (fnext * (*pv)); 00260 00261 *px2++ = fnext; 00262 00263 /* write out into pDst */ 00264 *pDst++ = acc; 00265 00266 /* Advance the state pointer by 4 to process the next group of 4 samples */ 00267 pState = pState + 1u; 00268 blkCnt--; 00269 00270 } 00271 00272 /* Processing is complete. Now copy last S->numStages samples to start of the buffer 00273 for the preperation of next frame process */ 00274 00275 /* Points to the start of the state buffer */ 00276 pStateCurnt = &S->pState[0]; 00277 pState = &S->pState[blockSize]; 00278 00279 tapCnt = numStages >> 2u; 00280 00281 /* copy data */ 00282 while(tapCnt > 0u) 00283 { 00284 *pStateCurnt++ = *pState++; 00285 *pStateCurnt++ = *pState++; 00286 *pStateCurnt++ = *pState++; 00287 *pStateCurnt++ = *pState++; 00288 00289 /* Decrement the loop counter */ 00290 tapCnt--; 00291 00292 } 00293 00294 /* Calculate remaining number of copies */ 00295 tapCnt = (numStages) % 0x4u; 00296 00297 /* Copy the remaining q31_t data */ 00298 while(tapCnt > 0u) 00299 { 00300 *pStateCurnt++ = *pState++; 00301 00302 /* Decrement the loop counter */ 00303 tapCnt--; 00304 } 00305 00306 } 00307 00308 00309 00310 00311 /** 00312 * @} end of IIR_Lattice group 00313 */
Generated on Tue Jul 12 2022 19:55:43 by
1.7.2
