arm_cfft_radix2_q31.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /* ----------------------------------------------------------------------
  2. * Project: CMSIS DSP Library
  3. * Title: arm_cfft_radix2_q31.c
  4. * Description: Radix-2 Decimation in Frequency CFFT & CIFFT Fixed point processing function
  5. *
  6. * $Date: 27. January 2017
  7. * $Revision: V.1.5.1
  8. *
  9. * Target Processor: Cortex-M cores
  10. * -------------------------------------------------------------------- */
  11. /*
  12. * Copyright (C) 2010-2017 ARM Limited or its affiliates. All rights reserved.
  13. *
  14. * SPDX-License-Identifier: Apache-2.0
  15. *
  16. * Licensed under the Apache License, Version 2.0 (the License); you may
  17. * not use this file except in compliance with the License.
  18. * You may obtain a copy of the License at
  19. *
  20. * www.apache.org/licenses/LICENSE-2.0
  21. *
  22. * Unless required by applicable law or agreed to in writing, software
  23. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  24. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  25. * See the License for the specific language governing permissions and
  26. * limitations under the License.
  27. */
  28. #include "arm_math.h"
  29. void arm_radix2_butterfly_q31(
  30. q31_t * pSrc,
  31. uint32_t fftLen,
  32. q31_t * pCoef,
  33. uint16_t twidCoefModifier);
  34. void arm_radix2_butterfly_inverse_q31(
  35. q31_t * pSrc,
  36. uint32_t fftLen,
  37. q31_t * pCoef,
  38. uint16_t twidCoefModifier);
  39. void arm_bitreversal_q31(
  40. q31_t * pSrc,
  41. uint32_t fftLen,
  42. uint16_t bitRevFactor,
  43. uint16_t * pBitRevTab);
  44. /**
  45. * @ingroup groupTransforms
  46. */
  47. /**
  48. * @addtogroup ComplexFFT
  49. * @{
  50. */
  51. /**
  52. * @details
  53. * @brief Processing function for the fixed-point CFFT/CIFFT.
  54. * @deprecated Do not use this function. It has been superseded by \ref arm_cfft_q31 and will be removed
  55. * @param[in] *S points to an instance of the fixed-point CFFT/CIFFT structure.
  56. * @param[in, out] *pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place.
  57. * @return none.
  58. */
  59. void arm_cfft_radix2_q31(
  60. const arm_cfft_radix2_instance_q31 * S,
  61. q31_t * pSrc)
  62. {
  63. if (S->ifftFlag == 1U)
  64. {
  65. arm_radix2_butterfly_inverse_q31(pSrc, S->fftLen,
  66. S->pTwiddle, S->twidCoefModifier);
  67. }
  68. else
  69. {
  70. arm_radix2_butterfly_q31(pSrc, S->fftLen,
  71. S->pTwiddle, S->twidCoefModifier);
  72. }
  73. arm_bitreversal_q31(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable);
  74. }
  75. /**
  76. * @} end of ComplexFFT group
  77. */
  78. void arm_radix2_butterfly_q31(
  79. q31_t * pSrc,
  80. uint32_t fftLen,
  81. q31_t * pCoef,
  82. uint16_t twidCoefModifier)
  83. {
  84. unsigned i, j, k, l, m;
  85. unsigned n1, n2, ia;
  86. q31_t xt, yt, cosVal, sinVal;
  87. q31_t p0, p1;
  88. //N = fftLen;
  89. n2 = fftLen;
  90. n1 = n2;
  91. n2 = n2 >> 1;
  92. ia = 0;
  93. // loop for groups
  94. for (i = 0; i < n2; i++)
  95. {
  96. cosVal = pCoef[ia * 2];
  97. sinVal = pCoef[(ia * 2) + 1];
  98. ia = ia + twidCoefModifier;
  99. l = i + n2;
  100. xt = (pSrc[2 * i] >> 1U) - (pSrc[2 * l] >> 1U);
  101. pSrc[2 * i] = ((pSrc[2 * i] >> 1U) + (pSrc[2 * l] >> 1U)) >> 1U;
  102. yt = (pSrc[2 * i + 1] >> 1U) - (pSrc[2 * l + 1] >> 1U);
  103. pSrc[2 * i + 1] =
  104. ((pSrc[2 * l + 1] >> 1U) + (pSrc[2 * i + 1] >> 1U)) >> 1U;
  105. mult_32x32_keep32_R(p0, xt, cosVal);
  106. mult_32x32_keep32_R(p1, yt, cosVal);
  107. multAcc_32x32_keep32_R(p0, yt, sinVal);
  108. multSub_32x32_keep32_R(p1, xt, sinVal);
  109. pSrc[2U * l] = p0;
  110. pSrc[2U * l + 1U] = p1;
  111. } // groups loop end
  112. twidCoefModifier <<= 1U;
  113. // loop for stage
  114. for (k = fftLen / 2; k > 2; k = k >> 1)
  115. {
  116. n1 = n2;
  117. n2 = n2 >> 1;
  118. ia = 0;
  119. // loop for groups
  120. for (j = 0; j < n2; j++)
  121. {
  122. cosVal = pCoef[ia * 2];
  123. sinVal = pCoef[(ia * 2) + 1];
  124. ia = ia + twidCoefModifier;
  125. // loop for butterfly
  126. i = j;
  127. m = fftLen / n1;
  128. do
  129. {
  130. l = i + n2;
  131. xt = pSrc[2 * i] - pSrc[2 * l];
  132. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1U;
  133. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  134. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1U;
  135. mult_32x32_keep32_R(p0, xt, cosVal);
  136. mult_32x32_keep32_R(p1, yt, cosVal);
  137. multAcc_32x32_keep32_R(p0, yt, sinVal);
  138. multSub_32x32_keep32_R(p1, xt, sinVal);
  139. pSrc[2U * l] = p0;
  140. pSrc[2U * l + 1U] = p1;
  141. i += n1;
  142. m--;
  143. } while ( m > 0); // butterfly loop end
  144. } // groups loop end
  145. twidCoefModifier <<= 1U;
  146. } // stages loop end
  147. n1 = n2;
  148. n2 = n2 >> 1;
  149. ia = 0;
  150. cosVal = pCoef[ia * 2];
  151. sinVal = pCoef[(ia * 2) + 1];
  152. ia = ia + twidCoefModifier;
  153. // loop for butterfly
  154. for (i = 0; i < fftLen; i += n1)
  155. {
  156. l = i + n2;
  157. xt = pSrc[2 * i] - pSrc[2 * l];
  158. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
  159. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  160. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
  161. pSrc[2U * l] = xt;
  162. pSrc[2U * l + 1U] = yt;
  163. i += n1;
  164. l = i + n2;
  165. xt = pSrc[2 * i] - pSrc[2 * l];
  166. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
  167. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  168. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
  169. pSrc[2U * l] = xt;
  170. pSrc[2U * l + 1U] = yt;
  171. } // butterfly loop end
  172. }
  173. void arm_radix2_butterfly_inverse_q31(
  174. q31_t * pSrc,
  175. uint32_t fftLen,
  176. q31_t * pCoef,
  177. uint16_t twidCoefModifier)
  178. {
  179. unsigned i, j, k, l;
  180. unsigned n1, n2, ia;
  181. q31_t xt, yt, cosVal, sinVal;
  182. q31_t p0, p1;
  183. //N = fftLen;
  184. n2 = fftLen;
  185. n1 = n2;
  186. n2 = n2 >> 1;
  187. ia = 0;
  188. // loop for groups
  189. for (i = 0; i < n2; i++)
  190. {
  191. cosVal = pCoef[ia * 2];
  192. sinVal = pCoef[(ia * 2) + 1];
  193. ia = ia + twidCoefModifier;
  194. l = i + n2;
  195. xt = (pSrc[2 * i] >> 1U) - (pSrc[2 * l] >> 1U);
  196. pSrc[2 * i] = ((pSrc[2 * i] >> 1U) + (pSrc[2 * l] >> 1U)) >> 1U;
  197. yt = (pSrc[2 * i + 1] >> 1U) - (pSrc[2 * l + 1] >> 1U);
  198. pSrc[2 * i + 1] =
  199. ((pSrc[2 * l + 1] >> 1U) + (pSrc[2 * i + 1] >> 1U)) >> 1U;
  200. mult_32x32_keep32_R(p0, xt, cosVal);
  201. mult_32x32_keep32_R(p1, yt, cosVal);
  202. multSub_32x32_keep32_R(p0, yt, sinVal);
  203. multAcc_32x32_keep32_R(p1, xt, sinVal);
  204. pSrc[2U * l] = p0;
  205. pSrc[2U * l + 1U] = p1;
  206. } // groups loop end
  207. twidCoefModifier = twidCoefModifier << 1U;
  208. // loop for stage
  209. for (k = fftLen / 2; k > 2; k = k >> 1)
  210. {
  211. n1 = n2;
  212. n2 = n2 >> 1;
  213. ia = 0;
  214. // loop for groups
  215. for (j = 0; j < n2; j++)
  216. {
  217. cosVal = pCoef[ia * 2];
  218. sinVal = pCoef[(ia * 2) + 1];
  219. ia = ia + twidCoefModifier;
  220. // loop for butterfly
  221. for (i = j; i < fftLen; i += n1)
  222. {
  223. l = i + n2;
  224. xt = pSrc[2 * i] - pSrc[2 * l];
  225. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1U;
  226. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  227. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1U;
  228. mult_32x32_keep32_R(p0, xt, cosVal);
  229. mult_32x32_keep32_R(p1, yt, cosVal);
  230. multSub_32x32_keep32_R(p0, yt, sinVal);
  231. multAcc_32x32_keep32_R(p1, xt, sinVal);
  232. pSrc[2U * l] = p0;
  233. pSrc[2U * l + 1U] = p1;
  234. } // butterfly loop end
  235. } // groups loop end
  236. twidCoefModifier = twidCoefModifier << 1U;
  237. } // stages loop end
  238. n1 = n2;
  239. n2 = n2 >> 1;
  240. ia = 0;
  241. cosVal = pCoef[ia * 2];
  242. sinVal = pCoef[(ia * 2) + 1];
  243. ia = ia + twidCoefModifier;
  244. // loop for butterfly
  245. for (i = 0; i < fftLen; i += n1)
  246. {
  247. l = i + n2;
  248. xt = pSrc[2 * i] - pSrc[2 * l];
  249. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
  250. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  251. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
  252. pSrc[2U * l] = xt;
  253. pSrc[2U * l + 1U] = yt;
  254. i += n1;
  255. l = i + n2;
  256. xt = pSrc[2 * i] - pSrc[2 * l];
  257. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
  258. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  259. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
  260. pSrc[2U * l] = xt;
  261. pSrc[2U * l + 1U] = yt;
  262. } // butterfly loop end
  263. }