arm_cfft_radix2_q31.c 8.4 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: 18. March 2019
  7. * $Revision: V1.6.0
  8. *
  9. * Target Processor: Cortex-M cores
  10. * -------------------------------------------------------------------- */
  11. /*
  12. * Copyright (C) 2010-2019 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. const q31_t * pCoef,
  33. uint16_t twidCoefModifier);
  34. void arm_radix2_butterfly_inverse_q31(
  35. q31_t * pSrc,
  36. uint32_t fftLen,
  37. const 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. const uint16_t * pBitRevTab);
  44. /**
  45. @ingroup groupTransforms
  46. */
  47. /**
  48. @addtogroup ComplexFFT
  49. @{
  50. */
  51. /**
  52. @brief Processing function for the fixed-point CFFT/CIFFT.
  53. @deprecated Do not use this function. It has been superseded by \ref arm_cfft_q31 and will be removed in the future.
  54. @param[in] S points to an instance of the fixed-point CFFT/CIFFT structure
  55. @param[in,out] pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place
  56. @return none
  57. */
  58. void arm_cfft_radix2_q31(
  59. const arm_cfft_radix2_instance_q31 * S,
  60. q31_t * pSrc)
  61. {
  62. if (S->ifftFlag == 1U)
  63. {
  64. arm_radix2_butterfly_inverse_q31(pSrc, S->fftLen,
  65. S->pTwiddle, S->twidCoefModifier);
  66. }
  67. else
  68. {
  69. arm_radix2_butterfly_q31(pSrc, S->fftLen,
  70. S->pTwiddle, S->twidCoefModifier);
  71. }
  72. arm_bitreversal_q31(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable);
  73. }
  74. /**
  75. @} end of ComplexFFT group
  76. */
  77. void arm_radix2_butterfly_q31(
  78. q31_t * pSrc,
  79. uint32_t fftLen,
  80. const q31_t * pCoef,
  81. uint16_t twidCoefModifier)
  82. {
  83. unsigned i, j, k, l, m;
  84. unsigned n1, n2, ia;
  85. q31_t xt, yt, cosVal, sinVal;
  86. q31_t p0, p1;
  87. //N = fftLen;
  88. n2 = fftLen;
  89. n1 = n2;
  90. n2 = n2 >> 1;
  91. ia = 0;
  92. // loop for groups
  93. for (i = 0; i < n2; i++)
  94. {
  95. cosVal = pCoef[ia * 2];
  96. sinVal = pCoef[(ia * 2) + 1];
  97. ia = ia + twidCoefModifier;
  98. l = i + n2;
  99. xt = (pSrc[2 * i] >> 1U) - (pSrc[2 * l] >> 1U);
  100. pSrc[2 * i] = ((pSrc[2 * i] >> 1U) + (pSrc[2 * l] >> 1U)) >> 1U;
  101. yt = (pSrc[2 * i + 1] >> 1U) - (pSrc[2 * l + 1] >> 1U);
  102. pSrc[2 * i + 1] =
  103. ((pSrc[2 * l + 1] >> 1U) + (pSrc[2 * i + 1] >> 1U)) >> 1U;
  104. mult_32x32_keep32_R(p0, xt, cosVal);
  105. mult_32x32_keep32_R(p1, yt, cosVal);
  106. multAcc_32x32_keep32_R(p0, yt, sinVal);
  107. multSub_32x32_keep32_R(p1, xt, sinVal);
  108. pSrc[2U * l] = p0;
  109. pSrc[2U * l + 1U] = p1;
  110. } // groups loop end
  111. twidCoefModifier <<= 1U;
  112. // loop for stage
  113. for (k = fftLen / 2; k > 2; k = k >> 1)
  114. {
  115. n1 = n2;
  116. n2 = n2 >> 1;
  117. ia = 0;
  118. // loop for groups
  119. for (j = 0; j < n2; j++)
  120. {
  121. cosVal = pCoef[ia * 2];
  122. sinVal = pCoef[(ia * 2) + 1];
  123. ia = ia + twidCoefModifier;
  124. // loop for butterfly
  125. i = j;
  126. m = fftLen / n1;
  127. do
  128. {
  129. l = i + n2;
  130. xt = pSrc[2 * i] - pSrc[2 * l];
  131. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1U;
  132. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  133. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1U;
  134. mult_32x32_keep32_R(p0, xt, cosVal);
  135. mult_32x32_keep32_R(p1, yt, cosVal);
  136. multAcc_32x32_keep32_R(p0, yt, sinVal);
  137. multSub_32x32_keep32_R(p1, xt, sinVal);
  138. pSrc[2U * l] = p0;
  139. pSrc[2U * l + 1U] = p1;
  140. i += n1;
  141. m--;
  142. } while ( m > 0); // butterfly loop end
  143. } // groups loop end
  144. twidCoefModifier <<= 1U;
  145. } // stages loop end
  146. n1 = n2;
  147. n2 = n2 >> 1;
  148. ia = 0;
  149. cosVal = pCoef[ia * 2];
  150. sinVal = pCoef[(ia * 2) + 1];
  151. ia = ia + twidCoefModifier;
  152. // loop for butterfly
  153. for (i = 0; i < fftLen; i += n1)
  154. {
  155. l = i + n2;
  156. xt = pSrc[2 * i] - pSrc[2 * l];
  157. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
  158. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  159. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
  160. pSrc[2U * l] = xt;
  161. pSrc[2U * l + 1U] = yt;
  162. i += n1;
  163. l = i + n2;
  164. xt = pSrc[2 * i] - pSrc[2 * l];
  165. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
  166. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  167. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
  168. pSrc[2U * l] = xt;
  169. pSrc[2U * l + 1U] = yt;
  170. } // butterfly loop end
  171. }
  172. void arm_radix2_butterfly_inverse_q31(
  173. q31_t * pSrc,
  174. uint32_t fftLen,
  175. const q31_t * pCoef,
  176. uint16_t twidCoefModifier)
  177. {
  178. unsigned i, j, k, l;
  179. unsigned n1, n2, ia;
  180. q31_t xt, yt, cosVal, sinVal;
  181. q31_t p0, p1;
  182. //N = fftLen;
  183. n2 = fftLen;
  184. n1 = n2;
  185. n2 = n2 >> 1;
  186. ia = 0;
  187. // loop for groups
  188. for (i = 0; i < n2; i++)
  189. {
  190. cosVal = pCoef[ia * 2];
  191. sinVal = pCoef[(ia * 2) + 1];
  192. ia = ia + twidCoefModifier;
  193. l = i + n2;
  194. xt = (pSrc[2 * i] >> 1U) - (pSrc[2 * l] >> 1U);
  195. pSrc[2 * i] = ((pSrc[2 * i] >> 1U) + (pSrc[2 * l] >> 1U)) >> 1U;
  196. yt = (pSrc[2 * i + 1] >> 1U) - (pSrc[2 * l + 1] >> 1U);
  197. pSrc[2 * i + 1] =
  198. ((pSrc[2 * l + 1] >> 1U) + (pSrc[2 * i + 1] >> 1U)) >> 1U;
  199. mult_32x32_keep32_R(p0, xt, cosVal);
  200. mult_32x32_keep32_R(p1, yt, cosVal);
  201. multSub_32x32_keep32_R(p0, yt, sinVal);
  202. multAcc_32x32_keep32_R(p1, xt, sinVal);
  203. pSrc[2U * l] = p0;
  204. pSrc[2U * l + 1U] = p1;
  205. } // groups loop end
  206. twidCoefModifier = twidCoefModifier << 1U;
  207. // loop for stage
  208. for (k = fftLen / 2; k > 2; k = k >> 1)
  209. {
  210. n1 = n2;
  211. n2 = n2 >> 1;
  212. ia = 0;
  213. // loop for groups
  214. for (j = 0; j < n2; j++)
  215. {
  216. cosVal = pCoef[ia * 2];
  217. sinVal = pCoef[(ia * 2) + 1];
  218. ia = ia + twidCoefModifier;
  219. // loop for butterfly
  220. for (i = j; i < fftLen; i += n1)
  221. {
  222. l = i + n2;
  223. xt = pSrc[2 * i] - pSrc[2 * l];
  224. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1U;
  225. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  226. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1U;
  227. mult_32x32_keep32_R(p0, xt, cosVal);
  228. mult_32x32_keep32_R(p1, yt, cosVal);
  229. multSub_32x32_keep32_R(p0, yt, sinVal);
  230. multAcc_32x32_keep32_R(p1, xt, sinVal);
  231. pSrc[2U * l] = p0;
  232. pSrc[2U * l + 1U] = p1;
  233. } // butterfly loop end
  234. } // groups loop end
  235. twidCoefModifier = twidCoefModifier << 1U;
  236. } // stages loop end
  237. n1 = n2;
  238. n2 = n2 >> 1;
  239. ia = 0;
  240. cosVal = pCoef[ia * 2];
  241. sinVal = pCoef[(ia * 2) + 1];
  242. ia = ia + twidCoefModifier;
  243. // loop for butterfly
  244. for (i = 0; i < fftLen; i += n1)
  245. {
  246. l = i + n2;
  247. xt = pSrc[2 * i] - pSrc[2 * l];
  248. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
  249. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  250. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
  251. pSrc[2U * l] = xt;
  252. pSrc[2U * l + 1U] = yt;
  253. i += n1;
  254. l = i + n2;
  255. xt = pSrc[2 * i] - pSrc[2 * l];
  256. pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
  257. yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
  258. pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
  259. pSrc[2U * l] = xt;
  260. pSrc[2U * l + 1U] = yt;
  261. } // butterfly loop end
  262. }