Subversion Repositories DashDisplay

Rev

Rev 49 | 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_q15.c    
  9. *    
  10. * Description:  RFFT & RIFFT Q15 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_q15(
  49.     q15_t * pSrc,
  50.     uint32_t fftLen,
  51.     q15_t * pATable,
  52.     q15_t * pBTable,
  53.     q15_t * pDst,
  54.     uint32_t modifier);
  55.  
  56. void arm_split_rifft_q15(
  57.     q15_t * pSrc,
  58.     uint32_t fftLen,
  59.     q15_t * pATable,
  60.     q15_t * pBTable,
  61.     q15_t * pDst,
  62.     uint32_t modifier);
  63.  
  64. /**    
  65. * @addtogroup RealFFT    
  66. * @{    
  67. */
  68.  
  69. /**    
  70. * @brief Processing function for the Q15 RFFT/RIFFT.  
  71. * @param[in]  *S    points to an instance of the Q15 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 RFFTQ15.gif "Input and Output Formats for Q15 RFFT"    
  83. * \par    
  84. * \image html RIFFTQ15.gif "Input and Output Formats for Q15 RIFFT"    
  85. */
  86.  
  87. void arm_rfft_q15(
  88.     const arm_rfft_instance_q15 * S,
  89.     q15_t * pSrc,
  90.     q15_t * pDst)
  91. {
  92.     const arm_cfft_instance_q15 *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_q15(pSrc, L2, S->pTwiddleAReal,
  101.                             S->pTwiddleBReal, pDst, S->twidCoefRModifier);
  102.        
  103.         /* Complex IFFT process */
  104.         arm_cfft_q15(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_q15(S_CFFT, pSrc, S->ifftFlagR, S->bitReverseFlagR);
  117.  
  118.         /*  Real FFT core process */
  119.         arm_split_rfft_q15(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  *pSrc                                 points to the input buffer.  
  131. * @param  fftLen                                length of FFT.  
  132. * @param  *pATable                      points to the A twiddle Coef buffer.    
  133. * @param  *pBTable                      points to the B twiddle Coef buffer.  
  134. * @param  *pDst                                 points to the output buffer.  
  135. * @param  modifier              twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.  
  136. * @return none.    
  137. * The function implements a Real FFT    
  138. */
  139.  
  140. void arm_split_rfft_q15(
  141.     q15_t * pSrc,
  142.     uint32_t fftLen,
  143.     q15_t * pATable,
  144.     q15_t * pBTable,
  145.     q15_t * pDst,
  146.     uint32_t modifier)
  147. {
  148.     uint32_t i;                                    /* Loop Counter */
  149.     q31_t outR, outI;                              /* Temporary variables for output */
  150.     q15_t *pCoefA, *pCoefB;                        /* Temporary pointers for twiddle factors */
  151.     q15_t *pSrc1, *pSrc2;
  152. #ifndef ARM_MATH_CM0_FAMILY
  153.     q15_t *pD1, *pD2;
  154. #endif
  155.  
  156.     //  pSrc[2u * fftLen] = pSrc[0];
  157.     //  pSrc[(2u * fftLen) + 1u] = pSrc[1];
  158.  
  159.     pCoefA = &pATable[modifier * 2u];
  160.     pCoefB = &pBTable[modifier * 2u];
  161.  
  162.     pSrc1 = &pSrc[2];
  163.     pSrc2 = &pSrc[(2u * fftLen) - 2u];
  164.  
  165. #ifndef ARM_MATH_CM0_FAMILY
  166.  
  167.     /* Run the below code for Cortex-M4 and Cortex-M3 */
  168.     i = 1u;
  169.     pD1 = pDst + 2;
  170.     pD2 = pDst + (4u * fftLen) - 2;
  171.  
  172.     for(i = fftLen - 1; i > 0; i--)
  173.     {
  174.         /*    
  175.         outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]    
  176.         + pSrc[2 * n - 2 * i] * pBTable[2 * i] +    
  177.         pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);    
  178.         */
  179.  
  180.         /* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +    
  181.         pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -    
  182.         pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); */
  183.  
  184.  
  185. #ifndef ARM_MATH_BIG_ENDIAN
  186.  
  187.         /* pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1] */
  188.         outR = __SMUSD(*__SIMD32(pSrc1), *__SIMD32(pCoefA));
  189.  
  190. #else
  191.  
  192.         /* -(pSrc[2 * i + 1] * pATable[2 * i + 1] - pSrc[2 * i] * pATable[2 * i]) */
  193.         outR = -(__SMUSD(*__SIMD32(pSrc1), *__SIMD32(pCoefA)));
  194.  
  195. #endif /*      #ifndef ARM_MATH_BIG_ENDIAN     */
  196.  
  197.         /* pSrc[2 * n - 2 * i] * pBTable[2 * i] +    
  198.         pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]) */
  199.         outR = __SMLAD(*__SIMD32(pSrc2), *__SIMD32(pCoefB), outR) >> 16u;
  200.  
  201.         /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -    
  202.         pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
  203.  
  204. #ifndef ARM_MATH_BIG_ENDIAN
  205.  
  206.         outI = __SMUSDX(*__SIMD32(pSrc2)--, *__SIMD32(pCoefB));
  207.  
  208. #else
  209.  
  210.         outI = __SMUSDX(*__SIMD32(pCoefB), *__SIMD32(pSrc2)--);
  211.  
  212. #endif /*      #ifndef ARM_MATH_BIG_ENDIAN     */
  213.  
  214.         /* (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] */
  215.         outI = __SMLADX(*__SIMD32(pSrc1)++, *__SIMD32(pCoefA), outI);
  216.  
  217.         /* write output */
  218.         *pD1++ = (q15_t) outR;
  219.         *pD1++ = outI >> 16u;
  220.  
  221.         /* write complex conjugate output */
  222.         pD2[0] = (q15_t) outR;
  223.         pD2[1] = -(outI >> 16u);
  224.         pD2 -= 2;
  225.  
  226.         /* update coefficient pointer */
  227.         pCoefB = pCoefB + (2u * modifier);
  228.         pCoefA = pCoefA + (2u * modifier);
  229.     }
  230.  
  231.     pDst[2u * fftLen] = (pSrc[0] - pSrc[1]) >> 1;
  232.     pDst[(2u * fftLen) + 1u] = 0;
  233.  
  234.     pDst[0] = (pSrc[0] + pSrc[1]) >> 1;
  235.     pDst[1] = 0;
  236.  
  237. #else
  238.  
  239.     /* Run the below code for Cortex-M0 */
  240.     i = 1u;
  241.  
  242.     while(i < fftLen)
  243.     {
  244.         /*    
  245.         outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]    
  246.         + pSrc[2 * n - 2 * i] * pBTable[2 * i] +    
  247.         pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);    
  248.         */
  249.  
  250.         outR = *pSrc1 * *pCoefA;
  251.         outR = outR - (*(pSrc1 + 1) * *(pCoefA + 1));
  252.         outR = outR + (*pSrc2 * *pCoefB);
  253.         outR = (outR + (*(pSrc2 + 1) * *(pCoefB + 1))) >> 16;
  254.  
  255.  
  256.         /* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +    
  257.         pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -    
  258.         pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);  
  259.         */
  260.  
  261.         outI = *pSrc2 * *(pCoefB + 1);
  262.         outI = outI - (*(pSrc2 + 1) * *pCoefB);
  263.         outI = outI + (*(pSrc1 + 1) * *pCoefA);
  264.         outI = outI + (*pSrc1 * *(pCoefA + 1));
  265.  
  266.         /* update input pointers */
  267.         pSrc1 += 2u;
  268.         pSrc2 -= 2u;
  269.  
  270.         /* write output */
  271.         pDst[2u * i] = (q15_t) outR;
  272.         pDst[(2u * i) + 1u] = outI >> 16u;
  273.  
  274.         /* write complex conjugate output */
  275.         pDst[(4u * fftLen) - (2u * i)] = (q15_t) outR;
  276.         pDst[((4u * fftLen) - (2u * i)) + 1u] = -(outI >> 16u);
  277.  
  278.         /* update coefficient pointer */
  279.         pCoefB = pCoefB + (2u * modifier);
  280.         pCoefA = pCoefA + (2u * modifier);
  281.  
  282.         i++;
  283.     }
  284.  
  285.     pDst[2u * fftLen] = (pSrc[0] - pSrc[1]) >> 1;
  286.     pDst[(2u * fftLen) + 1u] = 0;
  287.  
  288.     pDst[0] = (pSrc[0] + pSrc[1]) >> 1;
  289.     pDst[1] = 0;
  290.  
  291. #endif /* #ifndef ARM_MATH_CM0_FAMILY */
  292. }
  293.  
  294.  
  295. /**    
  296. * @brief  Core Real IFFT process    
  297. * @param[in]   *pSrc                            points to the input buffer.    
  298. * @param[in]   fftLen               length of FFT.  
  299. * @param[in]   *pATable                         points to the twiddle Coef A buffer.  
  300. * @param[in]   *pBTable                         points to the twiddle Coef B buffer.    
  301. * @param[out]  *pDst                            points to the output buffer.  
  302. * @param[in]   modifier                 twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.  
  303. * @return none.    
  304. * The function implements a Real IFFT    
  305. */
  306. void arm_split_rifft_q15(
  307.     q15_t * pSrc,
  308.     uint32_t fftLen,
  309.     q15_t * pATable,
  310.     q15_t * pBTable,
  311.     q15_t * pDst,
  312.     uint32_t modifier)
  313. {
  314.     uint32_t i;                                    /* Loop Counter */
  315.     q31_t outR, outI;                              /* Temporary variables for output */
  316.     q15_t *pCoefA, *pCoefB;                        /* Temporary pointers for twiddle factors */
  317.     q15_t *pSrc1, *pSrc2;
  318.     q15_t *pDst1 = &pDst[0];
  319.  
  320.     pCoefA = &pATable[0];
  321.     pCoefB = &pBTable[0];
  322.  
  323.     pSrc1 = &pSrc[0];
  324.     pSrc2 = &pSrc[2u * fftLen];
  325.  
  326. #ifndef ARM_MATH_CM0_FAMILY
  327.  
  328.     /* Run the below code for Cortex-M4 and Cortex-M3 */
  329.     i = fftLen;
  330.  
  331.     while(i > 0u)
  332.     {
  333.         /*    
  334.         outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +    
  335.         pIn[2 * n - 2 * i] * pBTable[2 * i] -    
  336.         pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);    
  337.  
  338.         outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -    
  339.         pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -    
  340.         pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);    
  341.         */
  342.  
  343.  
  344. #ifndef ARM_MATH_BIG_ENDIAN
  345.  
  346.         /* pIn[2 * n - 2 * i] * pBTable[2 * i] -    
  347.         pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]) */
  348.         outR = __SMUSD(*__SIMD32(pSrc2), *__SIMD32(pCoefB));
  349.  
  350. #else
  351.  
  352.         /* -(-pIn[2 * n - 2 * i] * pBTable[2 * i] +  
  353.         pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1])) */
  354.         outR = -(__SMUSD(*__SIMD32(pSrc2), *__SIMD32(pCoefB)));
  355.  
  356. #endif /*      #ifndef ARM_MATH_BIG_ENDIAN     */
  357.  
  358.         /* pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +    
  359.         pIn[2 * n - 2 * i] * pBTable[2 * i] */
  360.         outR = __SMLAD(*__SIMD32(pSrc1), *__SIMD32(pCoefA), outR) >> 16u;
  361.  
  362.         /*    
  363.         -pIn[2 * n - 2 * i] * pBTable[2 * i + 1] +    
  364.         pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
  365.         outI = __SMUADX(*__SIMD32(pSrc2)--, *__SIMD32(pCoefB));
  366.  
  367.         /* pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] */
  368.  
  369. #ifndef ARM_MATH_BIG_ENDIAN
  370.  
  371.         outI = __SMLSDX(*__SIMD32(pCoefA), *__SIMD32(pSrc1)++, -outI);
  372.  
  373. #else
  374.  
  375.         outI = __SMLSDX(*__SIMD32(pSrc1)++, *__SIMD32(pCoefA), -outI);
  376.  
  377. #endif /*      #ifndef ARM_MATH_BIG_ENDIAN     */
  378.         /* write output */
  379.  
  380. #ifndef ARM_MATH_BIG_ENDIAN
  381.  
  382.         *__SIMD32(pDst1)++ = __PKHBT(outR, (outI >> 16u), 16);
  383.  
  384. #else
  385.  
  386.         *__SIMD32(pDst1)++ = __PKHBT((outI >> 16u), outR, 16);
  387.  
  388. #endif /*      #ifndef ARM_MATH_BIG_ENDIAN     */
  389.  
  390.         /* update coefficient pointer */
  391.         pCoefB = pCoefB + (2u * modifier);
  392.         pCoefA = pCoefA + (2u * modifier);
  393.  
  394.         i--;
  395.     }
  396. #else
  397.     /* Run the below code for Cortex-M0 */
  398.     i = fftLen;
  399.  
  400.     while(i > 0u)
  401.     {
  402.         /*    
  403.         outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +    
  404.         pIn[2 * n - 2 * i] * pBTable[2 * i] -    
  405.         pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);    
  406.         */
  407.  
  408.         outR = *pSrc2 * *pCoefB;
  409.         outR = outR - (*(pSrc2 + 1) * *(pCoefB + 1));
  410.         outR = outR + (*pSrc1 * *pCoefA);
  411.         outR = (outR + (*(pSrc1 + 1) * *(pCoefA + 1))) >> 16;
  412.  
  413.         /*  
  414.         outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -  
  415.         pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -  
  416.         pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);  
  417.         */
  418.  
  419.         outI = *(pSrc1 + 1) * *pCoefA;
  420.         outI = outI - (*pSrc1 * *(pCoefA + 1));
  421.         outI = outI - (*pSrc2 * *(pCoefB + 1));
  422.         outI = outI - (*(pSrc2 + 1) * *(pCoefB));
  423.  
  424.         /* update input pointers */
  425.         pSrc1 += 2u;
  426.         pSrc2 -= 2u;
  427.  
  428.         /* write output */
  429.         *pDst1++ = (q15_t) outR;
  430.         *pDst1++ = (q15_t) (outI >> 16);
  431.  
  432.         /* update coefficient pointer */
  433.         pCoefB = pCoefB + (2u * modifier);
  434.         pCoefA = pCoefA + (2u * modifier);
  435.  
  436.         i--;
  437.     }
  438. #endif /* #ifndef ARM_MATH_CM0_FAMILY */
  439. }
  440.