Subversion Repositories DashDisplay

Rev

Rev 2 | Rev 49 | Go to most recent revision | 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_rfft_q31.c    
  9. *    
  10. * Description:  RFFT & RIFFT Q31 process function    
  11. *    
  12. *    
  13. * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
  14. *  
  15. * Redistribution and use in source and binary forms, with or without
  16. * modification, are permitted provided that the following conditions
  17. * are met:
  18. *   - Redistributions of source code must retain the above copyright
  19. *     notice, this list of conditions and the following disclaimer.
  20. *   - Redistributions in binary form must reproduce the above copyright
  21. *     notice, this list of conditions and the following disclaimer in
  22. *     the documentation and/or other materials provided with the
  23. *     distribution.
  24. *   - Neither the name of ARM LIMITED nor the names of its contributors
  25. *     may be used to endorse or promote products derived from this
  26. *     software without specific prior written permission.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  29. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  30. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  31. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  32. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  33. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  34. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  35. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  36. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  37. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  38. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  39. * POSSIBILITY OF SUCH DAMAGE.    
  40. * -------------------------------------------------------------------- */
  41.  
  42. #include "arm_math.h"
  43.  
  44. /*--------------------------------------------------------------------    
  45. *               Internal functions prototypes    
  46. --------------------------------------------------------------------*/
  47.  
  48. void arm_split_rfft_q31(
  49.     q31_t * pSrc,
  50.     uint32_t fftLen,
  51.     q31_t * pATable,
  52.     q31_t * pBTable,
  53.     q31_t * pDst,
  54.     uint32_t modifier);
  55.  
  56. void arm_split_rifft_q31(
  57.     q31_t * pSrc,
  58.     uint32_t fftLen,
  59.     q31_t * pATable,
  60.     q31_t * pBTable,
  61.     q31_t * pDst,
  62.     uint32_t modifier);
  63.  
  64. /**    
  65. * @addtogroup RealFFT    
  66. * @{    
  67. */
  68.  
  69. /**    
  70. * @brief Processing function for the Q31 RFFT/RIFFT.  
  71. * @param[in]  *S    points to an instance of the Q31 RFFT/RIFFT structure.  
  72. * @param[in]  *pSrc points to the input buffer.  
  73. * @param[out] *pDst points to the output buffer.  
  74. * @return none.  
  75. *    
  76. * \par Input an output formats:  
  77. * \par    
  78. * Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process.  
  79. * Hence the output format is different for different RFFT sizes.    
  80. * The input and output formats for different RFFT sizes and number of bits to upscale are mentioned in the tables below for RFFT and RIFFT:  
  81. * \par    
  82. * \image html RFFTQ31.gif "Input and Output Formats for Q31 RFFT"    
  83. *    
  84. * \par    
  85. * \image html RIFFTQ31.gif "Input and Output Formats for Q31 RIFFT"    
  86. */
  87. void arm_rfft_q31(
  88.     const arm_rfft_instance_q31 * S,
  89.     q31_t * pSrc,
  90.     q31_t * pDst)
  91. {
  92.     const arm_cfft_instance_q31 *S_CFFT = S->pCfft;
  93.     uint32_t i;
  94.     uint32_t L2 = S->fftLenReal >> 1;
  95.  
  96.     /* Calculation of RIFFT of input */
  97.     if(S->ifftFlagR == 1u)
  98.     {
  99.         /*  Real IFFT core process */
  100.         arm_split_rifft_q31(pSrc, L2, S->pTwiddleAReal,
  101.                             S->pTwiddleBReal, pDst, S->twidCoefRModifier);
  102.        
  103.         /* Complex IFFT process */
  104.         arm_cfft_q31(S_CFFT, pDst, S->ifftFlagR, S->bitReverseFlagR);
  105.        
  106.         for(i=0;i<S->fftLenReal;i++)
  107.         {
  108.             pDst[i] = pDst[i] << 1;
  109.         }
  110.     }
  111.     else
  112.     {
  113.         /* Calculation of RFFT of input */
  114.        
  115.         /* Complex FFT process */
  116.         arm_cfft_q31(S_CFFT, pSrc, S->ifftFlagR, S->bitReverseFlagR);
  117.  
  118.         /*  Real FFT core process */
  119.         arm_split_rfft_q31(pSrc, L2, S->pTwiddleAReal,
  120.                             S->pTwiddleBReal, pDst, S->twidCoefRModifier);
  121.     }
  122. }
  123.  
  124. /**    
  125. * @} end of RealFFT group    
  126. */
  127.  
  128. /**    
  129. * @brief  Core Real FFT process    
  130. * @param[in]   *pSrc                            points to the input buffer.    
  131. * @param[in]   fftLen                       length of FFT.  
  132. * @param[in]   *pATable                         points to the twiddle Coef A buffer.    
  133. * @param[in]   *pBTable                         points to the twiddle Coef B buffer.    
  134. * @param[out]  *pDst                            points to the output buffer.    
  135. * @param[in]   modifier                 twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.  
  136. * @return none.    
  137. */
  138. void arm_split_rfft_q31(
  139.     q31_t * pSrc,
  140.     uint32_t fftLen,
  141.     q31_t * pATable,
  142.     q31_t * pBTable,
  143.     q31_t * pDst,
  144.     uint32_t modifier)
  145. {
  146.     uint32_t i;                                    /* Loop Counter */
  147.     q31_t outR, outI;                              /* Temporary variables for output */
  148.     q31_t *pCoefA, *pCoefB;                        /* Temporary pointers for twiddle factors */
  149.     q31_t CoefA1, CoefA2, CoefB1;                  /* Temporary variables for twiddle coefficients */
  150.     q31_t *pOut1 = &pDst[2], *pOut2 = &pDst[(4u * fftLen) - 1u];
  151.     q31_t *pIn1 = &pSrc[2], *pIn2 = &pSrc[(2u * fftLen) - 1u];
  152.  
  153.     /* Init coefficient pointers */
  154.     pCoefA = &pATable[modifier * 2u];
  155.     pCoefB = &pBTable[modifier * 2u];
  156.  
  157.     i = fftLen - 1u;
  158.  
  159.     while(i > 0u)
  160.     {
  161.         /*    
  162.         outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]    
  163.         + pSrc[2 * n - 2 * i] * pBTable[2 * i] +    
  164.         pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);    
  165.         */
  166.  
  167.         /* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +    
  168.         pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -    
  169.         pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); */
  170.  
  171.         CoefA1 = *pCoefA++;
  172.         CoefA2 = *pCoefA;
  173.  
  174.         /* outR = (pSrc[2 * i] * pATable[2 * i] */    
  175.         mult_32x32_keep32_R(outR, *pIn1, CoefA1);
  176.  
  177.         /* outI = pIn[2 * i] * pATable[2 * i + 1] */
  178.         mult_32x32_keep32_R(outI, *pIn1++, CoefA2);
  179.  
  180.         /* - pSrc[2 * i + 1] * pATable[2 * i + 1] */
  181.         multSub_32x32_keep32_R(outR, *pIn1, CoefA2);
  182.  
  183.         /* (pIn[2 * i + 1] * pATable[2 * i] */
  184.         multAcc_32x32_keep32_R(outI, *pIn1++, CoefA1);
  185.  
  186.         /* pSrc[2 * n - 2 * i] * pBTable[2 * i]  */
  187.         multSub_32x32_keep32_R(outR, *pIn2, CoefA2);
  188.         CoefB1 = *pCoefB;
  189.  
  190.         /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
  191.         multSub_32x32_keep32_R(outI, *pIn2--, CoefB1);
  192.  
  193.         /* pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
  194.         multAcc_32x32_keep32_R(outR, *pIn2, CoefB1);
  195.  
  196.         /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
  197.         multSub_32x32_keep32_R(outI, *pIn2--, CoefA2);
  198.  
  199.         /* write output */
  200.         *pOut1++ = outR;
  201.         *pOut1++ = outI;
  202.  
  203.         /* write complex conjugate output */
  204.         *pOut2-- = -outI;
  205.         *pOut2-- = outR;
  206.  
  207.         /* update coefficient pointer */
  208.         pCoefB = pCoefB + (modifier * 2u);
  209.         pCoefA = pCoefA + ((modifier * 2u) - 1u);
  210.  
  211.         i--;
  212.     }
  213.     pDst[2u * fftLen] = (pSrc[0] - pSrc[1]) >> 1;
  214.     pDst[(2u * fftLen) + 1u] = 0;
  215.  
  216.     pDst[0] = (pSrc[0] + pSrc[1]) >> 1;
  217.     pDst[1] = 0;
  218. }
  219.  
  220. /**    
  221. * @brief  Core Real IFFT process    
  222. * @param[in]   *pSrc                            points to the input buffer.  
  223. * @param[in]   fftLen                       length of FFT.    
  224. * @param[in]   *pATable                         points to the twiddle Coef A buffer.  
  225. * @param[in]   *pBTable                         points to the twiddle Coef B buffer.    
  226. * @param[out]  *pDst                            points to the output buffer.  
  227. * @param[in]   modifier                 twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.  
  228. * @return none.    
  229. */
  230. void arm_split_rifft_q31(
  231.     q31_t * pSrc,
  232.     uint32_t fftLen,
  233.     q31_t * pATable,
  234.     q31_t * pBTable,
  235.     q31_t * pDst,
  236.     uint32_t modifier)
  237. {
  238.     q31_t outR, outI;                              /* Temporary variables for output */
  239.     q31_t *pCoefA, *pCoefB;                        /* Temporary pointers for twiddle factors */
  240.     q31_t CoefA1, CoefA2, CoefB1;                  /* Temporary variables for twiddle coefficients */
  241.     q31_t *pIn1 = &pSrc[0], *pIn2 = &pSrc[(2u * fftLen) + 1u];
  242.  
  243.     pCoefA = &pATable[0];
  244.     pCoefB = &pBTable[0];
  245.  
  246.     while(fftLen > 0u)
  247.     {
  248.         /*    
  249.         outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +    
  250.         pIn[2 * n - 2 * i] * pBTable[2 * i] -    
  251.         pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);    
  252.  
  253.         outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -    
  254.         pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -    
  255.         pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);  
  256.         */
  257.         CoefA1 = *pCoefA++;
  258.         CoefA2 = *pCoefA;
  259.  
  260.         /* outR = (pIn[2 * i] * pATable[2 * i] */
  261.         mult_32x32_keep32_R(outR, *pIn1, CoefA1);
  262.  
  263.         /* - pIn[2 * i] * pATable[2 * i + 1] */
  264.         mult_32x32_keep32_R(outI, *pIn1++, -CoefA2);
  265.        
  266.         /* pIn[2 * i + 1] * pATable[2 * i + 1] */
  267.         multAcc_32x32_keep32_R(outR, *pIn1, CoefA2);
  268.  
  269.         /* pIn[2 * i + 1] * pATable[2 * i] */
  270.         multAcc_32x32_keep32_R(outI, *pIn1++, CoefA1);
  271.  
  272.         /* pIn[2 * n - 2 * i] * pBTable[2 * i] */
  273.         multAcc_32x32_keep32_R(outR, *pIn2, CoefA2);
  274.         CoefB1 = *pCoefB;
  275.  
  276.         /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
  277.         multSub_32x32_keep32_R(outI, *pIn2--, CoefB1);
  278.  
  279.         /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
  280.         multAcc_32x32_keep32_R(outR, *pIn2, CoefB1);
  281.  
  282.         /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
  283.         multAcc_32x32_keep32_R(outI, *pIn2--, CoefA2);
  284.  
  285.         /* write output */
  286.         *pDst++ = outR;
  287.         *pDst++ = outI;
  288.  
  289.         /* update coefficient pointer */
  290.         pCoefB = pCoefB + (modifier * 2u);
  291.         pCoefA = pCoefA + ((modifier * 2u) - 1u);
  292.  
  293.         /* Decrement loop count */
  294.         fftLen--;
  295.     }
  296. }
  297.