Keyboard firmwares for Atmel AVR and Cortex-M
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.

arm_biquad_cascade_df2T_f32.c 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /* ----------------------------------------------------------------------
  2. * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
  3. *
  4. * $Date: 17. January 2013
  5. *
  6. * Project: CMSIS DSP Library
  7. * Title: arm_biquad_cascade_df2T_f32.c
  8. *
  9. * Description: Processing function for the floating-point transposed
  10. * direct form II Biquad cascade filter.
  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 BiquadCascadeDF2T Biquad Cascade IIR Filters Using a Direct Form II Transposed Structure
  46. *
  47. * This set of functions implements arbitrary order recursive (IIR) filters using a transposed direct form II structure.
  48. * The filters are implemented as a cascade of second order Biquad sections.
  49. * These functions provide a slight memory savings as compared to the direct form I Biquad filter functions.
  50. * Only floating-point data is supported.
  51. *
  52. * This function operate on blocks of input and output data and each call to the function
  53. * processes <code>blockSize</code> samples through the filter.
  54. * <code>pSrc</code> points to the array of input data and
  55. * <code>pDst</code> points to the array of output data.
  56. * Both arrays contain <code>blockSize</code> values.
  57. *
  58. * \par Algorithm
  59. * Each Biquad stage implements a second order filter using the difference equation:
  60. * <pre>
  61. * y[n] = b0 * x[n] + d1
  62. * d1 = b1 * x[n] + a1 * y[n] + d2
  63. * d2 = b2 * x[n] + a2 * y[n]
  64. * </pre>
  65. * where d1 and d2 represent the two state values.
  66. *
  67. * \par
  68. * A Biquad filter using a transposed Direct Form II structure is shown below.
  69. * \image html BiquadDF2Transposed.gif "Single transposed Direct Form II Biquad"
  70. * Coefficients <code>b0, b1, and b2 </code> multiply the input signal <code>x[n]</code> and are referred to as the feedforward coefficients.
  71. * Coefficients <code>a1</code> and <code>a2</code> multiply the output signal <code>y[n]</code> and are referred to as the feedback coefficients.
  72. * Pay careful attention to the sign of the feedback coefficients.
  73. * Some design tools flip the sign of the feedback coefficients:
  74. * <pre>
  75. * y[n] = b0 * x[n] + d1;
  76. * d1 = b1 * x[n] - a1 * y[n] + d2;
  77. * d2 = b2 * x[n] - a2 * y[n];
  78. * </pre>
  79. * In this case the feedback coefficients <code>a1</code> and <code>a2</code> must be negated when used with the CMSIS DSP Library.
  80. *
  81. * \par
  82. * Higher order filters are realized as a cascade of second order sections.
  83. * <code>numStages</code> refers to the number of second order stages used.
  84. * For example, an 8th order filter would be realized with <code>numStages=4</code> second order stages.
  85. * A 9th order filter would be realized with <code>numStages=5</code> second order stages with the
  86. * coefficients for one of the stages configured as a first order filter (<code>b2=0</code> and <code>a2=0</code>).
  87. *
  88. * \par
  89. * <code>pState</code> points to the state variable array.
  90. * Each Biquad stage has 2 state variables <code>d1</code> and <code>d2</code>.
  91. * The state variables are arranged in the <code>pState</code> array as:
  92. * <pre>
  93. * {d11, d12, d21, d22, ...}
  94. * </pre>
  95. * where <code>d1x</code> refers to the state variables for the first Biquad and
  96. * <code>d2x</code> refers to the state variables for the second Biquad.
  97. * The state array has a total length of <code>2*numStages</code> values.
  98. * The state variables are updated after each block of data is processed; the coefficients are untouched.
  99. *
  100. * \par
  101. * The CMSIS library contains Biquad filters in both Direct Form I and transposed Direct Form II.
  102. * The advantage of the Direct Form I structure is that it is numerically more robust for fixed-point data types.
  103. * That is why the Direct Form I structure supports Q15 and Q31 data types.
  104. * The transposed Direct Form II structure, on the other hand, requires a wide dynamic range for the state variables <code>d1</code> and <code>d2</code>.
  105. * Because of this, the CMSIS library only has a floating-point version of the Direct Form II Biquad.
  106. * The advantage of the Direct Form II Biquad is that it requires half the number of state variables, 2 rather than 4, per Biquad stage.
  107. *
  108. * \par Instance Structure
  109. * The coefficients and state variables for a filter are stored together in an instance data structure.
  110. * A separate instance structure must be defined for each filter.
  111. * Coefficient arrays may be shared among several instances while state variable arrays cannot be shared.
  112. *
  113. * \par Init Functions
  114. * There is also an associated initialization function.
  115. * The initialization function performs following operations:
  116. * - Sets the values of the internal structure fields.
  117. * - Zeros out the values in the state buffer.
  118. * To do this manually without calling the init function, assign the follow subfields of the instance structure:
  119. * numStages, pCoeffs, pState. Also set all of the values in pState to zero.
  120. *
  121. * \par
  122. * Use of the initialization function is optional.
  123. * However, if the initialization function is used, then the instance structure cannot be placed into a const data section.
  124. * To place an instance structure into a const data section, the instance structure must be manually initialized.
  125. * Set the values in the state buffer to zeros before static initialization.
  126. * For example, to statically initialize the instance structure use
  127. * <pre>
  128. * arm_biquad_cascade_df2T_instance_f32 S1 = {numStages, pState, pCoeffs};
  129. * </pre>
  130. * where <code>numStages</code> is the number of Biquad stages in the filter; <code>pState</code> is the address of the state buffer.
  131. * <code>pCoeffs</code> is the address of the coefficient buffer;
  132. *
  133. */
  134. /**
  135. * @addtogroup BiquadCascadeDF2T
  136. * @{
  137. */
  138. /**
  139. * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter.
  140. * @param[in] *S points to an instance of the filter data structure.
  141. * @param[in] *pSrc points to the block of input data.
  142. * @param[out] *pDst points to the block of output data
  143. * @param[in] blockSize number of samples to process.
  144. * @return none.
  145. */
  146. LOW_OPTIMIZATION_ENTER
  147. void arm_biquad_cascade_df2T_f32(
  148. const arm_biquad_cascade_df2T_instance_f32 * S,
  149. float32_t * pSrc,
  150. float32_t * pDst,
  151. uint32_t blockSize)
  152. {
  153. float32_t *pIn = pSrc; /* source pointer */
  154. float32_t *pOut = pDst; /* destination pointer */
  155. float32_t *pState = S->pState; /* State pointer */
  156. float32_t *pCoeffs = S->pCoeffs; /* coefficient pointer */
  157. float32_t acc1; /* accumulator */
  158. float32_t b0, b1, b2, a1, a2; /* Filter coefficients */
  159. float32_t Xn1; /* temporary input */
  160. float32_t d1, d2; /* state variables */
  161. uint32_t sample, stage = S->numStages; /* loop counters */
  162. #ifndef ARM_MATH_CM0_FAMILY_FAMILY
  163. float32_t Xn2, Xn3, Xn4; /* Input State variables */
  164. float32_t acc2, acc3, acc4; /* accumulator */
  165. float32_t p0, p1, p2, p3, p4, A1;
  166. /* Run the below code for Cortex-M4 and Cortex-M3 */
  167. do
  168. {
  169. /* Reading the coefficients */
  170. b0 = *pCoeffs++;
  171. b1 = *pCoeffs++;
  172. b2 = *pCoeffs++;
  173. a1 = *pCoeffs++;
  174. a2 = *pCoeffs++;
  175. /*Reading the state values */
  176. d1 = pState[0];
  177. d2 = pState[1];
  178. /* Apply loop unrolling and compute 4 output values simultaneously. */
  179. sample = blockSize >> 2u;
  180. /* First part of the processing with loop unrolling. Compute 4 outputs at a time.
  181. ** a second loop below computes the remaining 1 to 3 samples. */
  182. while(sample > 0u) {
  183. /* y[n] = b0 * x[n] + d1 */
  184. /* d1 = b1 * x[n] + a1 * y[n] + d2 */
  185. /* d2 = b2 * x[n] + a2 * y[n] */
  186. /* Read the four inputs */
  187. Xn1 = pIn[0];
  188. Xn2 = pIn[1];
  189. Xn3 = pIn[2];
  190. Xn4 = pIn[3];
  191. pIn += 4;
  192. p0 = b0 * Xn1;
  193. p1 = b1 * Xn1;
  194. acc1 = p0 + d1;
  195. p0 = b0 * Xn2;
  196. p3 = a1 * acc1;
  197. p2 = b2 * Xn1;
  198. A1 = p1 + p3;
  199. p4 = a2 * acc1;
  200. d1 = A1 + d2;
  201. d2 = p2 + p4;
  202. p1 = b1 * Xn2;
  203. acc2 = p0 + d1;
  204. p0 = b0 * Xn3;
  205. p3 = a1 * acc2;
  206. p2 = b2 * Xn2;
  207. A1 = p1 + p3;
  208. p4 = a2 * acc2;
  209. d1 = A1 + d2;
  210. d2 = p2 + p4;
  211. p1 = b1 * Xn3;
  212. acc3 = p0 + d1;
  213. p0 = b0 * Xn4;
  214. p3 = a1 * acc3;
  215. p2 = b2 * Xn3;
  216. A1 = p1 + p3;
  217. p4 = a2 * acc3;
  218. d1 = A1 + d2;
  219. d2 = p2 + p4;
  220. acc4 = p0 + d1;
  221. p1 = b1 * Xn4;
  222. p3 = a1 * acc4;
  223. p2 = b2 * Xn4;
  224. A1 = p1 + p3;
  225. p4 = a2 * acc4;
  226. d1 = A1 + d2;
  227. d2 = p2 + p4;
  228. pOut[0] = acc1;
  229. pOut[1] = acc2;
  230. pOut[2] = acc3;
  231. pOut[3] = acc4;
  232. pOut += 4;
  233. sample--;
  234. }
  235. sample = blockSize & 0x3u;
  236. while(sample > 0u) {
  237. Xn1 = *pIn++;
  238. p0 = b0 * Xn1;
  239. p1 = b1 * Xn1;
  240. acc1 = p0 + d1;
  241. p3 = a1 * acc1;
  242. p2 = b2 * Xn1;
  243. A1 = p1 + p3;
  244. p4 = a2 * acc1;
  245. d1 = A1 + d2;
  246. d2 = p2 + p4;
  247. *pOut++ = acc1;
  248. sample--;
  249. }
  250. /* Store the updated state variables back into the state array */
  251. *pState++ = d1;
  252. *pState++ = d2;
  253. /* The current stage input is given as the output to the next stage */
  254. pIn = pDst;
  255. /*Reset the output working pointer */
  256. pOut = pDst;
  257. /* decrement the loop counter */
  258. stage--;
  259. } while(stage > 0u);
  260. #else
  261. /* Run the below code for Cortex-M0 */
  262. do
  263. {
  264. /* Reading the coefficients */
  265. b0 = *pCoeffs++;
  266. b1 = *pCoeffs++;
  267. b2 = *pCoeffs++;
  268. a1 = *pCoeffs++;
  269. a2 = *pCoeffs++;
  270. /*Reading the state values */
  271. d1 = pState[0];
  272. d2 = pState[1];
  273. sample = blockSize;
  274. while(sample > 0u)
  275. {
  276. /* Read the input */
  277. Xn1 = *pIn++;
  278. /* y[n] = b0 * x[n] + d1 */
  279. acc1 = (b0 * Xn1) + d1;
  280. /* Store the result in the accumulator in the destination buffer. */
  281. *pOut++ = acc1;
  282. /* Every time after the output is computed state should be updated. */
  283. /* d1 = b1 * x[n] + a1 * y[n] + d2 */
  284. d1 = ((b1 * Xn1) + (a1 * acc1)) + d2;
  285. /* d2 = b2 * x[n] + a2 * y[n] */
  286. d2 = (b2 * Xn1) + (a2 * acc1);
  287. /* decrement the loop counter */
  288. sample--;
  289. }
  290. /* Store the updated state variables back into the state array */
  291. *pState++ = d1;
  292. *pState++ = d2;
  293. /* The current stage input is given as the output to the next stage */
  294. pIn = pDst;
  295. /*Reset the output working pointer */
  296. pOut = pDst;
  297. /* decrement the loop counter */
  298. stage--;
  299. } while(stage > 0u);
  300. #endif /* #ifndef ARM_MATH_CM0_FAMILY */
  301. }
  302. LOW_OPTIMIZATION_EXIT
  303. /**
  304. * @} end of BiquadCascadeDF2T group
  305. */