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-os by
arm_fir_decimate_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_decimate_f32.c 00009 * 00010 * Description: FIR decimation for floating-point sequences. 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_decimate Finite Impulse Response (FIR) Decimator 00049 * 00050 * These functions combine an FIR filter together with a decimator. 00051 * They are used in multirate systems for reducing the sample rate of a signal without introducing aliasing distortion. 00052 * Conceptually, the functions are equivalent to the block diagram below: 00053 * \image html FIRDecimator.gif "Components included in the FIR Decimator functions" 00054 * When decimating by a factor of <code>M</code>, the signal should be prefiltered by a lowpass filter with a normalized 00055 * cutoff frequency of <code>1/M</code> in order to prevent aliasing distortion. 00056 * The user of the function is responsible for providing the filter coefficients. 00057 * 00058 * The FIR decimator functions provided in the CMSIS DSP Library combine the FIR filter and the decimator in an efficient manner. 00059 * Instead of calculating all of the FIR filter outputs and discarding <code>M-1</code> out of every <code>M</code>, only the 00060 * samples output by the decimator are computed. 00061 * The functions operate on blocks of input and output data. 00062 * <code>pSrc</code> points to an array of <code>blockSize</code> input values and 00063 * <code>pDst</code> points to an array of <code>blockSize/M</code> output values. 00064 * In order to have an integer number of output samples <code>blockSize</code> 00065 * must always be a multiple of the decimation factor <code>M</code>. 00066 * 00067 * The library provides separate functions for Q15, Q31 and floating-point data types. 00068 * 00069 * \par Algorithm: 00070 * The FIR portion of the algorithm uses the standard form filter: 00071 * <pre> 00072 * y[n] = b[0] * x[n] + b[1] * x[n-1] + b[2] * x[n-2] + ...+ b[numTaps-1] * x[n-numTaps+1] 00073 * </pre> 00074 * where, <code>b[n]</code> are the filter coefficients. 00075 * \par 00076 * The <code>pCoeffs</code> points to a coefficient array of size <code>numTaps</code>. 00077 * Coefficients are stored in time reversed order. 00078 * \par 00079 * <pre> 00080 * {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]} 00081 * </pre> 00082 * \par 00083 * <code>pState</code> points to a state array of size <code>numTaps + blockSize - 1</code>. 00084 * Samples in the state buffer are stored in the order: 00085 * \par 00086 * <pre> 00087 * {x[n-numTaps+1], x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2]....x[0], x[1], ..., x[blockSize-1]} 00088 * </pre> 00089 * The state variables are updated after each block of data is processed, the coefficients are untouched. 00090 * 00091 * \par Instance Structure 00092 * The coefficients and state variables for a filter are stored together in an instance data structure. 00093 * A separate instance structure must be defined for each filter. 00094 * Coefficient arrays may be shared among several instances while state variable array should be allocated separately. 00095 * There are separate instance structure declarations for each of the 3 supported data types. 00096 * 00097 * \par Initialization Functions 00098 * There is also an associated initialization function for each data type. 00099 * The initialization function performs the following operations: 00100 * - Sets the values of the internal structure fields. 00101 * - Zeros out the values in the state buffer. 00102 * - Checks to make sure that the size of the input is a multiple of the decimation factor. 00103 * To do this manually without calling the init function, assign the follow subfields of the instance structure: 00104 * numTaps, pCoeffs, M (decimation factor), pState. Also set all of the values in pState to zero. 00105 * 00106 * \par 00107 * Use of the initialization function is optional. 00108 * However, if the initialization function is used, then the instance structure cannot be placed into a const data section. 00109 * To place an instance structure into a const data section, the instance structure must be manually initialized. 00110 * The code below statically initializes each of the 3 different data type filter instance structures 00111 * <pre> 00112 *arm_fir_decimate_instance_f32 S = {M, numTaps, pCoeffs, pState}; 00113 *arm_fir_decimate_instance_q31 S = {M, numTaps, pCoeffs, pState}; 00114 *arm_fir_decimate_instance_q15 S = {M, numTaps, pCoeffs, pState}; 00115 * </pre> 00116 * where <code>M</code> is the decimation factor; <code>numTaps</code> is the number of filter coefficients in the filter; 00117 * <code>pCoeffs</code> is the address of the coefficient buffer; 00118 * <code>pState</code> is the address of the state buffer. 00119 * Be sure to set the values in the state buffer to zeros when doing static initialization. 00120 * 00121 * \par Fixed-Point Behavior 00122 * Care must be taken when using the fixed-point versions of the FIR decimate filter functions. 00123 * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. 00124 * Refer to the function specific documentation below for usage guidelines. 00125 */ 00126 00127 /** 00128 * @addtogroup FIR_decimate 00129 * @{ 00130 */ 00131 00132 /** 00133 * @brief Processing function for the floating-point FIR decimator. 00134 * @param[in] *S points to an instance of the floating-point FIR decimator structure. 00135 * @param[in] *pSrc points to the block of input data. 00136 * @param[out] *pDst points to the block of output data. 00137 * @param[in] blockSize number of input samples to process per call. 00138 * @return none. 00139 */ 00140 00141 void arm_fir_decimate_f32( 00142 const arm_fir_decimate_instance_f32 * S, 00143 float32_t * pSrc, 00144 float32_t * pDst, 00145 uint32_t blockSize) 00146 { 00147 float32_t *pState = S->pState; /* State pointer */ 00148 float32_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ 00149 float32_t *pStateCurnt; /* Points to the current sample of the state */ 00150 float32_t *px, *pb; /* Temporary pointers for state and coefficient buffers */ 00151 float32_t sum0; /* Accumulator */ 00152 float32_t x0, c0; /* Temporary variables to hold state and coefficient values */ 00153 uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ 00154 uint32_t i, tapCnt, blkCnt, outBlockSize = blockSize / S->M; /* Loop counters */ 00155 00156 #ifndef ARM_MATH_CM0_FAMILY 00157 00158 uint32_t blkCntN4; 00159 float32_t *px0, *px1, *px2, *px3; 00160 float32_t acc0, acc1, acc2, acc3; 00161 float32_t x1, x2, x3; 00162 00163 /* Run the below code for Cortex-M4 and Cortex-M3 */ 00164 00165 /* S->pState buffer contains previous frame (numTaps - 1) samples */ 00166 /* pStateCurnt points to the location where the new input data should be written */ 00167 pStateCurnt = S->pState + (numTaps - 1u); 00168 00169 /* Total number of output samples to be computed */ 00170 blkCnt = outBlockSize / 4; 00171 blkCntN4 = outBlockSize - (4 * blkCnt); 00172 00173 while(blkCnt > 0u) 00174 { 00175 /* Copy 4 * decimation factor number of new input samples into the state buffer */ 00176 i = 4 * S->M; 00177 00178 do 00179 { 00180 *pStateCurnt++ = *pSrc++; 00181 00182 } while(--i); 00183 00184 /* Set accumulators to zero */ 00185 acc0 = 0.0f; 00186 acc1 = 0.0f; 00187 acc2 = 0.0f; 00188 acc3 = 0.0f; 00189 00190 /* Initialize state pointer for all the samples */ 00191 px0 = pState; 00192 px1 = pState + S->M; 00193 px2 = pState + 2 * S->M; 00194 px3 = pState + 3 * S->M; 00195 00196 /* Initialize coeff pointer */ 00197 pb = pCoeffs; 00198 00199 /* Loop unrolling. Process 4 taps at a time. */ 00200 tapCnt = numTaps >> 2; 00201 00202 /* Loop over the number of taps. Unroll by a factor of 4. 00203 ** Repeat until we've computed numTaps-4 coefficients. */ 00204 00205 while(tapCnt > 0u) 00206 { 00207 /* Read the b[numTaps-1] coefficient */ 00208 c0 = *(pb++); 00209 00210 /* Read x[n-numTaps-1] sample for acc0 */ 00211 x0 = *(px0++); 00212 /* Read x[n-numTaps-1] sample for acc1 */ 00213 x1 = *(px1++); 00214 /* Read x[n-numTaps-1] sample for acc2 */ 00215 x2 = *(px2++); 00216 /* Read x[n-numTaps-1] sample for acc3 */ 00217 x3 = *(px3++); 00218 00219 /* Perform the multiply-accumulate */ 00220 acc0 += x0 * c0; 00221 acc1 += x1 * c0; 00222 acc2 += x2 * c0; 00223 acc3 += x3 * c0; 00224 00225 /* Read the b[numTaps-2] coefficient */ 00226 c0 = *(pb++); 00227 00228 /* Read x[n-numTaps-2] sample for acc0, acc1, acc2, acc3 */ 00229 x0 = *(px0++); 00230 x1 = *(px1++); 00231 x2 = *(px2++); 00232 x3 = *(px3++); 00233 00234 /* Perform the multiply-accumulate */ 00235 acc0 += x0 * c0; 00236 acc1 += x1 * c0; 00237 acc2 += x2 * c0; 00238 acc3 += x3 * c0; 00239 00240 /* Read the b[numTaps-3] coefficient */ 00241 c0 = *(pb++); 00242 00243 /* Read x[n-numTaps-3] sample acc0, acc1, acc2, acc3 */ 00244 x0 = *(px0++); 00245 x1 = *(px1++); 00246 x2 = *(px2++); 00247 x3 = *(px3++); 00248 00249 /* Perform the multiply-accumulate */ 00250 acc0 += x0 * c0; 00251 acc1 += x1 * c0; 00252 acc2 += x2 * c0; 00253 acc3 += x3 * c0; 00254 00255 /* Read the b[numTaps-4] coefficient */ 00256 c0 = *(pb++); 00257 00258 /* Read x[n-numTaps-4] sample acc0, acc1, acc2, acc3 */ 00259 x0 = *(px0++); 00260 x1 = *(px1++); 00261 x2 = *(px2++); 00262 x3 = *(px3++); 00263 00264 /* Perform the multiply-accumulate */ 00265 acc0 += x0 * c0; 00266 acc1 += x1 * c0; 00267 acc2 += x2 * c0; 00268 acc3 += x3 * c0; 00269 00270 /* Decrement the loop counter */ 00271 tapCnt--; 00272 } 00273 00274 /* If the filter length is not a multiple of 4, compute the remaining filter taps */ 00275 tapCnt = numTaps % 0x4u; 00276 00277 while(tapCnt > 0u) 00278 { 00279 /* Read coefficients */ 00280 c0 = *(pb++); 00281 00282 /* Fetch state variables for acc0, acc1, acc2, acc3 */ 00283 x0 = *(px0++); 00284 x1 = *(px1++); 00285 x2 = *(px2++); 00286 x3 = *(px3++); 00287 00288 /* Perform the multiply-accumulate */ 00289 acc0 += x0 * c0; 00290 acc1 += x1 * c0; 00291 acc2 += x2 * c0; 00292 acc3 += x3 * c0; 00293 00294 /* Decrement the loop counter */ 00295 tapCnt--; 00296 } 00297 00298 /* Advance the state pointer by the decimation factor 00299 * to process the next group of decimation factor number samples */ 00300 pState = pState + 4 * S->M; 00301 00302 /* The result is in the accumulator, store in the destination buffer. */ 00303 *pDst++ = acc0; 00304 *pDst++ = acc1; 00305 *pDst++ = acc2; 00306 *pDst++ = acc3; 00307 00308 /* Decrement the loop counter */ 00309 blkCnt--; 00310 } 00311 00312 while(blkCntN4 > 0u) 00313 { 00314 /* Copy decimation factor number of new input samples into the state buffer */ 00315 i = S->M; 00316 00317 do 00318 { 00319 *pStateCurnt++ = *pSrc++; 00320 00321 } while(--i); 00322 00323 /* Set accumulator to zero */ 00324 sum0 = 0.0f; 00325 00326 /* Initialize state pointer */ 00327 px = pState; 00328 00329 /* Initialize coeff pointer */ 00330 pb = pCoeffs; 00331 00332 /* Loop unrolling. Process 4 taps at a time. */ 00333 tapCnt = numTaps >> 2; 00334 00335 /* Loop over the number of taps. Unroll by a factor of 4. 00336 ** Repeat until we've computed numTaps-4 coefficients. */ 00337 while(tapCnt > 0u) 00338 { 00339 /* Read the b[numTaps-1] coefficient */ 00340 c0 = *(pb++); 00341 00342 /* Read x[n-numTaps-1] sample */ 00343 x0 = *(px++); 00344 00345 /* Perform the multiply-accumulate */ 00346 sum0 += x0 * c0; 00347 00348 /* Read the b[numTaps-2] coefficient */ 00349 c0 = *(pb++); 00350 00351 /* Read x[n-numTaps-2] sample */ 00352 x0 = *(px++); 00353 00354 /* Perform the multiply-accumulate */ 00355 sum0 += x0 * c0; 00356 00357 /* Read the b[numTaps-3] coefficient */ 00358 c0 = *(pb++); 00359 00360 /* Read x[n-numTaps-3] sample */ 00361 x0 = *(px++); 00362 00363 /* Perform the multiply-accumulate */ 00364 sum0 += x0 * c0; 00365 00366 /* Read the b[numTaps-4] coefficient */ 00367 c0 = *(pb++); 00368 00369 /* Read x[n-numTaps-4] sample */ 00370 x0 = *(px++); 00371 00372 /* Perform the multiply-accumulate */ 00373 sum0 += x0 * c0; 00374 00375 /* Decrement the loop counter */ 00376 tapCnt--; 00377 } 00378 00379 /* If the filter length is not a multiple of 4, compute the remaining filter taps */ 00380 tapCnt = numTaps % 0x4u; 00381 00382 while(tapCnt > 0u) 00383 { 00384 /* Read coefficients */ 00385 c0 = *(pb++); 00386 00387 /* Fetch 1 state variable */ 00388 x0 = *(px++); 00389 00390 /* Perform the multiply-accumulate */ 00391 sum0 += x0 * c0; 00392 00393 /* Decrement the loop counter */ 00394 tapCnt--; 00395 } 00396 00397 /* Advance the state pointer by the decimation factor 00398 * to process the next group of decimation factor number samples */ 00399 pState = pState + S->M; 00400 00401 /* The result is in the accumulator, store in the destination buffer. */ 00402 *pDst++ = sum0; 00403 00404 /* Decrement the loop counter */ 00405 blkCntN4--; 00406 } 00407 00408 /* Processing is complete. 00409 ** Now copy the last numTaps - 1 samples to the satrt of the state buffer. 00410 ** This prepares the state buffer for the next function call. */ 00411 00412 /* Points to the start of the state buffer */ 00413 pStateCurnt = S->pState; 00414 00415 i = (numTaps - 1u) >> 2; 00416 00417 /* copy data */ 00418 while(i > 0u) 00419 { 00420 *pStateCurnt++ = *pState++; 00421 *pStateCurnt++ = *pState++; 00422 *pStateCurnt++ = *pState++; 00423 *pStateCurnt++ = *pState++; 00424 00425 /* Decrement the loop counter */ 00426 i--; 00427 } 00428 00429 i = (numTaps - 1u) % 0x04u; 00430 00431 /* copy data */ 00432 while(i > 0u) 00433 { 00434 *pStateCurnt++ = *pState++; 00435 00436 /* Decrement the loop counter */ 00437 i--; 00438 } 00439 00440 #else 00441 00442 /* Run the below code for Cortex-M0 */ 00443 00444 /* S->pState buffer contains previous frame (numTaps - 1) samples */ 00445 /* pStateCurnt points to the location where the new input data should be written */ 00446 pStateCurnt = S->pState + (numTaps - 1u); 00447 00448 /* Total number of output samples to be computed */ 00449 blkCnt = outBlockSize; 00450 00451 while(blkCnt > 0u) 00452 { 00453 /* Copy decimation factor number of new input samples into the state buffer */ 00454 i = S->M; 00455 00456 do 00457 { 00458 *pStateCurnt++ = *pSrc++; 00459 00460 } while(--i); 00461 00462 /* Set accumulator to zero */ 00463 sum0 = 0.0f; 00464 00465 /* Initialize state pointer */ 00466 px = pState; 00467 00468 /* Initialize coeff pointer */ 00469 pb = pCoeffs; 00470 00471 tapCnt = numTaps; 00472 00473 while(tapCnt > 0u) 00474 { 00475 /* Read coefficients */ 00476 c0 = *pb++; 00477 00478 /* Fetch 1 state variable */ 00479 x0 = *px++; 00480 00481 /* Perform the multiply-accumulate */ 00482 sum0 += x0 * c0; 00483 00484 /* Decrement the loop counter */ 00485 tapCnt--; 00486 } 00487 00488 /* Advance the state pointer by the decimation factor 00489 * to process the next group of decimation factor number samples */ 00490 pState = pState + S->M; 00491 00492 /* The result is in the accumulator, store in the destination buffer. */ 00493 *pDst++ = sum0; 00494 00495 /* Decrement the loop counter */ 00496 blkCnt--; 00497 } 00498 00499 /* Processing is complete. 00500 ** Now copy the last numTaps - 1 samples to the start of the state buffer. 00501 ** This prepares the state buffer for the next function call. */ 00502 00503 /* Points to the start of the state buffer */ 00504 pStateCurnt = S->pState; 00505 00506 /* Copy numTaps number of values */ 00507 i = (numTaps - 1u); 00508 00509 /* copy data */ 00510 while(i > 0u) 00511 { 00512 *pStateCurnt++ = *pState++; 00513 00514 /* Decrement the loop counter */ 00515 i--; 00516 } 00517 00518 #endif /* #ifndef ARM_MATH_CM0_FAMILY */ 00519 00520 } 00521 00522 /** 00523 * @} end of FIR_decimate group 00524 */
Generated on Tue Jul 12 2022 13:15:24 by
