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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

arm_cfft_radix2_q15.c 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  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_cfft_radix2_q15.c
  9. *
  10. * Description: Radix-2 Decimation in Frequency CFFT & CIFFT Fixed point processing function
  11. *
  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. void arm_radix2_butterfly_q15(
  43. q15_t * pSrc,
  44. uint32_t fftLen,
  45. q15_t * pCoef,
  46. uint16_t twidCoefModifier);
  47. void arm_radix2_butterfly_inverse_q15(
  48. q15_t * pSrc,
  49. uint32_t fftLen,
  50. q15_t * pCoef,
  51. uint16_t twidCoefModifier);
  52. void arm_bitreversal_q15(
  53. q15_t * pSrc,
  54. uint32_t fftLen,
  55. uint16_t bitRevFactor,
  56. uint16_t * pBitRevTab);
  57. /**
  58. * @ingroup groupTransforms
  59. */
  60. /**
  61. * @addtogroup ComplexFFT
  62. * @{
  63. */
  64. /**
  65. * @details
  66. * @brief Processing function for the fixed-point CFFT/CIFFT.
  67. * @param[in] *S points to an instance of the fixed-point CFFT/CIFFT structure.
  68. * @param[in, out] *pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place.
  69. * @return none.
  70. */
  71. void arm_cfft_radix2_q15(
  72. const arm_cfft_radix2_instance_q15 * S,
  73. q15_t * pSrc)
  74. {
  75. if(S->ifftFlag == 1u)
  76. {
  77. arm_radix2_butterfly_inverse_q15(pSrc, S->fftLen,
  78. S->pTwiddle, S->twidCoefModifier);
  79. }
  80. else
  81. {
  82. arm_radix2_butterfly_q15(pSrc, S->fftLen,
  83. S->pTwiddle, S->twidCoefModifier);
  84. }
  85. arm_bitreversal_q15(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable);
  86. }
  87. /**
  88. * @} end of ComplexFFT group
  89. */
  90. void arm_radix2_butterfly_q15(
  91. q15_t * pSrc,
  92. uint32_t fftLen,
  93. q15_t * pCoef,
  94. uint16_t twidCoefModifier)
  95. {
  96. #ifndef ARM_MATH_CM0_FAMILY
  97. unsigned i, j, k, l;
  98. unsigned n1, n2, ia;
  99. q15_t in;
  100. q31_t T, S, R;
  101. q31_t coeff, out1, out2;
  102. //N = fftLen;
  103. n2 = fftLen;
  104. n1 = n2;
  105. n2 = n2 >> 1;
  106. ia = 0;
  107. // loop for groups
  108. for (i = 0; i < n2; i++)
  109. {
  110. coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
  111. ia = ia + twidCoefModifier;
  112. l = i + n2;
  113. T = _SIMD32_OFFSET(pSrc + (2 * i));
  114. in = ((int16_t) (T & 0xFFFF)) >> 2;
  115. T = ((T >> 2) & 0xFFFF0000) | (in & 0xFFFF);
  116. S = _SIMD32_OFFSET(pSrc + (2 * l));
  117. in = ((int16_t) (S & 0xFFFF)) >> 2;
  118. S = ((S >> 2) & 0xFFFF0000) | (in & 0xFFFF);
  119. R = __QSUB16(T, S);
  120. _SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
  121. #ifndef ARM_MATH_BIG_ENDIAN
  122. out1 = __SMUAD(coeff, R) >> 16;
  123. out2 = __SMUSDX(coeff, R);
  124. #else
  125. out1 = __SMUSDX(R, coeff) >> 16u;
  126. out2 = __SMUAD(coeff, R);
  127. #endif // #ifndef ARM_MATH_BIG_ENDIAN
  128. _SIMD32_OFFSET(pSrc + (2u * l)) =
  129. (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
  130. coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
  131. ia = ia + twidCoefModifier;
  132. // loop for butterfly
  133. i++;
  134. l++;
  135. T = _SIMD32_OFFSET(pSrc + (2 * i));
  136. in = ((int16_t) (T & 0xFFFF)) >> 2;
  137. T = ((T >> 2) & 0xFFFF0000) | (in & 0xFFFF);
  138. S = _SIMD32_OFFSET(pSrc + (2 * l));
  139. in = ((int16_t) (S & 0xFFFF)) >> 2;
  140. S = ((S >> 2) & 0xFFFF0000) | (in & 0xFFFF);
  141. R = __QSUB16(T, S);
  142. _SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
  143. #ifndef ARM_MATH_BIG_ENDIAN
  144. out1 = __SMUAD(coeff, R) >> 16;
  145. out2 = __SMUSDX(coeff, R);
  146. #else
  147. out1 = __SMUSDX(R, coeff) >> 16u;
  148. out2 = __SMUAD(coeff, R);
  149. #endif // #ifndef ARM_MATH_BIG_ENDIAN
  150. _SIMD32_OFFSET(pSrc + (2u * l)) =
  151. (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
  152. } // groups loop end
  153. twidCoefModifier = twidCoefModifier << 1u;
  154. // loop for stage
  155. for (k = fftLen / 2; k > 2; k = k >> 1)
  156. {
  157. n1 = n2;
  158. n2 = n2 >> 1;
  159. ia = 0;
  160. // loop for groups
  161. for (j = 0; j < n2; j++)
  162. {
  163. coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
  164. ia = ia + twidCoefModifier;
  165. // loop for butterfly
  166. for (i = j; i < fftLen; i += n1)
  167. {
  168. l = i + n2;
  169. T = _SIMD32_OFFSET(pSrc + (2 * i));
  170. S = _SIMD32_OFFSET(pSrc + (2 * l));
  171. R = __QSUB16(T, S);
  172. _SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
  173. #ifndef ARM_MATH_BIG_ENDIAN
  174. out1 = __SMUAD(coeff, R) >> 16;
  175. out2 = __SMUSDX(coeff, R);
  176. #else
  177. out1 = __SMUSDX(R, coeff) >> 16u;
  178. out2 = __SMUAD(coeff, R);
  179. #endif // #ifndef ARM_MATH_BIG_ENDIAN
  180. _SIMD32_OFFSET(pSrc + (2u * l)) =
  181. (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
  182. i += n1;
  183. l = i + n2;
  184. T = _SIMD32_OFFSET(pSrc + (2 * i));
  185. S = _SIMD32_OFFSET(pSrc + (2 * l));
  186. R = __QSUB16(T, S);
  187. _SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
  188. #ifndef ARM_MATH_BIG_ENDIAN
  189. out1 = __SMUAD(coeff, R) >> 16;
  190. out2 = __SMUSDX(coeff, R);
  191. #else
  192. out1 = __SMUSDX(R, coeff) >> 16u;
  193. out2 = __SMUAD(coeff, R);
  194. #endif // #ifndef ARM_MATH_BIG_ENDIAN
  195. _SIMD32_OFFSET(pSrc + (2u * l)) =
  196. (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
  197. } // butterfly loop end
  198. } // groups loop end
  199. twidCoefModifier = twidCoefModifier << 1u;
  200. } // stages loop end
  201. n1 = n2;
  202. n2 = n2 >> 1;
  203. ia = 0;
  204. coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
  205. ia = ia + twidCoefModifier;
  206. // loop for butterfly
  207. for (i = 0; i < fftLen; i += n1)
  208. {
  209. l = i + n2;
  210. T = _SIMD32_OFFSET(pSrc + (2 * i));
  211. S = _SIMD32_OFFSET(pSrc + (2 * l));
  212. R = __QSUB16(T, S);
  213. _SIMD32_OFFSET(pSrc + (2 * i)) = __QADD16(T, S);
  214. _SIMD32_OFFSET(pSrc + (2u * l)) = R;
  215. i += n1;
  216. l = i + n2;
  217. T = _SIMD32_OFFSET(pSrc + (2 * i));
  218. S = _SIMD32_OFFSET(pSrc + (2 * l));
  219. R = __QSUB16(T, S);
  220. _SIMD32_OFFSET(pSrc + (2 * i)) = __QADD16(T, S);
  221. _SIMD32_OFFSET(pSrc + (2u * l)) = R;
  222. } // groups loop end
  223. #else
  224. unsigned i, j, k, l;
  225. unsigned n1, n2, ia;
  226. q15_t xt, yt, cosVal, sinVal;
  227. //N = fftLen;
  228. n2 = fftLen;
  229. n1 = n2;
  230. n2 = n2 >> 1;
  231. ia = 0;
  232. // loop for groups
  233. for (j = 0; j < n2; j++)
  234. {
  235. cosVal = pCoef[ia * 2];
  236. sinVal = pCoef[(ia * 2) + 1];
  237. ia = ia + twidCoefModifier;
  238. // loop for butterfly
  239. for (i = j; i < fftLen; i += n1)
  240. {
  241. l = i + n2;
  242. xt = (pSrc[2 * i] >> 2u) - (pSrc[2 * l] >> 2u);
  243. pSrc[2 * i] = ((pSrc[2 * i] >> 2u) + (pSrc[2 * l] >> 2u)) >> 1u;
  244. yt = (pSrc[2 * i + 1] >> 2u) - (pSrc[2 * l + 1] >> 2u);
  245. pSrc[2 * i + 1] =
  246. ((pSrc[2 * l + 1] >> 2u) + (pSrc[2 * i + 1] >> 2u)) >> 1u;
  247. pSrc[2u * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16)) +
  248. ((int16_t) (((q31_t) yt * sinVal) >> 16)));
  249. pSrc[2u * l + 1u] = (((int16_t) (((q31_t) yt * cosVal) >> 16)) -
  250. ((int16_t) (((q31_t) xt * sinVal) >> 16)));
  251. } // butterfly loop end
  252. } // groups loop end
  253. twidCoefModifier = twidCoefModifier << 1u;
  254. // loop for stage
  255. for (k = fftLen / 2; k > 2; k = k >> 1)
  256. {
  257. n1 = n2;
  258. n2 = n2 >> 1;
  259. ia = 0;
  260. // loop for groups
  261. for (j = 0; j < n2; j++)
  262. {
  263. cosVal = pCoef[ia * 2];
  264. sinVal = pCoef[(ia * 2) + 1];
  265. ia = ia + twidCoefModifier;
  266. // loop for butterfly
  267. for (i = j; i < fftLen; i += n1)
  268. {
  269. l = i + n2;
  270. xt = pSrc[2 * i] - pSrc[2 * l];
  271. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1u;
  272. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  273. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1u;
  274. pSrc[2u * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16)) +
  275. ((int16_t) (((q31_t) yt * sinVal) >> 16)));
  276. pSrc[2u * l + 1u] = (((int16_t) (((q31_t) yt * cosVal) >> 16)) -
  277. ((int16_t) (((q31_t) xt * sinVal) >> 16)));
  278. } // butterfly loop end
  279. } // groups loop end
  280. twidCoefModifier = twidCoefModifier << 1u;
  281. } // stages loop end
  282. n1 = n2;
  283. n2 = n2 >> 1;
  284. ia = 0;
  285. // loop for groups
  286. for (j = 0; j < n2; j++)
  287. {
  288. cosVal = pCoef[ia * 2];
  289. sinVal = pCoef[(ia * 2) + 1];
  290. ia = ia + twidCoefModifier;
  291. // loop for butterfly
  292. for (i = j; i < fftLen; i += n1)
  293. {
  294. l = i + n2;
  295. xt = pSrc[2 * i] - pSrc[2 * l];
  296. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
  297. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  298. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
  299. pSrc[2u * l] = xt;
  300. pSrc[2u * l + 1u] = yt;
  301. } // butterfly loop end
  302. } // groups loop end
  303. twidCoefModifier = twidCoefModifier << 1u;
  304. #endif // #ifndef ARM_MATH_CM0_FAMILY
  305. }
  306. void arm_radix2_butterfly_inverse_q15(
  307. q15_t * pSrc,
  308. uint32_t fftLen,
  309. q15_t * pCoef,
  310. uint16_t twidCoefModifier)
  311. {
  312. #ifndef ARM_MATH_CM0_FAMILY
  313. unsigned i, j, k, l;
  314. unsigned n1, n2, ia;
  315. q15_t in;
  316. q31_t T, S, R;
  317. q31_t coeff, out1, out2;
  318. //N = fftLen;
  319. n2 = fftLen;
  320. n1 = n2;
  321. n2 = n2 >> 1;
  322. ia = 0;
  323. // loop for groups
  324. for (i = 0; i < n2; i++)
  325. {
  326. coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
  327. ia = ia + twidCoefModifier;
  328. l = i + n2;
  329. T = _SIMD32_OFFSET(pSrc + (2 * i));
  330. in = ((int16_t) (T & 0xFFFF)) >> 2;
  331. T = ((T >> 2) & 0xFFFF0000) | (in & 0xFFFF);
  332. S = _SIMD32_OFFSET(pSrc + (2 * l));
  333. in = ((int16_t) (S & 0xFFFF)) >> 2;
  334. S = ((S >> 2) & 0xFFFF0000) | (in & 0xFFFF);
  335. R = __QSUB16(T, S);
  336. _SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
  337. #ifndef ARM_MATH_BIG_ENDIAN
  338. out1 = __SMUSD(coeff, R) >> 16;
  339. out2 = __SMUADX(coeff, R);
  340. #else
  341. out1 = __SMUADX(R, coeff) >> 16u;
  342. out2 = __SMUSD(__QSUB(0, coeff), R);
  343. #endif // #ifndef ARM_MATH_BIG_ENDIAN
  344. _SIMD32_OFFSET(pSrc + (2u * l)) =
  345. (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
  346. coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
  347. ia = ia + twidCoefModifier;
  348. // loop for butterfly
  349. i++;
  350. l++;
  351. T = _SIMD32_OFFSET(pSrc + (2 * i));
  352. in = ((int16_t) (T & 0xFFFF)) >> 2;
  353. T = ((T >> 2) & 0xFFFF0000) | (in & 0xFFFF);
  354. S = _SIMD32_OFFSET(pSrc + (2 * l));
  355. in = ((int16_t) (S & 0xFFFF)) >> 2;
  356. S = ((S >> 2) & 0xFFFF0000) | (in & 0xFFFF);
  357. R = __QSUB16(T, S);
  358. _SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
  359. #ifndef ARM_MATH_BIG_ENDIAN
  360. out1 = __SMUSD(coeff, R) >> 16;
  361. out2 = __SMUADX(coeff, R);
  362. #else
  363. out1 = __SMUADX(R, coeff) >> 16u;
  364. out2 = __SMUSD(__QSUB(0, coeff), R);
  365. #endif // #ifndef ARM_MATH_BIG_ENDIAN
  366. _SIMD32_OFFSET(pSrc + (2u * l)) =
  367. (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
  368. } // groups loop end
  369. twidCoefModifier = twidCoefModifier << 1u;
  370. // loop for stage
  371. for (k = fftLen / 2; k > 2; k = k >> 1)
  372. {
  373. n1 = n2;
  374. n2 = n2 >> 1;
  375. ia = 0;
  376. // loop for groups
  377. for (j = 0; j < n2; j++)
  378. {
  379. coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
  380. ia = ia + twidCoefModifier;
  381. // loop for butterfly
  382. for (i = j; i < fftLen; i += n1)
  383. {
  384. l = i + n2;
  385. T = _SIMD32_OFFSET(pSrc + (2 * i));
  386. S = _SIMD32_OFFSET(pSrc + (2 * l));
  387. R = __QSUB16(T, S);
  388. _SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
  389. #ifndef ARM_MATH_BIG_ENDIAN
  390. out1 = __SMUSD(coeff, R) >> 16;
  391. out2 = __SMUADX(coeff, R);
  392. #else
  393. out1 = __SMUADX(R, coeff) >> 16u;
  394. out2 = __SMUSD(__QSUB(0, coeff), R);
  395. #endif // #ifndef ARM_MATH_BIG_ENDIAN
  396. _SIMD32_OFFSET(pSrc + (2u * l)) =
  397. (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
  398. i += n1;
  399. l = i + n2;
  400. T = _SIMD32_OFFSET(pSrc + (2 * i));
  401. S = _SIMD32_OFFSET(pSrc + (2 * l));
  402. R = __QSUB16(T, S);
  403. _SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
  404. #ifndef ARM_MATH_BIG_ENDIAN
  405. out1 = __SMUSD(coeff, R) >> 16;
  406. out2 = __SMUADX(coeff, R);
  407. #else
  408. out1 = __SMUADX(R, coeff) >> 16u;
  409. out2 = __SMUSD(__QSUB(0, coeff), R);
  410. #endif // #ifndef ARM_MATH_BIG_ENDIAN
  411. _SIMD32_OFFSET(pSrc + (2u * l)) =
  412. (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
  413. } // butterfly loop end
  414. } // groups loop end
  415. twidCoefModifier = twidCoefModifier << 1u;
  416. } // stages loop end
  417. n1 = n2;
  418. n2 = n2 >> 1;
  419. ia = 0;
  420. // loop for groups
  421. for (j = 0; j < n2; j++)
  422. {
  423. coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
  424. ia = ia + twidCoefModifier;
  425. // loop for butterfly
  426. for (i = j; i < fftLen; i += n1)
  427. {
  428. l = i + n2;
  429. T = _SIMD32_OFFSET(pSrc + (2 * i));
  430. S = _SIMD32_OFFSET(pSrc + (2 * l));
  431. R = __QSUB16(T, S);
  432. _SIMD32_OFFSET(pSrc + (2 * i)) = __QADD16(T, S);
  433. _SIMD32_OFFSET(pSrc + (2u * l)) = R;
  434. } // butterfly loop end
  435. } // groups loop end
  436. twidCoefModifier = twidCoefModifier << 1u;
  437. #else
  438. unsigned i, j, k, l;
  439. unsigned n1, n2, ia;
  440. q15_t xt, yt, cosVal, sinVal;
  441. //N = fftLen;
  442. n2 = fftLen;
  443. n1 = n2;
  444. n2 = n2 >> 1;
  445. ia = 0;
  446. // loop for groups
  447. for (j = 0; j < n2; j++)
  448. {
  449. cosVal = pCoef[ia * 2];
  450. sinVal = pCoef[(ia * 2) + 1];
  451. ia = ia + twidCoefModifier;
  452. // loop for butterfly
  453. for (i = j; i < fftLen; i += n1)
  454. {
  455. l = i + n2;
  456. xt = (pSrc[2 * i] >> 2u) - (pSrc[2 * l] >> 2u);
  457. pSrc[2 * i] = ((pSrc[2 * i] >> 2u) + (pSrc[2 * l] >> 2u)) >> 1u;
  458. yt = (pSrc[2 * i + 1] >> 2u) - (pSrc[2 * l + 1] >> 2u);
  459. pSrc[2 * i + 1] =
  460. ((pSrc[2 * l + 1] >> 2u) + (pSrc[2 * i + 1] >> 2u)) >> 1u;
  461. pSrc[2u * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16)) -
  462. ((int16_t) (((q31_t) yt * sinVal) >> 16)));
  463. pSrc[2u * l + 1u] = (((int16_t) (((q31_t) yt * cosVal) >> 16)) +
  464. ((int16_t) (((q31_t) xt * sinVal) >> 16)));
  465. } // butterfly loop end
  466. } // groups loop end
  467. twidCoefModifier = twidCoefModifier << 1u;
  468. // loop for stage
  469. for (k = fftLen / 2; k > 2; k = k >> 1)
  470. {
  471. n1 = n2;
  472. n2 = n2 >> 1;
  473. ia = 0;
  474. // loop for groups
  475. for (j = 0; j < n2; j++)
  476. {
  477. cosVal = pCoef[ia * 2];
  478. sinVal = pCoef[(ia * 2) + 1];
  479. ia = ia + twidCoefModifier;
  480. // loop for butterfly
  481. for (i = j; i < fftLen; i += n1)
  482. {
  483. l = i + n2;
  484. xt = pSrc[2 * i] - pSrc[2 * l];
  485. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1u;
  486. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  487. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1u;
  488. pSrc[2u * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16)) -
  489. ((int16_t) (((q31_t) yt * sinVal) >> 16)));
  490. pSrc[2u * l + 1u] = (((int16_t) (((q31_t) yt * cosVal) >> 16)) +
  491. ((int16_t) (((q31_t) xt * sinVal) >> 16)));
  492. } // butterfly loop end
  493. } // groups loop end
  494. twidCoefModifier = twidCoefModifier << 1u;
  495. } // stages loop end
  496. n1 = n2;
  497. n2 = n2 >> 1;
  498. ia = 0;
  499. cosVal = pCoef[ia * 2];
  500. sinVal = pCoef[(ia * 2) + 1];
  501. ia = ia + twidCoefModifier;
  502. // loop for butterfly
  503. for (i = 0; i < fftLen; i += n1)
  504. {
  505. l = i + n2;
  506. xt = pSrc[2 * i] - pSrc[2 * l];
  507. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
  508. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  509. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
  510. pSrc[2u * l] = xt;
  511. pSrc[2u * l + 1u] = yt;
  512. } // groups loop end
  513. #endif // #ifndef ARM_MATH_CM0_FAMILY
  514. }