CMSIS DSP library

Dependents:   performance_timer Surfboard_ gps2rtty Capstone ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_cfft_q31.c Source File

arm_cfft_q31.c

00001 /* ----------------------------------------------------------------------    
00002 * Copyright (C) 2010-2014 ARM Limited. All rights reserved.    
00003 *    
00004 * $Date:        19. March 2015 
00005 * $Revision:    V.1.4.5  
00006 *    
00007 * Project:      CMSIS DSP Library    
00008 * Title:        arm_cfft_q31.c   
00009 *    
00010 * Description:  Combined Radix Decimation in Frequency CFFT fixed point processing function
00011 *    
00012 * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
00013 *  
00014 * Redistribution and use in source and binary forms, with or without 
00015 * modification, are permitted provided that the following conditions
00016 * are met:
00017 *   - Redistributions of source code must retain the above copyright
00018 *     notice, this list of conditions and the following disclaimer.
00019 *   - Redistributions in binary form must reproduce the above copyright
00020 *     notice, this list of conditions and the following disclaimer in
00021 *     the documentation and/or other materials provided with the 
00022 *     distribution.
00023 *   - Neither the name of ARM LIMITED nor the names of its contributors
00024 *     may be used to endorse or promote products derived from this
00025 *     software without specific prior written permission.
00026 *
00027 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00028 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00029 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00030 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
00031 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00032 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00033 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00034 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00035 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00036 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00037 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00038 * POSSIBILITY OF SUCH DAMAGE.   
00039 * -------------------------------------------------------------------- */
00040 
00041 #include "arm_math.h"
00042 
00043 extern void arm_radix4_butterfly_q31(
00044     q31_t * pSrc,
00045     uint32_t fftLen,
00046     q31_t * pCoef,
00047     uint32_t twidCoefModifier);
00048 
00049 extern void arm_radix4_butterfly_inverse_q31(
00050     q31_t * pSrc,
00051     uint32_t fftLen,
00052     q31_t * pCoef,
00053     uint32_t twidCoefModifier);
00054 
00055 extern void arm_bitreversal_32(
00056     uint32_t * pSrc,
00057     const uint16_t bitRevLen,
00058     const uint16_t * pBitRevTable);
00059     
00060 void arm_cfft_radix4by2_q31(
00061     q31_t * pSrc,
00062     uint32_t fftLen,
00063     const q31_t * pCoef);
00064     
00065 void arm_cfft_radix4by2_inverse_q31(
00066     q31_t * pSrc,
00067     uint32_t fftLen,
00068     const q31_t * pCoef);
00069 
00070 /**   
00071 * @ingroup groupTransforms   
00072 */
00073 
00074 /**
00075 * @addtogroup ComplexFFT   
00076 * @{   
00077 */
00078 
00079 /**   
00080 * @details   
00081 * @brief       Processing function for the fixed-point complex FFT in Q31 format.
00082 * @param[in]      *S    points to an instance of the fixed-point CFFT structure.  
00083 * @param[in, out] *p1   points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place.  
00084 * @param[in]     ifftFlag       flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.  
00085 * @param[in]     bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.  
00086 * @return none.  
00087 */
00088 
00089 void arm_cfft_q31( 
00090     const arm_cfft_instance_q31 * S, 
00091     q31_t * p1,
00092     uint8_t ifftFlag,
00093     uint8_t bitReverseFlag)
00094 {
00095     uint32_t L = S->fftLen;
00096 
00097     if(ifftFlag == 1u)
00098     {
00099         switch (L) 
00100         {
00101         case 16: 
00102         case 64:
00103         case 256:
00104         case 1024:
00105         case 4096:
00106             arm_radix4_butterfly_inverse_q31  ( p1, L, (q31_t*)S->pTwiddle, 1 );
00107             break;
00108             
00109         case 32:
00110         case 128:
00111         case 512:
00112         case 2048:
00113             arm_cfft_radix4by2_inverse_q31  ( p1, L, S->pTwiddle );
00114             break;
00115         }  
00116     }
00117     else
00118     {
00119         switch (L) 
00120         {
00121         case 16: 
00122         case 64:
00123         case 256:
00124         case 1024:
00125         case 4096:
00126             arm_radix4_butterfly_q31  ( p1, L, (q31_t*)S->pTwiddle, 1 );
00127             break;
00128             
00129         case 32:
00130         case 128:
00131         case 512:
00132         case 2048:
00133             arm_cfft_radix4by2_q31  ( p1, L, S->pTwiddle );
00134             break;
00135         }  
00136     }
00137     
00138     if( bitReverseFlag )
00139         arm_bitreversal_32((uint32_t*)p1,S->bitRevLength,S->pBitRevTable);    
00140 }
00141 
00142 /**    
00143 * @} end of ComplexFFT group    
00144 */
00145 
00146 void arm_cfft_radix4by2_q31(
00147     q31_t * pSrc,
00148     uint32_t fftLen,
00149     const q31_t * pCoef) 
00150 {    
00151     uint32_t i, l;
00152     uint32_t n2, ia;
00153     q31_t xt, yt, cosVal, sinVal;
00154     q31_t p0, p1;
00155     
00156     n2 = fftLen >> 1;    
00157     ia = 0;
00158     for (i = 0; i < n2; i++)
00159     {
00160         cosVal = pCoef[2*ia];
00161         sinVal = pCoef[2*ia + 1];
00162         ia++;
00163         
00164         l = i + n2;
00165         xt = (pSrc[2 * i] >> 2) - (pSrc[2 * l] >> 2);
00166         pSrc[2 * i] = (pSrc[2 * i] >> 2) + (pSrc[2 * l] >> 2);
00167         
00168         yt = (pSrc[2 * i + 1] >> 2) - (pSrc[2 * l + 1] >> 2);
00169         pSrc[2 * i + 1] = (pSrc[2 * l + 1] >> 2) + (pSrc[2 * i + 1] >> 2);
00170         
00171         mult_32x32_keep32_R(p0, xt, cosVal);
00172         mult_32x32_keep32_R(p1, yt, cosVal);
00173         multAcc_32x32_keep32_R(p0, yt, sinVal); 
00174         multSub_32x32_keep32_R(p1, xt, sinVal);
00175         
00176         pSrc[2u * l] = p0 << 1;
00177         pSrc[2u * l + 1u] = p1 << 1;
00178     
00179     }
00180 
00181     // first col
00182     arm_radix4_butterfly_q31( pSrc, n2, (q31_t*)pCoef, 2u);
00183     // second col
00184     arm_radix4_butterfly_q31( pSrc + fftLen, n2, (q31_t*)pCoef, 2u);
00185             
00186     for (i = 0; i < fftLen >> 1; i++)
00187     {
00188         p0 = pSrc[4*i+0];
00189         p1 = pSrc[4*i+1];
00190         xt = pSrc[4*i+2];
00191         yt = pSrc[4*i+3];
00192         
00193         p0 <<= 1;
00194         p1 <<= 1;
00195         xt <<= 1;
00196         yt <<= 1;
00197         
00198         pSrc[4*i+0] = p0;
00199         pSrc[4*i+1] = p1;
00200         pSrc[4*i+2] = xt;
00201         pSrc[4*i+3] = yt;
00202     }
00203 
00204 }
00205 
00206 void arm_cfft_radix4by2_inverse_q31(
00207     q31_t * pSrc,
00208     uint32_t fftLen,
00209     const q31_t * pCoef) 
00210 {    
00211     uint32_t i, l;
00212     uint32_t n2, ia;
00213     q31_t xt, yt, cosVal, sinVal;
00214     q31_t p0, p1;
00215     
00216     n2 = fftLen >> 1;    
00217     ia = 0;
00218     for (i = 0; i < n2; i++)
00219     {
00220         cosVal = pCoef[2*ia];
00221         sinVal = pCoef[2*ia + 1];
00222         ia++;
00223         
00224         l = i + n2;
00225         xt = (pSrc[2 * i] >> 2) - (pSrc[2 * l] >> 2);
00226         pSrc[2 * i] = (pSrc[2 * i] >> 2) + (pSrc[2 * l] >> 2);
00227         
00228         yt = (pSrc[2 * i + 1] >> 2) - (pSrc[2 * l + 1] >> 2);
00229         pSrc[2 * i + 1] = (pSrc[2 * l + 1] >> 2) + (pSrc[2 * i + 1] >> 2);
00230         
00231         mult_32x32_keep32_R(p0, xt, cosVal);
00232         mult_32x32_keep32_R(p1, yt, cosVal);
00233         multSub_32x32_keep32_R(p0, yt, sinVal); 
00234         multAcc_32x32_keep32_R(p1, xt, sinVal);
00235         
00236         pSrc[2u * l] = p0 << 1;
00237         pSrc[2u * l + 1u] = p1 << 1;
00238     
00239     }
00240 
00241     // first col
00242     arm_radix4_butterfly_inverse_q31( pSrc, n2, (q31_t*)pCoef, 2u);
00243     // second col
00244     arm_radix4_butterfly_inverse_q31( pSrc + fftLen, n2, (q31_t*)pCoef, 2u);
00245             
00246     for (i = 0; i < fftLen >> 1; i++)
00247     {
00248         p0 = pSrc[4*i+0];
00249         p1 = pSrc[4*i+1];
00250         xt = pSrc[4*i+2];
00251         yt = pSrc[4*i+3];
00252         
00253         p0 <<= 1;
00254         p1 <<= 1;
00255         xt <<= 1;
00256         yt <<= 1;
00257         
00258         pSrc[4*i+0] = p0;
00259         pSrc[4*i+1] = p1;
00260         pSrc[4*i+2] = xt;
00261         pSrc[4*i+3] = yt;
00262     }
00263 }
00264