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_iir_lattice_q31.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_iir_lattice_q31.c 00009 * 00010 * Description: Q31 IIR lattice filter processing function. 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 IIR_Lattice 00049 * @{ 00050 */ 00051 00052 /** 00053 * @brief Processing function for the Q31 IIR lattice filter. 00054 * @param[in] *S points to an instance of the Q31 IIR lattice 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 samples to process. 00058 * @return none. 00059 * 00060 * @details 00061 * <b>Scaling and Overflow Behavior:</b> 00062 * \par 00063 * The function is implemented using an internal 64-bit accumulator. 00064 * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. 00065 * Thus, if the accumulator result overflows it wraps around rather than clip. 00066 * In order to avoid overflows completely the input signal must be scaled down by 2*log2(numStages) bits. 00067 * After all multiply-accumulates are performed, the 2.62 accumulator is saturated to 1.32 format and then truncated to 1.31 format. 00068 */ 00069 00070 void arm_iir_lattice_q31( 00071 const arm_iir_lattice_instance_q31 * S, 00072 q31_t * pSrc, 00073 q31_t * pDst, 00074 uint32_t blockSize) 00075 { 00076 q31_t fcurr, fnext = 0, gcurr = 0, gnext; /* Temporary variables for lattice stages */ 00077 q63_t acc; /* Accumlator */ 00078 uint32_t blkCnt, tapCnt; /* Temporary variables for counts */ 00079 q31_t *px1, *px2, *pk, *pv; /* Temporary pointers for state and coef */ 00080 uint32_t numStages = S->numStages; /* number of stages */ 00081 q31_t *pState; /* State pointer */ 00082 q31_t *pStateCurnt; /* State current pointer */ 00083 00084 blkCnt = blockSize; 00085 00086 pState = &S->pState[0]; 00087 00088 00089 #ifndef ARM_MATH_CM0_FAMILY 00090 00091 /* Run the below code for Cortex-M4 and Cortex-M3 */ 00092 00093 /* Sample processing */ 00094 while(blkCnt > 0u) 00095 { 00096 /* Read Sample from input buffer */ 00097 /* fN(n) = x(n) */ 00098 fcurr = *pSrc++; 00099 00100 /* Initialize state read pointer */ 00101 px1 = pState; 00102 /* Initialize state write pointer */ 00103 px2 = pState; 00104 /* Set accumulator to zero */ 00105 acc = 0; 00106 /* Initialize Ladder coeff pointer */ 00107 pv = &S->pvCoeffs[0]; 00108 /* Initialize Reflection coeff pointer */ 00109 pk = &S->pkCoeffs[0]; 00110 00111 00112 /* Process sample for first tap */ 00113 gcurr = *px1++; 00114 /* fN-1(n) = fN(n) - kN * gN-1(n-1) */ 00115 fnext = __QSUB(fcurr, (q31_t) (((q63_t) gcurr * (*pk)) >> 31)); 00116 /* gN(n) = kN * fN-1(n) + gN-1(n-1) */ 00117 gnext = __QADD(gcurr, (q31_t) (((q63_t) fnext * (*pk++)) >> 31)); 00118 /* write gN-1(n-1) into state for next sample processing */ 00119 *px2++ = gnext; 00120 /* y(n) += gN(n) * vN */ 00121 acc += ((q63_t) gnext * *pv++); 00122 00123 /* Update f values for next coefficient processing */ 00124 fcurr = fnext; 00125 00126 /* Loop unrolling. Process 4 taps at a time. */ 00127 tapCnt = (numStages - 1u) >> 2; 00128 00129 while(tapCnt > 0u) 00130 { 00131 00132 /* Process sample for 2nd, 6th .. taps */ 00133 /* Read gN-2(n-1) from state buffer */ 00134 gcurr = *px1++; 00135 /* fN-2(n) = fN-1(n) - kN-1 * gN-2(n-1) */ 00136 fnext = __QSUB(fcurr, (q31_t) (((q63_t) gcurr * (*pk)) >> 31)); 00137 /* gN-1(n) = kN-1 * fN-2(n) + gN-2(n-1) */ 00138 gnext = __QADD(gcurr, (q31_t) (((q63_t) fnext * (*pk++)) >> 31)); 00139 /* y(n) += gN-1(n) * vN-1 */ 00140 /* process for gN-5(n) * vN-5, gN-9(n) * vN-9 ... */ 00141 acc += ((q63_t) gnext * *pv++); 00142 /* write gN-1(n) into state for next sample processing */ 00143 *px2++ = gnext; 00144 00145 /* Process sample for 3nd, 7th ...taps */ 00146 /* Read gN-3(n-1) from state buffer */ 00147 gcurr = *px1++; 00148 /* Process sample for 3rd, 7th .. taps */ 00149 /* fN-3(n) = fN-2(n) - kN-2 * gN-3(n-1) */ 00150 fcurr = __QSUB(fnext, (q31_t) (((q63_t) gcurr * (*pk)) >> 31)); 00151 /* gN-2(n) = kN-2 * fN-3(n) + gN-3(n-1) */ 00152 gnext = __QADD(gcurr, (q31_t) (((q63_t) fcurr * (*pk++)) >> 31)); 00153 /* y(n) += gN-2(n) * vN-2 */ 00154 /* process for gN-6(n) * vN-6, gN-10(n) * vN-10 ... */ 00155 acc += ((q63_t) gnext * *pv++); 00156 /* write gN-2(n) into state for next sample processing */ 00157 *px2++ = gnext; 00158 00159 00160 /* Process sample for 4th, 8th ...taps */ 00161 /* Read gN-4(n-1) from state buffer */ 00162 gcurr = *px1++; 00163 /* Process sample for 4th, 8th .. taps */ 00164 /* fN-4(n) = fN-3(n) - kN-3 * gN-4(n-1) */ 00165 fnext = __QSUB(fcurr, (q31_t) (((q63_t) gcurr * (*pk)) >> 31)); 00166 /* gN-3(n) = kN-3 * fN-4(n) + gN-4(n-1) */ 00167 gnext = __QADD(gcurr, (q31_t) (((q63_t) fnext * (*pk++)) >> 31)); 00168 /* y(n) += gN-3(n) * vN-3 */ 00169 /* process for gN-7(n) * vN-7, gN-11(n) * vN-11 ... */ 00170 acc += ((q63_t) gnext * *pv++); 00171 /* write gN-3(n) into state for next sample processing */ 00172 *px2++ = gnext; 00173 00174 00175 /* Process sample for 5th, 9th ...taps */ 00176 /* Read gN-5(n-1) from state buffer */ 00177 gcurr = *px1++; 00178 /* Process sample for 5th, 9th .. taps */ 00179 /* fN-5(n) = fN-4(n) - kN-4 * gN-1(n-1) */ 00180 fcurr = __QSUB(fnext, (q31_t) (((q63_t) gcurr * (*pk)) >> 31)); 00181 /* gN-4(n) = kN-4 * fN-5(n) + gN-5(n-1) */ 00182 gnext = __QADD(gcurr, (q31_t) (((q63_t) fcurr * (*pk++)) >> 31)); 00183 /* y(n) += gN-4(n) * vN-4 */ 00184 /* process for gN-8(n) * vN-8, gN-12(n) * vN-12 ... */ 00185 acc += ((q63_t) gnext * *pv++); 00186 /* write gN-4(n) into state for next sample processing */ 00187 *px2++ = gnext; 00188 00189 tapCnt--; 00190 00191 } 00192 00193 fnext = fcurr; 00194 00195 /* If the filter length is not a multiple of 4, compute the remaining filter taps */ 00196 tapCnt = (numStages - 1u) % 0x4u; 00197 00198 while(tapCnt > 0u) 00199 { 00200 gcurr = *px1++; 00201 /* Process sample for last taps */ 00202 fnext = __QSUB(fcurr, (q31_t) (((q63_t) gcurr * (*pk)) >> 31)); 00203 gnext = __QADD(gcurr, (q31_t) (((q63_t) fnext * (*pk++)) >> 31)); 00204 /* Output samples for last taps */ 00205 acc += ((q63_t) gnext * *pv++); 00206 *px2++ = gnext; 00207 fcurr = fnext; 00208 00209 tapCnt--; 00210 00211 } 00212 00213 /* y(n) += g0(n) * v0 */ 00214 acc += (q63_t) fnext *( 00215 *pv++); 00216 00217 *px2++ = fnext; 00218 00219 /* write out into pDst */ 00220 *pDst++ = (q31_t) (acc >> 31u); 00221 00222 /* Advance the state pointer by 4 to process the next group of 4 samples */ 00223 pState = pState + 1u; 00224 blkCnt--; 00225 00226 } 00227 00228 /* Processing is complete. Now copy last S->numStages samples to start of the buffer 00229 for the preperation of next frame process */ 00230 00231 /* Points to the start of the state buffer */ 00232 pStateCurnt = &S->pState[0]; 00233 pState = &S->pState[blockSize]; 00234 00235 tapCnt = numStages >> 2u; 00236 00237 /* copy data */ 00238 while(tapCnt > 0u) 00239 { 00240 *pStateCurnt++ = *pState++; 00241 *pStateCurnt++ = *pState++; 00242 *pStateCurnt++ = *pState++; 00243 *pStateCurnt++ = *pState++; 00244 00245 /* Decrement the loop counter */ 00246 tapCnt--; 00247 00248 } 00249 00250 /* Calculate remaining number of copies */ 00251 tapCnt = (numStages) % 0x4u; 00252 00253 /* Copy the remaining q31_t data */ 00254 while(tapCnt > 0u) 00255 { 00256 *pStateCurnt++ = *pState++; 00257 00258 /* Decrement the loop counter */ 00259 tapCnt--; 00260 }; 00261 00262 #else 00263 00264 /* Run the below code for Cortex-M0 */ 00265 /* Sample processing */ 00266 while(blkCnt > 0u) 00267 { 00268 /* Read Sample from input buffer */ 00269 /* fN(n) = x(n) */ 00270 fcurr = *pSrc++; 00271 00272 /* Initialize state read pointer */ 00273 px1 = pState; 00274 /* Initialize state write pointer */ 00275 px2 = pState; 00276 /* Set accumulator to zero */ 00277 acc = 0; 00278 /* Initialize Ladder coeff pointer */ 00279 pv = &S->pvCoeffs[0]; 00280 /* Initialize Reflection coeff pointer */ 00281 pk = &S->pkCoeffs[0]; 00282 00283 tapCnt = numStages; 00284 00285 while(tapCnt > 0u) 00286 { 00287 gcurr = *px1++; 00288 /* Process sample */ 00289 /* fN-1(n) = fN(n) - kN * gN-1(n-1) */ 00290 fnext = 00291 clip_q63_to_q31(((q63_t) fcurr - 00292 ((q31_t) (((q63_t) gcurr * (*pk)) >> 31)))); 00293 /* gN(n) = kN * fN-1(n) + gN-1(n-1) */ 00294 gnext = 00295 clip_q63_to_q31(((q63_t) gcurr + 00296 ((q31_t) (((q63_t) fnext * (*pk++)) >> 31)))); 00297 /* Output samples */ 00298 /* y(n) += gN(n) * vN */ 00299 acc += ((q63_t) gnext * *pv++); 00300 /* write gN-1(n-1) into state for next sample processing */ 00301 *px2++ = gnext; 00302 /* Update f values for next coefficient processing */ 00303 fcurr = fnext; 00304 00305 tapCnt--; 00306 } 00307 00308 /* y(n) += g0(n) * v0 */ 00309 acc += (q63_t) fnext *( 00310 *pv++); 00311 00312 *px2++ = fnext; 00313 00314 /* write out into pDst */ 00315 *pDst++ = (q31_t) (acc >> 31u); 00316 00317 /* Advance the state pointer by 1 to process the next group of samples */ 00318 pState = pState + 1u; 00319 blkCnt--; 00320 00321 } 00322 00323 /* Processing is complete. Now copy last S->numStages samples to start of the buffer 00324 for the preperation of next frame process */ 00325 00326 /* Points to the start of the state buffer */ 00327 pStateCurnt = &S->pState[0]; 00328 pState = &S->pState[blockSize]; 00329 00330 tapCnt = numStages; 00331 00332 /* Copy the remaining q31_t data */ 00333 while(tapCnt > 0u) 00334 { 00335 *pStateCurnt++ = *pState++; 00336 00337 /* Decrement the loop counter */ 00338 tapCnt--; 00339 } 00340 00341 #endif /* #ifndef ARM_MATH_CM0_FAMILY */ 00342 00343 } 00344 00345 00346 00347 00348 /** 00349 * @} end of IIR_Lattice group 00350 */
Generated on Tue Jul 12 2022 13:15:25 by
