CMSIS DSP library
Dependents: performance_timer Surfboard_ gps2rtty Capstone ... more
arm_fir_lattice_f32.c
00001 /* ---------------------------------------------------------------------- 00002 * Copyright (C) 2010-2014 ARM Limited. All rights reserved. 00003 * 00004 * $Date: 19. March 2015 00005 * $Revision: V.1.4.5 00006 * 00007 * Project: CMSIS DSP Library 00008 * Title: arm_fir_lattice_f32.c 00009 * 00010 * Description: Processing function for the floating-point FIR Lattice filter. 00011 * 00012 * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 00013 * 00014 * Redistribution and use in source and binary forms, with or without 00015 * modification, are permitted provided that the following conditions 00016 * are met: 00017 * - Redistributions of source code must retain the above copyright 00018 * notice, this list of conditions and the following disclaimer. 00019 * - Redistributions in binary form must reproduce the above copyright 00020 * notice, this list of conditions and the following disclaimer in 00021 * the documentation and/or other materials provided with the 00022 * distribution. 00023 * - Neither the name of ARM LIMITED nor the names of its contributors 00024 * may be used to endorse or promote products derived from this 00025 * software without specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00028 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00029 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00030 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00031 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00032 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00033 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00034 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00035 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00036 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00037 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00038 * POSSIBILITY OF SUCH DAMAGE. 00039 * -------------------------------------------------------------------- */ 00040 00041 #include "arm_math.h" 00042 00043 /** 00044 * @ingroup groupFilters 00045 */ 00046 00047 /** 00048 * @defgroup FIR_Lattice Finite Impulse Response (FIR) Lattice Filters 00049 * 00050 * This set of functions implements Finite Impulse Response (FIR) lattice filters 00051 * for Q15, Q31 and floating-point data types. Lattice filters are used in a 00052 * variety of adaptive filter applications. The filter structure is feedforward and 00053 * the net impulse response is finite length. 00054 * The functions operate on blocks 00055 * of input and output data and each call to the function processes 00056 * <code>blockSize</code> samples through the filter. <code>pSrc</code> and 00057 * <code>pDst</code> point to input and output arrays containing <code>blockSize</code> values. 00058 * 00059 * \par Algorithm: 00060 * \image html FIRLattice.gif "Finite Impulse Response Lattice filter" 00061 * The following difference equation is implemented: 00062 * <pre> 00063 * f0[n] = g0[n] = x[n] 00064 * fm[n] = fm-1[n] + km * gm-1[n-1] for m = 1, 2, ...M 00065 * gm[n] = km * fm-1[n] + gm-1[n-1] for m = 1, 2, ...M 00066 * y[n] = fM[n] 00067 * </pre> 00068 * \par 00069 * <code>pCoeffs</code> points to tha array of reflection coefficients of size <code>numStages</code>. 00070 * Reflection Coefficients are stored in the following order. 00071 * \par 00072 * <pre> 00073 * {k1, k2, ..., kM} 00074 * </pre> 00075 * where M is number of stages 00076 * \par 00077 * <code>pState</code> points to a state array of size <code>numStages</code>. 00078 * The state variables (g values) hold previous inputs and are stored in the following order. 00079 * <pre> 00080 * {g0[n], g1[n], g2[n] ...gM-1[n]} 00081 * </pre> 00082 * The state variables are updated after each block of data is processed; the coefficients are untouched. 00083 * \par Instance Structure 00084 * The coefficients and state variables for a filter are stored together in an instance data structure. 00085 * A separate instance structure must be defined for each filter. 00086 * Coefficient arrays may be shared among several instances while state variable arrays cannot be shared. 00087 * There are separate instance structure declarations for each of the 3 supported data types. 00088 * 00089 * \par Initialization Functions 00090 * There is also an associated initialization function for each data type. 00091 * The initialization function performs the following operations: 00092 * - Sets the values of the internal structure fields. 00093 * - Zeros out the values in the state buffer. 00094 * To do this manually without calling the init function, assign the follow subfields of the instance structure: 00095 * numStages, pCoeffs, pState. Also set all of the values in pState to zero. 00096 * 00097 * \par 00098 * Use of the initialization function is optional. 00099 * However, if the initialization function is used, then the instance structure cannot be placed into a const data section. 00100 * To place an instance structure into a const data section, the instance structure must be manually initialized. 00101 * Set the values in the state buffer to zeros and then manually initialize the instance structure as follows: 00102 * <pre> 00103 *arm_fir_lattice_instance_f32 S = {numStages, pState, pCoeffs}; 00104 *arm_fir_lattice_instance_q31 S = {numStages, pState, pCoeffs}; 00105 *arm_fir_lattice_instance_q15 S = {numStages, pState, pCoeffs}; 00106 * </pre> 00107 * \par 00108 * where <code>numStages</code> is the number of stages in the filter; <code>pState</code> is the address of the state buffer; 00109 * <code>pCoeffs</code> is the address of the coefficient buffer. 00110 * \par Fixed-Point Behavior 00111 * Care must be taken when using the fixed-point versions of the FIR Lattice filter functions. 00112 * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. 00113 * Refer to the function specific documentation below for usage guidelines. 00114 */ 00115 00116 /** 00117 * @addtogroup FIR_Lattice 00118 * @{ 00119 */ 00120 00121 00122 /** 00123 * @brief Processing function for the floating-point FIR lattice filter. 00124 * @param[in] *S points to an instance of the floating-point FIR lattice structure. 00125 * @param[in] *pSrc points to the block of input data. 00126 * @param[out] *pDst points to the block of output data 00127 * @param[in] blockSize number of samples to process. 00128 * @return none. 00129 */ 00130 00131 void arm_fir_lattice_f32( 00132 const arm_fir_lattice_instance_f32 * S, 00133 float32_t * pSrc, 00134 float32_t * pDst, 00135 uint32_t blockSize) 00136 { 00137 float32_t *pState; /* State pointer */ 00138 float32_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ 00139 float32_t *px; /* temporary state pointer */ 00140 float32_t *pk; /* temporary coefficient pointer */ 00141 00142 00143 #ifndef ARM_MATH_CM0_FAMILY 00144 00145 /* Run the below code for Cortex-M4 and Cortex-M3 */ 00146 00147 float32_t fcurr1, fnext1, gcurr1, gnext1; /* temporary variables for first sample in loop unrolling */ 00148 float32_t fcurr2, fnext2, gnext2; /* temporary variables for second sample in loop unrolling */ 00149 float32_t fcurr3, fnext3, gnext3; /* temporary variables for third sample in loop unrolling */ 00150 float32_t fcurr4, fnext4, gnext4; /* temporary variables for fourth sample in loop unrolling */ 00151 uint32_t numStages = S->numStages; /* Number of stages in the filter */ 00152 uint32_t blkCnt, stageCnt; /* temporary variables for counts */ 00153 00154 gcurr1 = 0.0f; 00155 pState = &S->pState[0]; 00156 00157 blkCnt = blockSize >> 2; 00158 00159 /* First part of the processing with loop unrolling. Compute 4 outputs at a time. 00160 a second loop below computes the remaining 1 to 3 samples. */ 00161 while(blkCnt > 0u) 00162 { 00163 00164 /* Read two samples from input buffer */ 00165 /* f0(n) = x(n) */ 00166 fcurr1 = *pSrc++; 00167 fcurr2 = *pSrc++; 00168 00169 /* Initialize coeff pointer */ 00170 pk = (pCoeffs); 00171 00172 /* Initialize state pointer */ 00173 px = pState; 00174 00175 /* Read g0(n-1) from state */ 00176 gcurr1 = *px; 00177 00178 /* Process first sample for first tap */ 00179 /* f1(n) = f0(n) + K1 * g0(n-1) */ 00180 fnext1 = fcurr1 + ((*pk) * gcurr1); 00181 /* g1(n) = f0(n) * K1 + g0(n-1) */ 00182 gnext1 = (fcurr1 * (*pk)) + gcurr1; 00183 00184 /* Process second sample for first tap */ 00185 /* for sample 2 processing */ 00186 fnext2 = fcurr2 + ((*pk) * fcurr1); 00187 gnext2 = (fcurr2 * (*pk)) + fcurr1; 00188 00189 /* Read next two samples from input buffer */ 00190 /* f0(n+2) = x(n+2) */ 00191 fcurr3 = *pSrc++; 00192 fcurr4 = *pSrc++; 00193 00194 /* Copy only last input samples into the state buffer 00195 which will be used for next four samples processing */ 00196 *px++ = fcurr4; 00197 00198 /* Process third sample for first tap */ 00199 fnext3 = fcurr3 + ((*pk) * fcurr2); 00200 gnext3 = (fcurr3 * (*pk)) + fcurr2; 00201 00202 /* Process fourth sample for first tap */ 00203 fnext4 = fcurr4 + ((*pk) * fcurr3); 00204 gnext4 = (fcurr4 * (*pk++)) + fcurr3; 00205 00206 /* Update of f values for next coefficient set processing */ 00207 fcurr1 = fnext1; 00208 fcurr2 = fnext2; 00209 fcurr3 = fnext3; 00210 fcurr4 = fnext4; 00211 00212 /* Loop unrolling. Process 4 taps at a time . */ 00213 stageCnt = (numStages - 1u) >> 2u; 00214 00215 /* Loop over the number of taps. Unroll by a factor of 4. 00216 ** Repeat until we've computed numStages-3 coefficients. */ 00217 00218 /* Process 2nd, 3rd, 4th and 5th taps ... here */ 00219 while(stageCnt > 0u) 00220 { 00221 /* Read g1(n-1), g3(n-1) .... from state */ 00222 gcurr1 = *px; 00223 00224 /* save g1(n) in state buffer */ 00225 *px++ = gnext4; 00226 00227 /* Process first sample for 2nd, 6th .. tap */ 00228 /* Sample processing for K2, K6.... */ 00229 /* f2(n) = f1(n) + K2 * g1(n-1) */ 00230 fnext1 = fcurr1 + ((*pk) * gcurr1); 00231 /* Process second sample for 2nd, 6th .. tap */ 00232 /* for sample 2 processing */ 00233 fnext2 = fcurr2 + ((*pk) * gnext1); 00234 /* Process third sample for 2nd, 6th .. tap */ 00235 fnext3 = fcurr3 + ((*pk) * gnext2); 00236 /* Process fourth sample for 2nd, 6th .. tap */ 00237 fnext4 = fcurr4 + ((*pk) * gnext3); 00238 00239 /* g2(n) = f1(n) * K2 + g1(n-1) */ 00240 /* Calculation of state values for next stage */ 00241 gnext4 = (fcurr4 * (*pk)) + gnext3; 00242 gnext3 = (fcurr3 * (*pk)) + gnext2; 00243 gnext2 = (fcurr2 * (*pk)) + gnext1; 00244 gnext1 = (fcurr1 * (*pk++)) + gcurr1; 00245 00246 00247 /* Read g2(n-1), g4(n-1) .... from state */ 00248 gcurr1 = *px; 00249 00250 /* save g2(n) in state buffer */ 00251 *px++ = gnext4; 00252 00253 /* Sample processing for K3, K7.... */ 00254 /* Process first sample for 3rd, 7th .. tap */ 00255 /* f3(n) = f2(n) + K3 * g2(n-1) */ 00256 fcurr1 = fnext1 + ((*pk) * gcurr1); 00257 /* Process second sample for 3rd, 7th .. tap */ 00258 fcurr2 = fnext2 + ((*pk) * gnext1); 00259 /* Process third sample for 3rd, 7th .. tap */ 00260 fcurr3 = fnext3 + ((*pk) * gnext2); 00261 /* Process fourth sample for 3rd, 7th .. tap */ 00262 fcurr4 = fnext4 + ((*pk) * gnext3); 00263 00264 /* Calculation of state values for next stage */ 00265 /* g3(n) = f2(n) * K3 + g2(n-1) */ 00266 gnext4 = (fnext4 * (*pk)) + gnext3; 00267 gnext3 = (fnext3 * (*pk)) + gnext2; 00268 gnext2 = (fnext2 * (*pk)) + gnext1; 00269 gnext1 = (fnext1 * (*pk++)) + gcurr1; 00270 00271 00272 /* Read g1(n-1), g3(n-1) .... from state */ 00273 gcurr1 = *px; 00274 00275 /* save g3(n) in state buffer */ 00276 *px++ = gnext4; 00277 00278 /* Sample processing for K4, K8.... */ 00279 /* Process first sample for 4th, 8th .. tap */ 00280 /* f4(n) = f3(n) + K4 * g3(n-1) */ 00281 fnext1 = fcurr1 + ((*pk) * gcurr1); 00282 /* Process second sample for 4th, 8th .. tap */ 00283 /* for sample 2 processing */ 00284 fnext2 = fcurr2 + ((*pk) * gnext1); 00285 /* Process third sample for 4th, 8th .. tap */ 00286 fnext3 = fcurr3 + ((*pk) * gnext2); 00287 /* Process fourth sample for 4th, 8th .. tap */ 00288 fnext4 = fcurr4 + ((*pk) * gnext3); 00289 00290 /* g4(n) = f3(n) * K4 + g3(n-1) */ 00291 /* Calculation of state values for next stage */ 00292 gnext4 = (fcurr4 * (*pk)) + gnext3; 00293 gnext3 = (fcurr3 * (*pk)) + gnext2; 00294 gnext2 = (fcurr2 * (*pk)) + gnext1; 00295 gnext1 = (fcurr1 * (*pk++)) + gcurr1; 00296 00297 /* Read g2(n-1), g4(n-1) .... from state */ 00298 gcurr1 = *px; 00299 00300 /* save g4(n) in state buffer */ 00301 *px++ = gnext4; 00302 00303 /* Sample processing for K5, K9.... */ 00304 /* Process first sample for 5th, 9th .. tap */ 00305 /* f5(n) = f4(n) + K5 * g4(n-1) */ 00306 fcurr1 = fnext1 + ((*pk) * gcurr1); 00307 /* Process second sample for 5th, 9th .. tap */ 00308 fcurr2 = fnext2 + ((*pk) * gnext1); 00309 /* Process third sample for 5th, 9th .. tap */ 00310 fcurr3 = fnext3 + ((*pk) * gnext2); 00311 /* Process fourth sample for 5th, 9th .. tap */ 00312 fcurr4 = fnext4 + ((*pk) * gnext3); 00313 00314 /* Calculation of state values for next stage */ 00315 /* g5(n) = f4(n) * K5 + g4(n-1) */ 00316 gnext4 = (fnext4 * (*pk)) + gnext3; 00317 gnext3 = (fnext3 * (*pk)) + gnext2; 00318 gnext2 = (fnext2 * (*pk)) + gnext1; 00319 gnext1 = (fnext1 * (*pk++)) + gcurr1; 00320 00321 stageCnt--; 00322 } 00323 00324 /* If the (filter length -1) is not a multiple of 4, compute the remaining filter taps */ 00325 stageCnt = (numStages - 1u) % 0x4u; 00326 00327 while(stageCnt > 0u) 00328 { 00329 gcurr1 = *px; 00330 00331 /* save g value in state buffer */ 00332 *px++ = gnext4; 00333 00334 /* Process four samples for last three taps here */ 00335 fnext1 = fcurr1 + ((*pk) * gcurr1); 00336 fnext2 = fcurr2 + ((*pk) * gnext1); 00337 fnext3 = fcurr3 + ((*pk) * gnext2); 00338 fnext4 = fcurr4 + ((*pk) * gnext3); 00339 00340 /* g1(n) = f0(n) * K1 + g0(n-1) */ 00341 gnext4 = (fcurr4 * (*pk)) + gnext3; 00342 gnext3 = (fcurr3 * (*pk)) + gnext2; 00343 gnext2 = (fcurr2 * (*pk)) + gnext1; 00344 gnext1 = (fcurr1 * (*pk++)) + gcurr1; 00345 00346 /* Update of f values for next coefficient set processing */ 00347 fcurr1 = fnext1; 00348 fcurr2 = fnext2; 00349 fcurr3 = fnext3; 00350 fcurr4 = fnext4; 00351 00352 stageCnt--; 00353 00354 } 00355 00356 /* The results in the 4 accumulators, store in the destination buffer. */ 00357 /* y(n) = fN(n) */ 00358 *pDst++ = fcurr1; 00359 *pDst++ = fcurr2; 00360 *pDst++ = fcurr3; 00361 *pDst++ = fcurr4; 00362 00363 blkCnt--; 00364 } 00365 00366 /* If the blockSize is not a multiple of 4, compute any remaining output samples here. 00367 ** No loop unrolling is used. */ 00368 blkCnt = blockSize % 0x4u; 00369 00370 while(blkCnt > 0u) 00371 { 00372 /* f0(n) = x(n) */ 00373 fcurr1 = *pSrc++; 00374 00375 /* Initialize coeff pointer */ 00376 pk = (pCoeffs); 00377 00378 /* Initialize state pointer */ 00379 px = pState; 00380 00381 /* read g2(n) from state buffer */ 00382 gcurr1 = *px; 00383 00384 /* for sample 1 processing */ 00385 /* f1(n) = f0(n) + K1 * g0(n-1) */ 00386 fnext1 = fcurr1 + ((*pk) * gcurr1); 00387 /* g1(n) = f0(n) * K1 + g0(n-1) */ 00388 gnext1 = (fcurr1 * (*pk++)) + gcurr1; 00389 00390 /* save g1(n) in state buffer */ 00391 *px++ = fcurr1; 00392 00393 /* f1(n) is saved in fcurr1 00394 for next stage processing */ 00395 fcurr1 = fnext1; 00396 00397 stageCnt = (numStages - 1u); 00398 00399 /* stage loop */ 00400 while(stageCnt > 0u) 00401 { 00402 /* read g2(n) from state buffer */ 00403 gcurr1 = *px; 00404 00405 /* save g1(n) in state buffer */ 00406 *px++ = gnext1; 00407 00408 /* Sample processing for K2, K3.... */ 00409 /* f2(n) = f1(n) + K2 * g1(n-1) */ 00410 fnext1 = fcurr1 + ((*pk) * gcurr1); 00411 /* g2(n) = f1(n) * K2 + g1(n-1) */ 00412 gnext1 = (fcurr1 * (*pk++)) + gcurr1; 00413 00414 /* f1(n) is saved in fcurr1 00415 for next stage processing */ 00416 fcurr1 = fnext1; 00417 00418 stageCnt--; 00419 00420 } 00421 00422 /* y(n) = fN(n) */ 00423 *pDst++ = fcurr1; 00424 00425 blkCnt--; 00426 00427 } 00428 00429 #else 00430 00431 /* Run the below code for Cortex-M0 */ 00432 00433 float32_t fcurr, fnext, gcurr, gnext; /* temporary variables */ 00434 uint32_t numStages = S->numStages; /* Length of the filter */ 00435 uint32_t blkCnt, stageCnt; /* temporary variables for counts */ 00436 00437 pState = &S->pState[0]; 00438 00439 blkCnt = blockSize; 00440 00441 while(blkCnt > 0u) 00442 { 00443 /* f0(n) = x(n) */ 00444 fcurr = *pSrc++; 00445 00446 /* Initialize coeff pointer */ 00447 pk = pCoeffs; 00448 00449 /* Initialize state pointer */ 00450 px = pState; 00451 00452 /* read g0(n-1) from state buffer */ 00453 gcurr = *px; 00454 00455 /* for sample 1 processing */ 00456 /* f1(n) = f0(n) + K1 * g0(n-1) */ 00457 fnext = fcurr + ((*pk) * gcurr); 00458 /* g1(n) = f0(n) * K1 + g0(n-1) */ 00459 gnext = (fcurr * (*pk++)) + gcurr; 00460 00461 /* save f0(n) in state buffer */ 00462 *px++ = fcurr; 00463 00464 /* f1(n) is saved in fcurr 00465 for next stage processing */ 00466 fcurr = fnext; 00467 00468 stageCnt = (numStages - 1u); 00469 00470 /* stage loop */ 00471 while(stageCnt > 0u) 00472 { 00473 /* read g2(n) from state buffer */ 00474 gcurr = *px; 00475 00476 /* save g1(n) in state buffer */ 00477 *px++ = gnext; 00478 00479 /* Sample processing for K2, K3.... */ 00480 /* f2(n) = f1(n) + K2 * g1(n-1) */ 00481 fnext = fcurr + ((*pk) * gcurr); 00482 /* g2(n) = f1(n) * K2 + g1(n-1) */ 00483 gnext = (fcurr * (*pk++)) + gcurr; 00484 00485 /* f1(n) is saved in fcurr1 00486 for next stage processing */ 00487 fcurr = fnext; 00488 00489 stageCnt--; 00490 00491 } 00492 00493 /* y(n) = fN(n) */ 00494 *pDst++ = fcurr; 00495 00496 blkCnt--; 00497 00498 } 00499 00500 #endif /* #ifndef ARM_MATH_CM0_FAMILY */ 00501 00502 } 00503 00504 /** 00505 * @} end of FIR_Lattice group 00506 */
Generated on Tue Jul 12 2022 11:59:17 by 1.7.2