arm_cfft_radix2_q31.c 8.4 KB

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