Keyboard firmwares for Atmel AVR and Cortex-M
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

arm_fir_f32.c 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /* ----------------------------------------------------------------------
  2. * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
  3. *
  4. * $Date: 17. January 2013
  5. * $Revision: V1.4.1
  6. *
  7. * Project: CMSIS DSP Library
  8. * Title: arm_fir_f32.c
  9. *
  10. * Description: Floating-point FIR filter processing function.
  11. *
  12. * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions
  16. * are met:
  17. * - Redistributions of source code must retain the above copyright
  18. * notice, this list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright
  20. * notice, this list of conditions and the following disclaimer in
  21. * the documentation and/or other materials provided with the
  22. * distribution.
  23. * - Neither the name of ARM LIMITED nor the names of its contributors
  24. * may be used to endorse or promote products derived from this
  25. * software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  28. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  29. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  30. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  31. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  32. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  33. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  35. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  37. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGE.
  39. * -------------------------------------------------------------------- */
  40. #include "arm_math.h"
  41. /**
  42. * @ingroup groupFilters
  43. */
  44. /**
  45. * @defgroup FIR Finite Impulse Response (FIR) Filters
  46. *
  47. * This set of functions implements Finite Impulse Response (FIR) filters
  48. * for Q7, Q15, Q31, and floating-point data types. Fast versions of Q15 and Q31 are also provided.
  49. * The functions operate on blocks of input and output data and each call to the function processes
  50. * <code>blockSize</code> samples through the filter. <code>pSrc</code> and
  51. * <code>pDst</code> points to input and output arrays containing <code>blockSize</code> values.
  52. *
  53. * \par Algorithm:
  54. * The FIR filter algorithm is based upon a sequence of multiply-accumulate (MAC) operations.
  55. * Each filter coefficient <code>b[n]</code> is multiplied by a state variable which equals a previous input sample <code>x[n]</code>.
  56. * <pre>
  57. * y[n] = b[0] * x[n] + b[1] * x[n-1] + b[2] * x[n-2] + ...+ b[numTaps-1] * x[n-numTaps+1]
  58. * </pre>
  59. * \par
  60. * \image html FIR.gif "Finite Impulse Response filter"
  61. * \par
  62. * <code>pCoeffs</code> points to a coefficient array of size <code>numTaps</code>.
  63. * Coefficients are stored in time reversed order.
  64. * \par
  65. * <pre>
  66. * {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}
  67. * </pre>
  68. * \par
  69. * <code>pState</code> points to a state array of size <code>numTaps + blockSize - 1</code>.
  70. * Samples in the state buffer are stored in the following order.
  71. * \par
  72. * <pre>
  73. * {x[n-numTaps+1], x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2]....x[0], x[1], ..., x[blockSize-1]}
  74. * </pre>
  75. * \par
  76. * Note that the length of the state buffer exceeds the length of the coefficient array by <code>blockSize-1</code>.
  77. * The increased state buffer length allows circular addressing, which is traditionally used in the FIR filters,
  78. * to be avoided and yields a significant speed improvement.
  79. * The state variables are updated after each block of data is processed; the coefficients are untouched.
  80. * \par Instance Structure
  81. * The coefficients and state variables for a filter are stored together in an instance data structure.
  82. * A separate instance structure must be defined for each filter.
  83. * Coefficient arrays may be shared among several instances while state variable arrays cannot be shared.
  84. * There are separate instance structure declarations for each of the 4 supported data types.
  85. *
  86. * \par Initialization Functions
  87. * There is also an associated initialization function for each data type.
  88. * The initialization function performs the following operations:
  89. * - Sets the values of the internal structure fields.
  90. * - Zeros out the values in the state buffer.
  91. * To do this manually without calling the init function, assign the follow subfields of the instance structure:
  92. * numTaps, pCoeffs, pState. Also set all of the values in pState to zero.
  93. *
  94. * \par
  95. * Use of the initialization function is optional.
  96. * However, if the initialization function is used, then the instance structure cannot be placed into a const data section.
  97. * To place an instance structure into a const data section, the instance structure must be manually initialized.
  98. * Set the values in the state buffer to zeros before static initialization.
  99. * The code below statically initializes each of the 4 different data type filter instance structures
  100. * <pre>
  101. *arm_fir_instance_f32 S = {numTaps, pState, pCoeffs};
  102. *arm_fir_instance_q31 S = {numTaps, pState, pCoeffs};
  103. *arm_fir_instance_q15 S = {numTaps, pState, pCoeffs};
  104. *arm_fir_instance_q7 S = {numTaps, pState, pCoeffs};
  105. * </pre>
  106. *
  107. * where <code>numTaps</code> is the number of filter coefficients in the filter; <code>pState</code> is the address of the state buffer;
  108. * <code>pCoeffs</code> is the address of the coefficient buffer.
  109. *
  110. * \par Fixed-Point Behavior
  111. * Care must be taken when using the fixed-point versions of the FIR filter functions.
  112. * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered.
  113. * Refer to the function specific documentation below for usage guidelines.
  114. */
  115. /**
  116. * @addtogroup FIR
  117. * @{
  118. */
  119. /**
  120. *
  121. * @param[in] *S points to an instance of the floating-point FIR filter structure.
  122. * @param[in] *pSrc points to the block of input data.
  123. * @param[out] *pDst points to the block of output data.
  124. * @param[in] blockSize number of samples to process per call.
  125. * @return none.
  126. *
  127. */
  128. #ifndef ARM_MATH_CM0_FAMILY
  129. /* Run the below code for Cortex-M4 and Cortex-M3 */
  130. void arm_fir_f32(
  131. const arm_fir_instance_f32 * S,
  132. float32_t * pSrc,
  133. float32_t * pDst,
  134. uint32_t blockSize)
  135. {
  136. float32_t *pState = S->pState; /* State pointer */
  137. float32_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */
  138. float32_t *pStateCurnt; /* Points to the current sample of the state */
  139. float32_t *px, *pb; /* Temporary pointers for state and coefficient buffers */
  140. float32_t acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7; /* Accumulators */
  141. float32_t x0, x1, x2, x3, x4, x5, x6, x7, c0; /* Temporary variables to hold state and coefficient values */
  142. uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */
  143. uint32_t i, tapCnt, blkCnt; /* Loop counters */
  144. float32_t p0,p1,p2,p3,p4,p5,p6,p7; /* Temporary product values */
  145. /* S->pState points to state array which contains previous frame (numTaps - 1) samples */
  146. /* pStateCurnt points to the location where the new input data should be written */
  147. pStateCurnt = &(S->pState[(numTaps - 1u)]);
  148. /* Apply loop unrolling and compute 8 output values simultaneously.
  149. * The variables acc0 ... acc7 hold output values that are being computed:
  150. *
  151. * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0]
  152. * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1]
  153. * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2]
  154. * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3]
  155. */
  156. blkCnt = blockSize >> 3;
  157. /* First part of the processing with loop unrolling. Compute 8 outputs at a time.
  158. ** a second loop below computes the remaining 1 to 7 samples. */
  159. while(blkCnt > 0u)
  160. {
  161. /* Copy four new input samples into the state buffer */
  162. *pStateCurnt++ = *pSrc++;
  163. *pStateCurnt++ = *pSrc++;
  164. *pStateCurnt++ = *pSrc++;
  165. *pStateCurnt++ = *pSrc++;
  166. /* Set all accumulators to zero */
  167. acc0 = 0.0f;
  168. acc1 = 0.0f;
  169. acc2 = 0.0f;
  170. acc3 = 0.0f;
  171. acc4 = 0.0f;
  172. acc5 = 0.0f;
  173. acc6 = 0.0f;
  174. acc7 = 0.0f;
  175. /* Initialize state pointer */
  176. px = pState;
  177. /* Initialize coeff pointer */
  178. pb = (pCoeffs);
  179. /* This is separated from the others to avoid
  180. * a call to __aeabi_memmove which would be slower
  181. */
  182. *pStateCurnt++ = *pSrc++;
  183. *pStateCurnt++ = *pSrc++;
  184. *pStateCurnt++ = *pSrc++;
  185. *pStateCurnt++ = *pSrc++;
  186. /* Read the first seven samples from the state buffer: x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2] */
  187. x0 = *px++;
  188. x1 = *px++;
  189. x2 = *px++;
  190. x3 = *px++;
  191. x4 = *px++;
  192. x5 = *px++;
  193. x6 = *px++;
  194. /* Loop unrolling. Process 8 taps at a time. */
  195. tapCnt = numTaps >> 3u;
  196. /* Loop over the number of taps. Unroll by a factor of 8.
  197. ** Repeat until we've computed numTaps-8 coefficients. */
  198. while(tapCnt > 0u)
  199. {
  200. /* Read the b[numTaps-1] coefficient */
  201. c0 = *(pb++);
  202. /* Read x[n-numTaps-3] sample */
  203. x7 = *(px++);
  204. /* acc0 += b[numTaps-1] * x[n-numTaps] */
  205. p0 = x0 * c0;
  206. /* acc1 += b[numTaps-1] * x[n-numTaps-1] */
  207. p1 = x1 * c0;
  208. /* acc2 += b[numTaps-1] * x[n-numTaps-2] */
  209. p2 = x2 * c0;
  210. /* acc3 += b[numTaps-1] * x[n-numTaps-3] */
  211. p3 = x3 * c0;
  212. /* acc4 += b[numTaps-1] * x[n-numTaps-4] */
  213. p4 = x4 * c0;
  214. /* acc1 += b[numTaps-1] * x[n-numTaps-5] */
  215. p5 = x5 * c0;
  216. /* acc2 += b[numTaps-1] * x[n-numTaps-6] */
  217. p6 = x6 * c0;
  218. /* acc3 += b[numTaps-1] * x[n-numTaps-7] */
  219. p7 = x7 * c0;
  220. /* Read the b[numTaps-2] coefficient */
  221. c0 = *(pb++);
  222. /* Read x[n-numTaps-4] sample */
  223. x0 = *(px++);
  224. acc0 += p0;
  225. acc1 += p1;
  226. acc2 += p2;
  227. acc3 += p3;
  228. acc4 += p4;
  229. acc5 += p5;
  230. acc6 += p6;
  231. acc7 += p7;
  232. /* Perform the multiply-accumulate */
  233. p0 = x1 * c0;
  234. p1 = x2 * c0;
  235. p2 = x3 * c0;
  236. p3 = x4 * c0;
  237. p4 = x5 * c0;
  238. p5 = x6 * c0;
  239. p6 = x7 * c0;
  240. p7 = x0 * c0;
  241. /* Read the b[numTaps-3] coefficient */
  242. c0 = *(pb++);
  243. /* Read x[n-numTaps-5] sample */
  244. x1 = *(px++);
  245. acc0 += p0;
  246. acc1 += p1;
  247. acc2 += p2;
  248. acc3 += p3;
  249. acc4 += p4;
  250. acc5 += p5;
  251. acc6 += p6;
  252. acc7 += p7;
  253. /* Perform the multiply-accumulates */
  254. p0 = x2 * c0;
  255. p1 = x3 * c0;
  256. p2 = x4 * c0;
  257. p3 = x5 * c0;
  258. p4 = x6 * c0;
  259. p5 = x7 * c0;
  260. p6 = x0 * c0;
  261. p7 = x1 * c0;
  262. /* Read the b[numTaps-4] coefficient */
  263. c0 = *(pb++);
  264. /* Read x[n-numTaps-6] sample */
  265. x2 = *(px++);
  266. acc0 += p0;
  267. acc1 += p1;
  268. acc2 += p2;
  269. acc3 += p3;
  270. acc4 += p4;
  271. acc5 += p5;
  272. acc6 += p6;
  273. acc7 += p7;
  274. /* Perform the multiply-accumulates */
  275. p0 = x3 * c0;
  276. p1 = x4 * c0;
  277. p2 = x5 * c0;
  278. p3 = x6 * c0;
  279. p4 = x7 * c0;
  280. p5 = x0 * c0;
  281. p6 = x1 * c0;
  282. p7 = x2 * c0;
  283. /* Read the b[numTaps-4] coefficient */
  284. c0 = *(pb++);
  285. /* Read x[n-numTaps-6] sample */
  286. x3 = *(px++);
  287. acc0 += p0;
  288. acc1 += p1;
  289. acc2 += p2;
  290. acc3 += p3;
  291. acc4 += p4;
  292. acc5 += p5;
  293. acc6 += p6;
  294. acc7 += p7;
  295. /* Perform the multiply-accumulates */
  296. p0 = x4 * c0;
  297. p1 = x5 * c0;
  298. p2 = x6 * c0;
  299. p3 = x7 * c0;
  300. p4 = x0 * c0;
  301. p5 = x1 * c0;
  302. p6 = x2 * c0;
  303. p7 = x3 * c0;
  304. /* Read the b[numTaps-4] coefficient */
  305. c0 = *(pb++);
  306. /* Read x[n-numTaps-6] sample */
  307. x4 = *(px++);
  308. acc0 += p0;
  309. acc1 += p1;
  310. acc2 += p2;
  311. acc3 += p3;
  312. acc4 += p4;
  313. acc5 += p5;
  314. acc6 += p6;
  315. acc7 += p7;
  316. /* Perform the multiply-accumulates */
  317. p0 = x5 * c0;
  318. p1 = x6 * c0;
  319. p2 = x7 * c0;
  320. p3 = x0 * c0;
  321. p4 = x1 * c0;
  322. p5 = x2 * c0;
  323. p6 = x3 * c0;
  324. p7 = x4 * c0;
  325. /* Read the b[numTaps-4] coefficient */
  326. c0 = *(pb++);
  327. /* Read x[n-numTaps-6] sample */
  328. x5 = *(px++);
  329. acc0 += p0;
  330. acc1 += p1;
  331. acc2 += p2;
  332. acc3 += p3;
  333. acc4 += p4;
  334. acc5 += p5;
  335. acc6 += p6;
  336. acc7 += p7;
  337. /* Perform the multiply-accumulates */
  338. p0 = x6 * c0;
  339. p1 = x7 * c0;
  340. p2 = x0 * c0;
  341. p3 = x1 * c0;
  342. p4 = x2 * c0;
  343. p5 = x3 * c0;
  344. p6 = x4 * c0;
  345. p7 = x5 * c0;
  346. /* Read the b[numTaps-4] coefficient */
  347. c0 = *(pb++);
  348. /* Read x[n-numTaps-6] sample */
  349. x6 = *(px++);
  350. acc0 += p0;
  351. acc1 += p1;
  352. acc2 += p2;
  353. acc3 += p3;
  354. acc4 += p4;
  355. acc5 += p5;
  356. acc6 += p6;
  357. acc7 += p7;
  358. /* Perform the multiply-accumulates */
  359. p0 = x7 * c0;
  360. p1 = x0 * c0;
  361. p2 = x1 * c0;
  362. p3 = x2 * c0;
  363. p4 = x3 * c0;
  364. p5 = x4 * c0;
  365. p6 = x5 * c0;
  366. p7 = x6 * c0;
  367. tapCnt--;
  368. acc0 += p0;
  369. acc1 += p1;
  370. acc2 += p2;
  371. acc3 += p3;
  372. acc4 += p4;
  373. acc5 += p5;
  374. acc6 += p6;
  375. acc7 += p7;
  376. }
  377. /* If the filter length is not a multiple of 8, compute the remaining filter taps */
  378. tapCnt = numTaps % 0x8u;
  379. while(tapCnt > 0u)
  380. {
  381. /* Read coefficients */
  382. c0 = *(pb++);
  383. /* Fetch 1 state variable */
  384. x7 = *(px++);
  385. /* Perform the multiply-accumulates */
  386. p0 = x0 * c0;
  387. p1 = x1 * c0;
  388. p2 = x2 * c0;
  389. p3 = x3 * c0;
  390. p4 = x4 * c0;
  391. p5 = x5 * c0;
  392. p6 = x6 * c0;
  393. p7 = x7 * c0;
  394. /* Reuse the present sample states for next sample */
  395. x0 = x1;
  396. x1 = x2;
  397. x2 = x3;
  398. x3 = x4;
  399. x4 = x5;
  400. x5 = x6;
  401. x6 = x7;
  402. acc0 += p0;
  403. acc1 += p1;
  404. acc2 += p2;
  405. acc3 += p3;
  406. acc4 += p4;
  407. acc5 += p5;
  408. acc6 += p6;
  409. acc7 += p7;
  410. /* Decrement the loop counter */
  411. tapCnt--;
  412. }
  413. /* Advance the state pointer by 8 to process the next group of 8 samples */
  414. pState = pState + 8;
  415. /* The results in the 8 accumulators, store in the destination buffer. */
  416. *pDst++ = acc0;
  417. *pDst++ = acc1;
  418. *pDst++ = acc2;
  419. *pDst++ = acc3;
  420. *pDst++ = acc4;
  421. *pDst++ = acc5;
  422. *pDst++ = acc6;
  423. *pDst++ = acc7;
  424. blkCnt--;
  425. }
  426. /* If the blockSize is not a multiple of 8, compute any remaining output samples here.
  427. ** No loop unrolling is used. */
  428. blkCnt = blockSize % 0x8u;
  429. while(blkCnt > 0u)
  430. {
  431. /* Copy one sample at a time into state buffer */
  432. *pStateCurnt++ = *pSrc++;
  433. /* Set the accumulator to zero */
  434. acc0 = 0.0f;
  435. /* Initialize state pointer */
  436. px = pState;
  437. /* Initialize Coefficient pointer */
  438. pb = (pCoeffs);
  439. i = numTaps;
  440. /* Perform the multiply-accumulates */
  441. do
  442. {
  443. acc0 += *px++ * *pb++;
  444. i--;
  445. } while(i > 0u);
  446. /* The result is store in the destination buffer. */
  447. *pDst++ = acc0;
  448. /* Advance state pointer by 1 for the next sample */
  449. pState = pState + 1;
  450. blkCnt--;
  451. }
  452. /* Processing is complete.
  453. ** Now copy the last numTaps - 1 samples to the start of the state buffer.
  454. ** This prepares the state buffer for the next function call. */
  455. /* Points to the start of the state buffer */
  456. pStateCurnt = S->pState;
  457. tapCnt = (numTaps - 1u) >> 2u;
  458. /* copy data */
  459. while(tapCnt > 0u)
  460. {
  461. *pStateCurnt++ = *pState++;
  462. *pStateCurnt++ = *pState++;
  463. *pStateCurnt++ = *pState++;
  464. *pStateCurnt++ = *pState++;
  465. /* Decrement the loop counter */
  466. tapCnt--;
  467. }
  468. /* Calculate remaining number of copies */
  469. tapCnt = (numTaps - 1u) % 0x4u;
  470. /* Copy the remaining q31_t data */
  471. while(tapCnt > 0u)
  472. {
  473. *pStateCurnt++ = *pState++;
  474. /* Decrement the loop counter */
  475. tapCnt--;
  476. }
  477. }
  478. #else
  479. void arm_fir_f32(
  480. const arm_fir_instance_f32 * S,
  481. float32_t * pSrc,
  482. float32_t * pDst,
  483. uint32_t blockSize)
  484. {
  485. float32_t *pState = S->pState; /* State pointer */
  486. float32_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */
  487. float32_t *pStateCurnt; /* Points to the current sample of the state */
  488. float32_t *px, *pb; /* Temporary pointers for state and coefficient buffers */
  489. uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */
  490. uint32_t i, tapCnt, blkCnt; /* Loop counters */
  491. /* Run the below code for Cortex-M0 */
  492. float32_t acc;
  493. /* S->pState points to state array which contains previous frame (numTaps - 1) samples */
  494. /* pStateCurnt points to the location where the new input data should be written */
  495. pStateCurnt = &(S->pState[(numTaps - 1u)]);
  496. /* Initialize blkCnt with blockSize */
  497. blkCnt = blockSize;
  498. while(blkCnt > 0u)
  499. {
  500. /* Copy one sample at a time into state buffer */
  501. *pStateCurnt++ = *pSrc++;
  502. /* Set the accumulator to zero */
  503. acc = 0.0f;
  504. /* Initialize state pointer */
  505. px = pState;
  506. /* Initialize Coefficient pointer */
  507. pb = pCoeffs;
  508. i = numTaps;
  509. /* Perform the multiply-accumulates */
  510. do
  511. {
  512. /* acc = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] */
  513. acc += *px++ * *pb++;
  514. i--;
  515. } while(i > 0u);
  516. /* The result is store in the destination buffer. */
  517. *pDst++ = acc;
  518. /* Advance state pointer by 1 for the next sample */
  519. pState = pState + 1;
  520. blkCnt--;
  521. }
  522. /* Processing is complete.
  523. ** Now copy the last numTaps - 1 samples to the starting of the state buffer.
  524. ** This prepares the state buffer for the next function call. */
  525. /* Points to the start of the state buffer */
  526. pStateCurnt = S->pState;
  527. /* Copy numTaps number of values */
  528. tapCnt = numTaps - 1u;
  529. /* Copy data */
  530. while(tapCnt > 0u)
  531. {
  532. *pStateCurnt++ = *pState++;
  533. /* Decrement the loop counter */
  534. tapCnt--;
  535. }
  536. }
  537. #endif /* #ifndef ARM_MATH_CM0_FAMILY */
  538. /**
  539. * @} end of FIR group
  540. */