A bundled STM32F10x Std Periph and CMSIS library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

426 lines
16 KiB

  1. /* ----------------------------------------------------------------------
  2. * Copyright (C) 2010-2014 ARM Limited. All rights reserved.
  3. *
  4. * $Date: 12. March 2014
  5. * $Revision: V1.4.4
  6. *
  7. * Project: CMSIS DSP Library
  8. * Title: arm_biquad_cascade_df1_f32.c
  9. *
  10. * Description: Processing function for the
  11. * floating-point Biquad cascade DirectFormI(DF1) filter.
  12. *
  13. * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
  14. *
  15. * Redistribution and use in source and binary forms, with or without
  16. * modification, are permitted provided that the following conditions
  17. * are met:
  18. * - Redistributions of source code must retain the above copyright
  19. * notice, this list of conditions and the following disclaimer.
  20. * - Redistributions in binary form must reproduce the above copyright
  21. * notice, this list of conditions and the following disclaimer in
  22. * the documentation and/or other materials provided with the
  23. * distribution.
  24. * - Neither the name of ARM LIMITED nor the names of its contributors
  25. * may be used to endorse or promote products derived from this
  26. * software without specific prior written permission.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  29. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  30. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  31. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  32. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  33. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  34. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  35. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  36. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  37. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  38. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  39. * POSSIBILITY OF SUCH DAMAGE.
  40. * -------------------------------------------------------------------- */
  41. #include "arm_math.h"
  42. /**
  43. * @ingroup groupFilters
  44. */
  45. /**
  46. * @defgroup BiquadCascadeDF1 Biquad Cascade IIR Filters Using Direct Form I Structure
  47. *
  48. * This set of functions implements arbitrary order recursive (IIR) filters.
  49. * The filters are implemented as a cascade of second order Biquad sections.
  50. * The functions support Q15, Q31 and floating-point data types.
  51. * Fast version of Q15 and Q31 also supported on CortexM4 and Cortex-M3.
  52. *
  53. * The functions operate on blocks of input and output data and each call to the function
  54. * processes <code>blockSize</code> samples through the filter.
  55. * <code>pSrc</code> points to the array of input data and
  56. * <code>pDst</code> points to the array of output data.
  57. * Both arrays contain <code>blockSize</code> values.
  58. *
  59. * \par Algorithm
  60. * Each Biquad stage implements a second order filter using the difference equation:
  61. * <pre>
  62. * y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]
  63. * </pre>
  64. * A Direct Form I algorithm is used with 5 coefficients and 4 state variables per stage.
  65. * \image html Biquad.gif "Single Biquad filter stage"
  66. * Coefficients <code>b0, b1 and b2 </code> multiply the input signal <code>x[n]</code> and are referred to as the feedforward coefficients.
  67. * Coefficients <code>a1</code> and <code>a2</code> multiply the output signal <code>y[n]</code> and are referred to as the feedback coefficients.
  68. * Pay careful attention to the sign of the feedback coefficients.
  69. * Some design tools use the difference equation
  70. * <pre>
  71. * y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2]
  72. * </pre>
  73. * In this case the feedback coefficients <code>a1</code> and <code>a2</code> must be negated when used with the CMSIS DSP Library.
  74. *
  75. * \par
  76. * Higher order filters are realized as a cascade of second order sections.
  77. * <code>numStages</code> refers to the number of second order stages used.
  78. * For example, an 8th order filter would be realized with <code>numStages=4</code> second order stages.
  79. * \image html BiquadCascade.gif "8th order filter using a cascade of Biquad stages"
  80. * A 9th order filter would be realized with <code>numStages=5</code> second order stages with the coefficients for one of the stages configured as a first order filter (<code>b2=0</code> and <code>a2=0</code>).
  81. *
  82. * \par
  83. * The <code>pState</code> points to state variables array.
  84. * Each Biquad stage has 4 state variables <code>x[n-1], x[n-2], y[n-1],</code> and <code>y[n-2]</code>.
  85. * The state variables are arranged in the <code>pState</code> array as:
  86. * <pre>
  87. * {x[n-1], x[n-2], y[n-1], y[n-2]}
  88. * </pre>
  89. *
  90. * \par
  91. * The 4 state variables for stage 1 are first, then the 4 state variables for stage 2, and so on.
  92. * The state array has a total length of <code>4*numStages</code> values.
  93. * The state variables are updated after each block of data is processed, the coefficients are untouched.
  94. *
  95. * \par Instance Structure
  96. * The coefficients and state variables for a filter are stored together in an instance data structure.
  97. * A separate instance structure must be defined for each filter.
  98. * Coefficient arrays may be shared among several instances while state variable arrays cannot be shared.
  99. * There are separate instance structure declarations for each of the 3 supported data types.
  100. *
  101. * \par Init Functions
  102. * There is also an associated initialization function for each data type.
  103. * The initialization function performs following operations:
  104. * - Sets the values of the internal structure fields.
  105. * - Zeros out the values in the state buffer.
  106. * To do this manually without calling the init function, assign the follow subfields of the instance structure:
  107. * numStages, pCoeffs, pState. Also set all of the values in pState to zero.
  108. *
  109. * \par
  110. * Use of the initialization function is optional.
  111. * However, if the initialization function is used, then the instance structure cannot be placed into a const data section.
  112. * To place an instance structure into a const data section, the instance structure must be manually initialized.
  113. * Set the values in the state buffer to zeros before static initialization.
  114. * The code below statically initializes each of the 3 different data type filter instance structures
  115. * <pre>
  116. * arm_biquad_casd_df1_inst_f32 S1 = {numStages, pState, pCoeffs};
  117. * arm_biquad_casd_df1_inst_q15 S2 = {numStages, pState, pCoeffs, postShift};
  118. * arm_biquad_casd_df1_inst_q31 S3 = {numStages, pState, pCoeffs, postShift};
  119. * </pre>
  120. * where <code>numStages</code> is the number of Biquad stages in the filter; <code>pState</code> is the address of the state buffer;
  121. * <code>pCoeffs</code> is the address of the coefficient buffer; <code>postShift</code> shift to be applied.
  122. *
  123. * \par Fixed-Point Behavior
  124. * Care must be taken when using the Q15 and Q31 versions of the Biquad Cascade filter functions.
  125. * Following issues must be considered:
  126. * - Scaling of coefficients
  127. * - Filter gain
  128. * - Overflow and saturation
  129. *
  130. * \par
  131. * <b>Scaling of coefficients: </b>
  132. * Filter coefficients are represented as fractional values and
  133. * coefficients are restricted to lie in the range <code>[-1 +1)</code>.
  134. * The fixed-point functions have an additional scaling parameter <code>postShift</code>
  135. * which allow the filter coefficients to exceed the range <code>[+1 -1)</code>.
  136. * At the output of the filter's accumulator is a shift register which shifts the result by <code>postShift</code> bits.
  137. * \image html BiquadPostshift.gif "Fixed-point Biquad with shift by postShift bits after accumulator"
  138. * This essentially scales the filter coefficients by <code>2^postShift</code>.
  139. * For example, to realize the coefficients
  140. * <pre>
  141. * {1.5, -0.8, 1.2, 1.6, -0.9}
  142. * </pre>
  143. * set the pCoeffs array to:
  144. * <pre>
  145. * {0.75, -0.4, 0.6, 0.8, -0.45}
  146. * </pre>
  147. * and set <code>postShift=1</code>
  148. *
  149. * \par
  150. * <b>Filter gain: </b>
  151. * The frequency response of a Biquad filter is a function of its coefficients.
  152. * It is possible for the gain through the filter to exceed 1.0 meaning that the filter increases the amplitude of certain frequencies.
  153. * This means that an input signal with amplitude < 1.0 may result in an output > 1.0 and these are saturated or overflowed based on the implementation of the filter.
  154. * To avoid this behavior the filter needs to be scaled down such that its peak gain < 1.0 or the input signal must be scaled down so that the combination of input and filter are never overflowed.
  155. *
  156. * \par
  157. * <b>Overflow and saturation: </b>
  158. * For Q15 and Q31 versions, it is described separately as part of the function specific documentation below.
  159. */
  160. /**
  161. * @addtogroup BiquadCascadeDF1
  162. * @{
  163. */
  164. /**
  165. * @param[in] *S points to an instance of the floating-point Biquad cascade structure.
  166. * @param[in] *pSrc points to the block of input data.
  167. * @param[out] *pDst points to the block of output data.
  168. * @param[in] blockSize number of samples to process per call.
  169. * @return none.
  170. *
  171. */
  172. void arm_biquad_cascade_df1_f32(
  173. const arm_biquad_casd_df1_inst_f32 * S,
  174. float32_t * pSrc,
  175. float32_t * pDst,
  176. uint32_t blockSize)
  177. {
  178. float32_t *pIn = pSrc; /* source pointer */
  179. float32_t *pOut = pDst; /* destination pointer */
  180. float32_t *pState = S->pState; /* pState pointer */
  181. float32_t *pCoeffs = S->pCoeffs; /* coefficient pointer */
  182. float32_t acc; /* Simulates the accumulator */
  183. float32_t b0, b1, b2, a1, a2; /* Filter coefficients */
  184. float32_t Xn1, Xn2, Yn1, Yn2; /* Filter pState variables */
  185. float32_t Xn; /* temporary input */
  186. uint32_t sample, stage = S->numStages; /* loop counters */
  187. #ifndef ARM_MATH_CM0_FAMILY
  188. /* Run the below code for Cortex-M4 and Cortex-M3 */
  189. do
  190. {
  191. /* Reading the coefficients */
  192. b0 = *pCoeffs++;
  193. b1 = *pCoeffs++;
  194. b2 = *pCoeffs++;
  195. a1 = *pCoeffs++;
  196. a2 = *pCoeffs++;
  197. /* Reading the pState values */
  198. Xn1 = pState[0];
  199. Xn2 = pState[1];
  200. Yn1 = pState[2];
  201. Yn2 = pState[3];
  202. /* Apply loop unrolling and compute 4 output values simultaneously. */
  203. /* The variable acc hold output values that are being computed:
  204. *
  205. * acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]
  206. * acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]
  207. * acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]
  208. * acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]
  209. */
  210. sample = blockSize >> 2u;
  211. /* First part of the processing with loop unrolling. Compute 4 outputs at a time.
  212. ** a second loop below computes the remaining 1 to 3 samples. */
  213. while(sample > 0u)
  214. {
  215. /* Read the first input */
  216. Xn = *pIn++;
  217. /* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
  218. Yn2 = (b0 * Xn) + (b1 * Xn1) + (b2 * Xn2) + (a1 * Yn1) + (a2 * Yn2);
  219. /* Store the result in the accumulator in the destination buffer. */
  220. *pOut++ = Yn2;
  221. /* Every time after the output is computed state should be updated. */
  222. /* The states should be updated as: */
  223. /* Xn2 = Xn1 */
  224. /* Xn1 = Xn */
  225. /* Yn2 = Yn1 */
  226. /* Yn1 = acc */
  227. /* Read the second input */
  228. Xn2 = *pIn++;
  229. /* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
  230. Yn1 = (b0 * Xn2) + (b1 * Xn) + (b2 * Xn1) + (a1 * Yn2) + (a2 * Yn1);
  231. /* Store the result in the accumulator in the destination buffer. */
  232. *pOut++ = Yn1;
  233. /* Every time after the output is computed state should be updated. */
  234. /* The states should be updated as: */
  235. /* Xn2 = Xn1 */
  236. /* Xn1 = Xn */
  237. /* Yn2 = Yn1 */
  238. /* Yn1 = acc */
  239. /* Read the third input */
  240. Xn1 = *pIn++;
  241. /* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
  242. Yn2 = (b0 * Xn1) + (b1 * Xn2) + (b2 * Xn) + (a1 * Yn1) + (a2 * Yn2);
  243. /* Store the result in the accumulator in the destination buffer. */
  244. *pOut++ = Yn2;
  245. /* Every time after the output is computed state should be updated. */
  246. /* The states should be updated as: */
  247. /* Xn2 = Xn1 */
  248. /* Xn1 = Xn */
  249. /* Yn2 = Yn1 */
  250. /* Yn1 = acc */
  251. /* Read the forth input */
  252. Xn = *pIn++;
  253. /* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
  254. Yn1 = (b0 * Xn) + (b1 * Xn1) + (b2 * Xn2) + (a1 * Yn2) + (a2 * Yn1);
  255. /* Store the result in the accumulator in the destination buffer. */
  256. *pOut++ = Yn1;
  257. /* Every time after the output is computed state should be updated. */
  258. /* The states should be updated as: */
  259. /* Xn2 = Xn1 */
  260. /* Xn1 = Xn */
  261. /* Yn2 = Yn1 */
  262. /* Yn1 = acc */
  263. Xn2 = Xn1;
  264. Xn1 = Xn;
  265. /* decrement the loop counter */
  266. sample--;
  267. }
  268. /* If the blockSize is not a multiple of 4, compute any remaining output samples here.
  269. ** No loop unrolling is used. */
  270. sample = blockSize & 0x3u;
  271. while(sample > 0u)
  272. {
  273. /* Read the input */
  274. Xn = *pIn++;
  275. /* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
  276. acc = (b0 * Xn) + (b1 * Xn1) + (b2 * Xn2) + (a1 * Yn1) + (a2 * Yn2);
  277. /* Store the result in the accumulator in the destination buffer. */
  278. *pOut++ = acc;
  279. /* Every time after the output is computed state should be updated. */
  280. /* The states should be updated as: */
  281. /* Xn2 = Xn1 */
  282. /* Xn1 = Xn */
  283. /* Yn2 = Yn1 */
  284. /* Yn1 = acc */
  285. Xn2 = Xn1;
  286. Xn1 = Xn;
  287. Yn2 = Yn1;
  288. Yn1 = acc;
  289. /* decrement the loop counter */
  290. sample--;
  291. }
  292. /* Store the updated state variables back into the pState array */
  293. *pState++ = Xn1;
  294. *pState++ = Xn2;
  295. *pState++ = Yn1;
  296. *pState++ = Yn2;
  297. /* The first stage goes from the input buffer to the output buffer. */
  298. /* Subsequent numStages occur in-place in the output buffer */
  299. pIn = pDst;
  300. /* Reset the output pointer */
  301. pOut = pDst;
  302. /* decrement the loop counter */
  303. stage--;
  304. } while(stage > 0u);
  305. #else
  306. /* Run the below code for Cortex-M0 */
  307. do
  308. {
  309. /* Reading the coefficients */
  310. b0 = *pCoeffs++;
  311. b1 = *pCoeffs++;
  312. b2 = *pCoeffs++;
  313. a1 = *pCoeffs++;
  314. a2 = *pCoeffs++;
  315. /* Reading the pState values */
  316. Xn1 = pState[0];
  317. Xn2 = pState[1];
  318. Yn1 = pState[2];
  319. Yn2 = pState[3];
  320. /* The variables acc holds the output value that is computed:
  321. * acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]
  322. */
  323. sample = blockSize;
  324. while(sample > 0u)
  325. {
  326. /* Read the input */
  327. Xn = *pIn++;
  328. /* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
  329. acc = (b0 * Xn) + (b1 * Xn1) + (b2 * Xn2) + (a1 * Yn1) + (a2 * Yn2);
  330. /* Store the result in the accumulator in the destination buffer. */
  331. *pOut++ = acc;
  332. /* Every time after the output is computed state should be updated. */
  333. /* The states should be updated as: */
  334. /* Xn2 = Xn1 */
  335. /* Xn1 = Xn */
  336. /* Yn2 = Yn1 */
  337. /* Yn1 = acc */
  338. Xn2 = Xn1;
  339. Xn1 = Xn;
  340. Yn2 = Yn1;
  341. Yn1 = acc;
  342. /* decrement the loop counter */
  343. sample--;
  344. }
  345. /* Store the updated state variables back into the pState array */
  346. *pState++ = Xn1;
  347. *pState++ = Xn2;
  348. *pState++ = Yn1;
  349. *pState++ = Yn2;
  350. /* The first stage goes from the input buffer to the output buffer. */
  351. /* Subsequent numStages occur in-place in the output buffer */
  352. pIn = pDst;
  353. /* Reset the output pointer */
  354. pOut = pDst;
  355. /* decrement the loop counter */
  356. stage--;
  357. } while(stage > 0u);
  358. #endif /* #ifndef ARM_MATH_CM0_FAMILY */
  359. }
  360. /**
  361. * @} end of BiquadCascadeDF1 group
  362. */