CMSIS DSP library

Dependents:   KL25Z_FFT_Demo Hat_Board_v5_1 KL25Z_FFT_Demo_tony KL25Z_FFT_Demo_tony ... more

Fork of mbed-dsp by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_fir_decimate_q31.c Source File

arm_fir_decimate_q31.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_decimate_q31.c    
00009 *    
00010 * Description:  Q31 FIR Decimator.    
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  * @addtogroup FIR_decimate    
00049  * @{    
00050  */
00051 
00052 /**    
00053  * @brief Processing function for the Q31 FIR decimator.    
00054  * @param[in] *S points to an instance of the Q31 FIR decimator structure.    
00055  * @param[in] *pSrc points to the block of input data.    
00056  * @param[out] *pDst points to the block of output data    
00057  * @param[in] blockSize number of input samples to process per call.    
00058  * @return none    
00059  *    
00060  * <b>Scaling and Overflow Behavior:</b>    
00061  * \par    
00062  * The function is implemented using an internal 64-bit accumulator.    
00063  * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit.    
00064  * Thus, if the accumulator result overflows it wraps around rather than clip.    
00065  * In order to avoid overflows completely the input signal must be scaled down by log2(numTaps) bits (where log2 is read as log to the base 2).    
00066  * After all multiply-accumulates are performed, the 2.62 accumulator is truncated to 1.32 format and then saturated to 1.31 format.    
00067  *    
00068  * \par    
00069  * Refer to the function <code>arm_fir_decimate_fast_q31()</code> for a faster but less precise implementation of this function for Cortex-M3 and Cortex-M4.    
00070  */
00071 
00072 void arm_fir_decimate_q31(
00073   const arm_fir_decimate_instance_q31 * S,
00074   q31_t * pSrc,
00075   q31_t * pDst,
00076   uint32_t blockSize)
00077 {
00078   q31_t *pState = S->pState;                     /* State pointer */
00079   q31_t *pCoeffs = S->pCoeffs;                   /* Coefficient pointer */
00080   q31_t *pStateCurnt;                            /* Points to the current sample of the state */
00081   q31_t x0, c0;                                  /* Temporary variables to hold state and coefficient values */
00082   q31_t *px;                                     /* Temporary pointers for state buffer */
00083   q31_t *pb;                                     /* Temporary pointers for coefficient buffer */
00084   q63_t sum0;                                    /* Accumulator */
00085   uint32_t numTaps = S->numTaps;                 /* Number of taps */
00086   uint32_t i, tapCnt, blkCnt, outBlockSize = blockSize / S->M;  /* Loop counters */
00087 
00088 
00089 #ifndef ARM_MATH_CM0_FAMILY
00090 
00091   /* Run the below code for Cortex-M4 and Cortex-M3 */
00092 
00093   /* S->pState buffer contains previous frame (numTaps - 1) samples */
00094   /* pStateCurnt points to the location where the new input data should be written */
00095   pStateCurnt = S->pState + (numTaps - 1u);
00096 
00097   /* Total number of output samples to be computed */
00098   blkCnt = outBlockSize;
00099 
00100   while(blkCnt > 0u)
00101   {
00102     /* Copy decimation factor number of new input samples into the state buffer */
00103     i = S->M;
00104 
00105     do
00106     {
00107       *pStateCurnt++ = *pSrc++;
00108 
00109     } while(--i);
00110 
00111     /* Set accumulator to zero */
00112     sum0 = 0;
00113 
00114     /* Initialize state pointer */
00115     px = pState;
00116 
00117     /* Initialize coeff pointer */
00118     pb = pCoeffs;
00119 
00120     /* Loop unrolling.  Process 4 taps at a time. */
00121     tapCnt = numTaps >> 2;
00122 
00123     /* Loop over the number of taps.  Unroll by a factor of 4.    
00124      ** Repeat until we've computed numTaps-4 coefficients. */
00125     while(tapCnt > 0u)
00126     {
00127       /* Read the b[numTaps-1] coefficient */
00128       c0 = *(pb++);
00129 
00130       /* Read x[n-numTaps-1] sample */
00131       x0 = *(px++);
00132 
00133       /* Perform the multiply-accumulate */
00134       sum0 += (q63_t) x0 *c0;
00135 
00136       /* Read the b[numTaps-2] coefficient */
00137       c0 = *(pb++);
00138 
00139       /* Read x[n-numTaps-2] sample */
00140       x0 = *(px++);
00141 
00142       /* Perform the multiply-accumulate */
00143       sum0 += (q63_t) x0 *c0;
00144 
00145       /* Read the b[numTaps-3] coefficient */
00146       c0 = *(pb++);
00147 
00148       /* Read x[n-numTaps-3] sample */
00149       x0 = *(px++);
00150 
00151       /* Perform the multiply-accumulate */
00152       sum0 += (q63_t) x0 *c0;
00153 
00154       /* Read the b[numTaps-4] coefficient */
00155       c0 = *(pb++);
00156 
00157       /* Read x[n-numTaps-4] sample */
00158       x0 = *(px++);
00159 
00160       /* Perform the multiply-accumulate */
00161       sum0 += (q63_t) x0 *c0;
00162 
00163       /* Decrement the loop counter */
00164       tapCnt--;
00165     }
00166 
00167     /* If the filter length is not a multiple of 4, compute the remaining filter taps */
00168     tapCnt = numTaps % 0x4u;
00169 
00170     while(tapCnt > 0u)
00171     {
00172       /* Read coefficients */
00173       c0 = *(pb++);
00174 
00175       /* Fetch 1 state variable */
00176       x0 = *(px++);
00177 
00178       /* Perform the multiply-accumulate */
00179       sum0 += (q63_t) x0 *c0;
00180 
00181       /* Decrement the loop counter */
00182       tapCnt--;
00183     }
00184 
00185     /* Advance the state pointer by the decimation factor    
00186      * to process the next group of decimation factor number samples */
00187     pState = pState + S->M;
00188 
00189     /* The result is in the accumulator, store in the destination buffer. */
00190     *pDst++ = (q31_t) (sum0 >> 31);
00191 
00192     /* Decrement the loop counter */
00193     blkCnt--;
00194   }
00195 
00196   /* Processing is complete.    
00197    ** Now copy the last numTaps - 1 samples to the satrt of the state buffer.    
00198    ** This prepares the state buffer for the next function call. */
00199 
00200   /* Points to the start of the state buffer */
00201   pStateCurnt = S->pState;
00202 
00203   i = (numTaps - 1u) >> 2u;
00204 
00205   /* copy data */
00206   while(i > 0u)
00207   {
00208     *pStateCurnt++ = *pState++;
00209     *pStateCurnt++ = *pState++;
00210     *pStateCurnt++ = *pState++;
00211     *pStateCurnt++ = *pState++;
00212 
00213     /* Decrement the loop counter */
00214     i--;
00215   }
00216 
00217   i = (numTaps - 1u) % 0x04u;
00218 
00219   /* copy data */
00220   while(i > 0u)
00221   {
00222     *pStateCurnt++ = *pState++;
00223 
00224     /* Decrement the loop counter */
00225     i--;
00226   }
00227 
00228 #else
00229 
00230 /* Run the below code for Cortex-M0 */
00231 
00232   /* S->pState buffer contains previous frame (numTaps - 1) samples */
00233   /* pStateCurnt points to the location where the new input data should be written */
00234   pStateCurnt = S->pState + (numTaps - 1u);
00235 
00236   /* Total number of output samples to be computed */
00237   blkCnt = outBlockSize;
00238 
00239   while(blkCnt > 0u)
00240   {
00241     /* Copy decimation factor number of new input samples into the state buffer */
00242     i = S->M;
00243 
00244     do
00245     {
00246       *pStateCurnt++ = *pSrc++;
00247 
00248     } while(--i);
00249 
00250     /* Set accumulator to zero */
00251     sum0 = 0;
00252 
00253     /* Initialize state pointer */
00254     px = pState;
00255 
00256     /* Initialize coeff pointer */
00257     pb = pCoeffs;
00258 
00259     tapCnt = numTaps;
00260 
00261     while(tapCnt > 0u)
00262     {
00263       /* Read coefficients */
00264       c0 = *pb++;
00265 
00266       /* Fetch 1 state variable */
00267       x0 = *px++;
00268 
00269       /* Perform the multiply-accumulate */
00270       sum0 += (q63_t) x0 *c0;
00271 
00272       /* Decrement the loop counter */
00273       tapCnt--;
00274     }
00275 
00276     /* Advance the state pointer by the decimation factor           
00277      * to process the next group of decimation factor number samples */
00278     pState = pState + S->M;
00279 
00280     /* The result is in the accumulator, store in the destination buffer. */
00281     *pDst++ = (q31_t) (sum0 >> 31);
00282 
00283     /* Decrement the loop counter */
00284     blkCnt--;
00285   }
00286 
00287   /* Processing is complete.         
00288    ** Now copy the last numTaps - 1 samples to the start of the state buffer.       
00289    ** This prepares the state buffer for the next function call. */
00290 
00291   /* Points to the start of the state buffer */
00292   pStateCurnt = S->pState;
00293 
00294   i = numTaps - 1u;
00295 
00296   /* copy data */
00297   while(i > 0u)
00298   {
00299     *pStateCurnt++ = *pState++;
00300 
00301     /* Decrement the loop counter */
00302     i--;
00303   }
00304 
00305 #endif /*   #ifndef ARM_MATH_CM0_FAMILY */
00306 
00307 }
00308 
00309 /**    
00310  * @} end of FIR_decimate group    
00311  */