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 mbed-dsp by
arm_fir_lattice_f32.c
00001 /* ---------------------------------------------------------------------- 00002 * Copyright (C) 2010-2013 ARM Limited. All rights reserved. 00003 * 00004 * $Date: 17. January 2013 00005 * $Revision: V1.4.1 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 18:44:09 by
