Subversion Repositories AFRtranscoder

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /* ----------------------------------------------------------------------
  2.  * Project:      CMSIS DSP Library
  3.  * Title:        arm_cfft_q31.c
  4.  * Description:  Combined Radix Decimation in Frequency CFFT 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.  
  29. #include "arm_math.h"
  30.  
  31. extern void arm_radix4_butterfly_q31(
  32.     q31_t * pSrc,
  33.     uint32_t fftLen,
  34.     q31_t * pCoef,
  35.     uint32_t twidCoefModifier);
  36.  
  37. extern void arm_radix4_butterfly_inverse_q31(
  38.     q31_t * pSrc,
  39.     uint32_t fftLen,
  40.     q31_t * pCoef,
  41.     uint32_t twidCoefModifier);
  42.  
  43. extern void arm_bitreversal_32(
  44.     uint32_t * pSrc,
  45.     const uint16_t bitRevLen,
  46.     const uint16_t * pBitRevTable);
  47.  
  48. void arm_cfft_radix4by2_q31(
  49.     q31_t * pSrc,
  50.     uint32_t fftLen,
  51.     const q31_t * pCoef);
  52.  
  53. void arm_cfft_radix4by2_inverse_q31(
  54.     q31_t * pSrc,
  55.     uint32_t fftLen,
  56.     const q31_t * pCoef);
  57.  
  58. /**
  59. * @ingroup groupTransforms
  60. */
  61.  
  62. /**
  63. * @addtogroup ComplexFFT
  64. * @{
  65. */
  66.  
  67. /**
  68. * @details
  69. * @brief       Processing function for the fixed-point complex FFT in Q31 format.
  70. * @param[in]      *S    points to an instance of the fixed-point CFFT structure.
  71. * @param[in, out] *p1   points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place.
  72. * @param[in]     ifftFlag       flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
  73. * @param[in]     bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
  74. * @return none.
  75. */
  76.  
  77. void arm_cfft_q31(
  78.     const arm_cfft_instance_q31 * S,
  79.     q31_t * p1,
  80.     uint8_t ifftFlag,
  81.     uint8_t bitReverseFlag)
  82. {
  83.     uint32_t L = S->fftLen;
  84.  
  85.     if (ifftFlag == 1U)
  86.     {
  87.         switch (L)
  88.         {
  89.         case 16:
  90.         case 64:
  91.         case 256:
  92.         case 1024:
  93.         case 4096:
  94.             arm_radix4_butterfly_inverse_q31  ( p1, L, (q31_t*)S->pTwiddle, 1 );
  95.             break;
  96.  
  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.  
  117.         case 32:
  118.         case 128:
  119.         case 512:
  120.         case 2048:
  121.             arm_cfft_radix4by2_q31  ( p1, L, S->pTwiddle );
  122.             break;
  123.         }
  124.     }
  125.  
  126.     if ( bitReverseFlag )
  127.         arm_bitreversal_32((uint32_t*)p1,S->bitRevLength,S->pBitRevTable);
  128. }
  129.  
  130. /**
  131. * @} end of ComplexFFT group
  132. */
  133.  
  134. void arm_cfft_radix4by2_q31(
  135.     q31_t * pSrc,
  136.     uint32_t fftLen,
  137.     const q31_t * pCoef)
  138. {
  139.     uint32_t i, l;
  140.     uint32_t n2, ia;
  141.     q31_t xt, yt, cosVal, sinVal;
  142.     q31_t p0, p1;
  143.  
  144.     n2 = fftLen >> 1;
  145.     ia = 0;
  146.     for (i = 0; i < n2; i++)
  147.     {
  148.         cosVal = pCoef[2*ia];
  149.         sinVal = pCoef[2*ia + 1];
  150.         ia++;
  151.  
  152.         l = i + n2;
  153.         xt = (pSrc[2 * i] >> 2) - (pSrc[2 * l] >> 2);
  154.         pSrc[2 * i] = (pSrc[2 * i] >> 2) + (pSrc[2 * l] >> 2);
  155.  
  156.         yt = (pSrc[2 * i + 1] >> 2) - (pSrc[2 * l + 1] >> 2);
  157.         pSrc[2 * i + 1] = (pSrc[2 * l + 1] >> 2) + (pSrc[2 * i + 1] >> 2);
  158.  
  159.         mult_32x32_keep32_R(p0, xt, cosVal);
  160.         mult_32x32_keep32_R(p1, yt, cosVal);
  161.         multAcc_32x32_keep32_R(p0, yt, sinVal);
  162.         multSub_32x32_keep32_R(p1, xt, sinVal);
  163.  
  164.         pSrc[2U * l] = p0 << 1;
  165.         pSrc[2U * l + 1U] = p1 << 1;
  166.  
  167.     }
  168.  
  169.     // first col
  170.     arm_radix4_butterfly_q31( pSrc, n2, (q31_t*)pCoef, 2U);
  171.     // second col
  172.     arm_radix4_butterfly_q31( pSrc + fftLen, n2, (q31_t*)pCoef, 2U);
  173.  
  174.     for (i = 0; i < fftLen >> 1; i++)
  175.     {
  176.         p0 = pSrc[4*i+0];
  177.         p1 = pSrc[4*i+1];
  178.         xt = pSrc[4*i+2];
  179.         yt = pSrc[4*i+3];
  180.  
  181.         p0 <<= 1;
  182.         p1 <<= 1;
  183.         xt <<= 1;
  184.         yt <<= 1;
  185.  
  186.         pSrc[4*i+0] = p0;
  187.         pSrc[4*i+1] = p1;
  188.         pSrc[4*i+2] = xt;
  189.         pSrc[4*i+3] = yt;
  190.     }
  191.  
  192. }
  193.  
  194. void arm_cfft_radix4by2_inverse_q31(
  195.     q31_t * pSrc,
  196.     uint32_t fftLen,
  197.     const q31_t * pCoef)
  198. {
  199.     uint32_t i, l;
  200.     uint32_t n2, ia;
  201.     q31_t xt, yt, cosVal, sinVal;
  202.     q31_t p0, p1;
  203.  
  204.     n2 = fftLen >> 1;
  205.     ia = 0;
  206.     for (i = 0; i < n2; i++)
  207.     {
  208.         cosVal = pCoef[2*ia];
  209.         sinVal = pCoef[2*ia + 1];
  210.         ia++;
  211.  
  212.         l = i + n2;
  213.         xt = (pSrc[2 * i] >> 2) - (pSrc[2 * l] >> 2);
  214.         pSrc[2 * i] = (pSrc[2 * i] >> 2) + (pSrc[2 * l] >> 2);
  215.  
  216.         yt = (pSrc[2 * i + 1] >> 2) - (pSrc[2 * l + 1] >> 2);
  217.         pSrc[2 * i + 1] = (pSrc[2 * l + 1] >> 2) + (pSrc[2 * i + 1] >> 2);
  218.  
  219.         mult_32x32_keep32_R(p0, xt, cosVal);
  220.         mult_32x32_keep32_R(p1, yt, cosVal);
  221.         multSub_32x32_keep32_R(p0, yt, sinVal);
  222.         multAcc_32x32_keep32_R(p1, xt, sinVal);
  223.  
  224.         pSrc[2U * l] = p0 << 1;
  225.         pSrc[2U * l + 1U] = p1 << 1;
  226.  
  227.     }
  228.  
  229.     // first col
  230.     arm_radix4_butterfly_inverse_q31( pSrc, n2, (q31_t*)pCoef, 2U);
  231.     // second col
  232.     arm_radix4_butterfly_inverse_q31( pSrc + fftLen, n2, (q31_t*)pCoef, 2U);
  233.  
  234.     for (i = 0; i < fftLen >> 1; i++)
  235.     {
  236.         p0 = pSrc[4*i+0];
  237.         p1 = pSrc[4*i+1];
  238.         xt = pSrc[4*i+2];
  239.         yt = pSrc[4*i+3];
  240.  
  241.         p0 <<= 1;
  242.         p1 <<= 1;
  243.         xt <<= 1;
  244.         yt <<= 1;
  245.  
  246.         pSrc[4*i+0] = p0;
  247.         pSrc[4*i+1] = p1;
  248.         pSrc[4*i+2] = xt;
  249.         pSrc[4*i+3] = yt;
  250.     }
  251. }
  252.  
  253.