CMSIS DSP Library from CMSIS 2.0. See http://www.onarm.com/cmsis/ for full details
Dependents: K22F_DSP_Matrix_least_square BNO055-ELEC3810 1BNO055 ECE4180Project--Slave2 ... more
arm_biquad_cascade_df1_q31.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_biquad_cascade_df1_q31.c 00009 * 00010 * Description: Processing function for the 00011 * Q31 Biquad cascade filter 00012 * 00013 * Target Processor: Cortex-M4/Cortex-M3 00014 * 00015 * Version 1.0.3 2010/11/29 00016 * Re-organized the CMSIS folders and updated documentation. 00017 * 00018 * Version 1.0.2 2010/11/11 00019 * Documentation updated. 00020 * 00021 * Version 1.0.1 2010/10/05 00022 * Production release and review comments incorporated. 00023 * 00024 * Version 1.0.0 2010/09/20 00025 * Production release and review comments incorporated. 00026 * 00027 * Version 0.0.5 2010/04/26 00028 * incorporated review comments and updated with latest CMSIS layer 00029 * 00030 * Version 0.0.3 2010/03/10 00031 * Initial version 00032 * -------------------------------------------------------------------- */ 00033 00034 #include "arm_math.h" 00035 00036 /** 00037 * @ingroup groupFilters 00038 */ 00039 00040 /** 00041 * @addtogroup BiquadCascadeDF1 00042 * @{ 00043 */ 00044 00045 /** 00046 * @brief Processing function for the Q31 Biquad cascade filter. 00047 * @param[in] *S points to an instance of the Q31 Biquad cascade structure. 00048 * @param[in] *pSrc points to the block of input data. 00049 * @param[out] *pDst points to the block of output data. 00050 * @param[in] blockSize number of samples to process per call. 00051 * @return none. 00052 * 00053 * <b>Scaling and Overflow Behavior:</b> 00054 * \par 00055 * The function is implemented using an internal 64-bit accumulator. 00056 * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. 00057 * Thus, if the accumulator result overflows it wraps around rather than clip. 00058 * In order to avoid overflows completely the input signal must be scaled down by 2 bits and lie in the range [-0.25 +0.25). 00059 * After all 5 multiply-accumulates are performed, the 2.62 accumulator is shifted by <code>postShift</code> bits and the result truncated to 00060 * 1.31 format by discarding the low 32 bits. 00061 * 00062 * \par 00063 * Refer to the function <code>arm_biquad_cascade_df1_fast_q31()</code> for a faster but less precise implementation of this filter. 00064 */ 00065 00066 void arm_biquad_cascade_df1_q31( 00067 const arm_biquad_casd_df1_inst_q31 * S, 00068 q31_t * pSrc, 00069 q31_t * pDst, 00070 uint32_t blockSize) 00071 { 00072 q31_t *pIn = pSrc; /* input pointer initialization */ 00073 q31_t *pOut = pDst; /* output pointer initialization */ 00074 q31_t *pState = S->pState; /* pState pointer initialization */ 00075 q31_t *pCoeffs = S->pCoeffs; /* coeff pointer initialization */ 00076 q63_t acc; /* accumulator */ 00077 q31_t Xn1, Xn2, Yn1, Yn2; /* Filter state variables */ 00078 q31_t b0, b1, b2, a1, a2; /* Filter coefficients */ 00079 q31_t Xn; /* temporary input */ 00080 uint32_t shift = 32u - ((uint32_t) S->postShift + 1u); /* Shift to be applied to the output */ 00081 uint32_t sample, stage = S->numStages; /* loop counters */ 00082 00083 00084 do 00085 { 00086 /* Reading the coefficients */ 00087 b0 = *pCoeffs++; 00088 b1 = *pCoeffs++; 00089 b2 = *pCoeffs++; 00090 a1 = *pCoeffs++; 00091 a2 = *pCoeffs++; 00092 00093 /* Reading the state values */ 00094 Xn1 = pState[0]; 00095 Xn2 = pState[1]; 00096 Yn1 = pState[2]; 00097 Yn2 = pState[3]; 00098 00099 /* Apply loop unrolling and compute 4 output values simultaneously. */ 00100 /* The variable acc hold output values that are being computed: 00101 * 00102 * acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] 00103 */ 00104 00105 sample = blockSize >> 2u; 00106 00107 /* First part of the processing with loop unrolling. Compute 4 outputs at a time. 00108 ** a second loop below computes the remaining 1 to 3 samples. */ 00109 while(sample > 0u) 00110 { 00111 /* Read the input */ 00112 Xn = *pIn++; 00113 00114 /* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */ 00115 00116 /* acc = b0 * x[n] */ 00117 acc = (q63_t) b0 *Xn; 00118 /* acc += b1 * x[n-1] */ 00119 acc += (q63_t) b1 *Xn1; 00120 /* acc += b[2] * x[n-2] */ 00121 acc += (q63_t) b2 *Xn2; 00122 /* acc += a1 * y[n-1] */ 00123 acc += (q63_t) a1 *Yn1; 00124 /* acc += a2 * y[n-2] */ 00125 acc += (q63_t) a2 *Yn2; 00126 00127 /* The result is converted to 1.31 , Yn2 variable is reused */ 00128 Yn2 = (q31_t) (acc >> shift); 00129 00130 /* Store the output in the destination buffer. */ 00131 *pOut++ = Yn2; 00132 00133 /* Read the second input */ 00134 Xn2 = *pIn++; 00135 00136 /* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */ 00137 00138 /* acc = b0 * x[n] */ 00139 acc = (q63_t) b0 *Xn2; 00140 /* acc += b1 * x[n-1] */ 00141 acc += (q63_t) b1 *Xn; 00142 /* acc += b[2] * x[n-2] */ 00143 acc += (q63_t) b2 *Xn1; 00144 /* acc += a1 * y[n-1] */ 00145 acc += (q63_t) a1 *Yn2; 00146 /* acc += a2 * y[n-2] */ 00147 acc += (q63_t) a2 *Yn1; 00148 00149 00150 /* The result is converted to 1.31, Yn1 variable is reused */ 00151 Yn1 = (q31_t) (acc >> shift); 00152 00153 /* Store the output in the destination buffer. */ 00154 *pOut++ = Yn1; 00155 00156 /* Read the third input */ 00157 Xn1 = *pIn++; 00158 00159 /* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */ 00160 00161 /* acc = b0 * x[n] */ 00162 acc = (q63_t) b0 *Xn1; 00163 /* acc += b1 * x[n-1] */ 00164 acc += (q63_t) b1 *Xn2; 00165 /* acc += b[2] * x[n-2] */ 00166 acc += (q63_t) b2 *Xn; 00167 /* acc += a1 * y[n-1] */ 00168 acc += (q63_t) a1 *Yn1; 00169 /* acc += a2 * y[n-2] */ 00170 acc += (q63_t) a2 *Yn2; 00171 00172 /* The result is converted to 1.31, Yn2 variable is reused */ 00173 Yn2 = (q31_t) (acc >> shift); 00174 00175 /* Store the output in the destination buffer. */ 00176 *pOut++ = Yn2; 00177 00178 /* Read the forth input */ 00179 Xn = *pIn++; 00180 00181 /* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */ 00182 00183 /* acc = b0 * x[n] */ 00184 acc = (q63_t) b0 *Xn; 00185 /* acc += b1 * x[n-1] */ 00186 acc += (q63_t) b1 *Xn1; 00187 /* acc += b[2] * x[n-2] */ 00188 acc += (q63_t) b2 *Xn2; 00189 /* acc += a1 * y[n-1] */ 00190 acc += (q63_t) a1 *Yn2; 00191 /* acc += a2 * y[n-2] */ 00192 acc += (q63_t) a2 *Yn1; 00193 00194 /* The result is converted to 1.31, Yn1 variable is reused */ 00195 Yn1 = (q31_t) (acc >> shift); 00196 00197 /* Every time after the output is computed state should be updated. */ 00198 /* The states should be updated as: */ 00199 /* Xn2 = Xn1 */ 00200 /* Xn1 = Xn */ 00201 /* Yn2 = Yn1 */ 00202 /* Yn1 = acc */ 00203 Xn2 = Xn1; 00204 Xn1 = Xn; 00205 00206 /* Store the output in the destination buffer. */ 00207 *pOut++ = Yn1; 00208 00209 /* decrement the loop counter */ 00210 sample--; 00211 } 00212 00213 /* If the blockSize is not a multiple of 4, compute any remaining output samples here. 00214 ** No loop unrolling is used. */ 00215 sample = (blockSize & 0x3u); 00216 00217 while(sample > 0u) 00218 { 00219 /* Read the input */ 00220 Xn = *pIn++; 00221 00222 /* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */ 00223 00224 /* acc = b0 * x[n] */ 00225 acc = (q63_t) b0 *Xn; 00226 /* acc += b1 * x[n-1] */ 00227 acc += (q63_t) b1 *Xn1; 00228 /* acc += b[2] * x[n-2] */ 00229 acc += (q63_t) b2 *Xn2; 00230 /* acc += a1 * y[n-1] */ 00231 acc += (q63_t) a1 *Yn1; 00232 /* acc += a2 * y[n-2] */ 00233 acc += (q63_t) a2 *Yn2; 00234 00235 /* The result is converted to 1.31 */ 00236 acc = acc >> shift; 00237 00238 /* Every time after the output is computed state should be updated. */ 00239 /* The states should be updated as: */ 00240 /* Xn2 = Xn1 */ 00241 /* Xn1 = Xn */ 00242 /* Yn2 = Yn1 */ 00243 /* Yn1 = acc */ 00244 Xn2 = Xn1; 00245 Xn1 = Xn; 00246 Yn2 = Yn1; 00247 Yn1 = (q31_t) acc; 00248 00249 /* Store the output in the destination buffer. */ 00250 *pOut++ = (q31_t) acc; 00251 00252 /* decrement the loop counter */ 00253 sample--; 00254 } 00255 00256 /* The first stage goes from the input buffer to the output buffer. */ 00257 /* Subsequent stages occur in-place in the output buffer */ 00258 pIn = pDst; 00259 00260 /* Reset to destination pointer */ 00261 pOut = pDst; 00262 00263 /* Store the updated state variables back into the pState array */ 00264 *pState++ = Xn1; 00265 *pState++ = Xn2; 00266 *pState++ = Yn1; 00267 *pState++ = Yn2; 00268 00269 } while(--stage); 00270 } 00271 00272 /** 00273 * @} end of BiquadCascadeDF1 group 00274 */
Generated on Tue Jul 12 2022 14:13:52 by 1.7.2