arm_cfft_q31.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /* ----------------------------------------------------------------------
  2. * Copyright (C) 2010-2014 ARM Limited. All rights reserved.
  3. *
  4. * $Date: 31. July 2014
  5. * $Revision: V1.4.4
  6. *
  7. * Project: CMSIS DSP Library
  8. * Title: arm_cfft_q31.c
  9. *
  10. * Description: Combined Radix Decimation in Frequency CFFT Floating point processing function
  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. extern void arm_radix4_butterfly_q31(
  42. q31_t * pSrc,
  43. uint32_t fftLen,
  44. q31_t * pCoef,
  45. uint32_t twidCoefModifier);
  46. extern void arm_radix4_butterfly_inverse_q31(
  47. q31_t * pSrc,
  48. uint32_t fftLen,
  49. q31_t * pCoef,
  50. uint32_t twidCoefModifier);
  51. extern void arm_bitreversal_32(
  52. uint32_t * pSrc,
  53. const uint16_t bitRevLen,
  54. const uint16_t * pBitRevTable);
  55. void arm_cfft_radix4by2_q31(
  56. q31_t * pSrc,
  57. uint32_t fftLen,
  58. const q31_t * pCoef);
  59. void arm_cfft_radix4by2_inverse_q31(
  60. q31_t * pSrc,
  61. uint32_t fftLen,
  62. const q31_t * pCoef);
  63. /**
  64. * @ingroup groupTransforms
  65. */
  66. /**
  67. * @addtogroup ComplexFFT
  68. * @{
  69. */
  70. /**
  71. * @details
  72. * @brief Processing function for the floating-point complex FFT.
  73. * @param[in] *S points to an instance of the floating-point CFFT structure.
  74. * @param[in, out] *p1 points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place.
  75. * @param[in] ifftFlag flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
  76. * @param[in] bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
  77. * @return none.
  78. */
  79. void arm_cfft_q31(
  80. const arm_cfft_instance_q31 * S,
  81. q31_t * p1,
  82. uint8_t ifftFlag,
  83. uint8_t bitReverseFlag)
  84. {
  85. uint32_t L = S->fftLen;
  86. if(ifftFlag == 1u)
  87. {
  88. switch (L)
  89. {
  90. case 16:
  91. case 64:
  92. case 256:
  93. case 1024:
  94. case 4096:
  95. arm_radix4_butterfly_inverse_q31 ( p1, L, (q31_t*)S->pTwiddle, 1 );
  96. break;
  97. case 32:
  98. case 128:
  99. case 512:
  100. case 2048:
  101. arm_cfft_radix4by2_inverse_q31 ( p1, L, S->pTwiddle );
  102. break;
  103. }
  104. }
  105. else
  106. {
  107. switch (L)
  108. {
  109. case 16:
  110. case 64:
  111. case 256:
  112. case 1024:
  113. case 4096:
  114. arm_radix4_butterfly_q31 ( p1, L, (q31_t*)S->pTwiddle, 1 );
  115. break;
  116. case 32:
  117. case 128:
  118. case 512:
  119. case 2048:
  120. arm_cfft_radix4by2_q31 ( p1, L, S->pTwiddle );
  121. break;
  122. }
  123. }
  124. if( bitReverseFlag )
  125. arm_bitreversal_32((uint32_t*)p1,S->bitRevLength,S->pBitRevTable);
  126. }
  127. /**
  128. * @} end of ComplexFFT group
  129. */
  130. void arm_cfft_radix4by2_q31(
  131. q31_t * pSrc,
  132. uint32_t fftLen,
  133. const q31_t * pCoef)
  134. {
  135. uint32_t i, l;
  136. uint32_t n2, ia;
  137. q31_t xt, yt, cosVal, sinVal;
  138. q31_t p0, p1;
  139. n2 = fftLen >> 1;
  140. ia = 0;
  141. for (i = 0; i < n2; i++)
  142. {
  143. cosVal = pCoef[2*ia];
  144. sinVal = pCoef[2*ia + 1];
  145. ia++;
  146. l = i + n2;
  147. xt = (pSrc[2 * i] >> 2) - (pSrc[2 * l] >> 2);
  148. pSrc[2 * i] = (pSrc[2 * i] >> 2) + (pSrc[2 * l] >> 2);
  149. yt = (pSrc[2 * i + 1] >> 2) - (pSrc[2 * l + 1] >> 2);
  150. pSrc[2 * i + 1] = (pSrc[2 * l + 1] >> 2) + (pSrc[2 * i + 1] >> 2);
  151. mult_32x32_keep32_R(p0, xt, cosVal);
  152. mult_32x32_keep32_R(p1, yt, cosVal);
  153. multAcc_32x32_keep32_R(p0, yt, sinVal);
  154. multSub_32x32_keep32_R(p1, xt, sinVal);
  155. pSrc[2u * l] = p0 << 1;
  156. pSrc[2u * l + 1u] = p1 << 1;
  157. }
  158. // first col
  159. arm_radix4_butterfly_q31( pSrc, n2, (q31_t*)pCoef, 2u);
  160. // second col
  161. arm_radix4_butterfly_q31( pSrc + fftLen, n2, (q31_t*)pCoef, 2u);
  162. for (i = 0; i < fftLen >> 1; i++)
  163. {
  164. p0 = pSrc[4*i+0];
  165. p1 = pSrc[4*i+1];
  166. xt = pSrc[4*i+2];
  167. yt = pSrc[4*i+3];
  168. p0 <<= 1;
  169. p1 <<= 1;
  170. xt <<= 1;
  171. yt <<= 1;
  172. pSrc[4*i+0] = p0;
  173. pSrc[4*i+1] = p1;
  174. pSrc[4*i+2] = xt;
  175. pSrc[4*i+3] = yt;
  176. }
  177. }
  178. void arm_cfft_radix4by2_inverse_q31(
  179. q31_t * pSrc,
  180. uint32_t fftLen,
  181. const q31_t * pCoef)
  182. {
  183. uint32_t i, l;
  184. uint32_t n2, ia;
  185. q31_t xt, yt, cosVal, sinVal;
  186. q31_t p0, p1;
  187. n2 = fftLen >> 1;
  188. ia = 0;
  189. for (i = 0; i < n2; i++)
  190. {
  191. cosVal = pCoef[2*ia];
  192. sinVal = pCoef[2*ia + 1];
  193. ia++;
  194. l = i + n2;
  195. xt = (pSrc[2 * i] >> 2) - (pSrc[2 * l] >> 2);
  196. pSrc[2 * i] = (pSrc[2 * i] >> 2) + (pSrc[2 * l] >> 2);
  197. yt = (pSrc[2 * i + 1] >> 2) - (pSrc[2 * l + 1] >> 2);
  198. pSrc[2 * i + 1] = (pSrc[2 * l + 1] >> 2) + (pSrc[2 * i + 1] >> 2);
  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 << 1;
  204. pSrc[2u * l + 1u] = p1 << 1;
  205. }
  206. // first col
  207. arm_radix4_butterfly_inverse_q31( pSrc, n2, (q31_t*)pCoef, 2u);
  208. // second col
  209. arm_radix4_butterfly_inverse_q31( pSrc + fftLen, n2, (q31_t*)pCoef, 2u);
  210. for (i = 0; i < fftLen >> 1; i++)
  211. {
  212. p0 = pSrc[4*i+0];
  213. p1 = pSrc[4*i+1];
  214. xt = pSrc[4*i+2];
  215. yt = pSrc[4*i+3];
  216. p0 <<= 1;
  217. p1 <<= 1;
  218. xt <<= 1;
  219. yt <<= 1;
  220. pSrc[4*i+0] = p0;
  221. pSrc[4*i+1] = p1;
  222. pSrc[4*i+2] = xt;
  223. pSrc[4*i+3] = yt;
  224. }
  225. }