Subversion Repositories DashDisplay

Rev

Rev 28 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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