CMSIS DSP library
Dependents: performance_timer Surfboard_ gps2rtty Capstone ... more
arm_cfft_radix8_f32.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_radix8_f32.c 00009 * 00010 * Description: Radix-8 Decimation in Frequency CFFT & CIFFT Floating 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 /** 00044 * @ingroup groupTransforms 00045 */ 00046 00047 /** 00048 * @defgroup Radix8_CFFT_CIFFT Radix-8 Complex FFT Functions 00049 * 00050 * \par 00051 * Complex Fast Fourier Transform(CFFT) and Complex Inverse Fast Fourier Transform(CIFFT) is an efficient algorithm to compute Discrete Fourier Transform(DFT) and Inverse Discrete Fourier Transform(IDFT). 00052 * Computational complexity of CFFT reduces drastically when compared to DFT. 00053 * \par 00054 * This set of functions implements CFFT/CIFFT 00055 * for floating-point data types. The functions operates on in-place buffer which uses same buffer for input and output. 00056 * Complex input is stored in input buffer in an interleaved fashion. 00057 * 00058 * \par 00059 * The functions operate on blocks of input and output data and each call to the function processes 00060 * <code>2*fftLen</code> samples through the transform. <code>pSrc</code> points to In-place arrays containing <code>2*fftLen</code> values. 00061 * \par 00062 * The <code>pSrc</code> points to the array of in-place buffer of size <code>2*fftLen</code> and inputs and outputs are stored in an interleaved fashion as shown below. 00063 * <pre> {real[0], imag[0], real[1], imag[1],..} </pre> 00064 * 00065 * \par Lengths supported by the transform: 00066 * \par 00067 * Internally, the function utilize a Radix-8 decimation in frequency(DIF) algorithm 00068 * and the size of the FFT supported are of the lengths [ 64, 512, 4096]. 00069 * 00070 * 00071 * \par Algorithm: 00072 * 00073 * <b>Complex Fast Fourier Transform:</b> 00074 * \par 00075 * Input real and imaginary data: 00076 * <pre> 00077 * x(n) = xa + j * ya 00078 * x(n+N/4 ) = xb + j * yb 00079 * x(n+N/2 ) = xc + j * yc 00080 * x(n+3N 4) = xd + j * yd 00081 * </pre> 00082 * where N is length of FFT 00083 * \par 00084 * Output real and imaginary data: 00085 * <pre> 00086 * X(4r) = xa'+ j * ya' 00087 * X(4r+1) = xb'+ j * yb' 00088 * X(4r+2) = xc'+ j * yc' 00089 * X(4r+3) = xd'+ j * yd' 00090 * </pre> 00091 * \par 00092 * Twiddle factors for Radix-8 FFT: 00093 * <pre> 00094 * Wn = co1 + j * (- si1) 00095 * W2n = co2 + j * (- si2) 00096 * W3n = co3 + j * (- si3) 00097 * </pre> 00098 * 00099 * \par 00100 * \image html CFFT.gif "Radix-8 Decimation-in Frequency Complex Fast Fourier Transform" 00101 * 00102 * \par 00103 * Output from Radix-8 CFFT Results in Digit reversal order. Interchange middle two branches of every butterfly results in Bit reversed output. 00104 * \par 00105 * <b> Butterfly CFFT equations:</b> 00106 * <pre> 00107 * xa' = xa + xb + xc + xd 00108 * ya' = ya + yb + yc + yd 00109 * xc' = (xa+yb-xc-yd)* co1 + (ya-xb-yc+xd)* (si1) 00110 * yc' = (ya-xb-yc+xd)* co1 - (xa+yb-xc-yd)* (si1) 00111 * xb' = (xa-xb+xc-xd)* co2 + (ya-yb+yc-yd)* (si2) 00112 * yb' = (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) 00113 * xd' = (xa-yb-xc+yd)* co3 + (ya+xb-yc-xd)* (si3) 00114 * yd' = (ya+xb-yc-xd)* co3 - (xa-yb-xc+yd)* (si3) 00115 * </pre> 00116 * 00117 * \par 00118 * where <code>fftLen</code> length of CFFT/CIFFT; <code>ifftFlag</code> Flag for selection of CFFT or CIFFT(Set ifftFlag to calculate CIFFT otherwise calculates CFFT); 00119 * <code>bitReverseFlag</code> Flag for selection of output order(Set bitReverseFlag to output in normal order otherwise output in bit reversed order); 00120 * <code>pTwiddle</code>points to array of twiddle coefficients; <code>pBitRevTable</code> points to the array of bit reversal table. 00121 * <code>twidCoefModifier</code> modifier for twiddle factor table which supports all FFT lengths with same table; 00122 * <code>pBitRevTable</code> modifier for bit reversal table which supports all FFT lengths with same table. 00123 * <code>onebyfftLen</code> value of 1/fftLen to calculate CIFFT; 00124 * 00125 * \par Fixed-Point Behavior 00126 * Care must be taken when using the fixed-point versions of the CFFT/CIFFT function. 00127 * Refer to the function specific documentation below for usage guidelines. 00128 */ 00129 00130 00131 /* 00132 * @brief Core function for the floating-point CFFT butterfly process. 00133 * @param[in, out] *pSrc points to the in-place buffer of floating-point data type. 00134 * @param[in] fftLen length of the FFT. 00135 * @param[in] *pCoef points to the twiddle coefficient buffer. 00136 * @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. 00137 * @return none. 00138 */ 00139 00140 void arm_radix8_butterfly_f32( 00141 float32_t * pSrc, 00142 uint16_t fftLen, 00143 const float32_t * pCoef, 00144 uint16_t twidCoefModifier) 00145 { 00146 uint32_t ia1, ia2, ia3, ia4, ia5, ia6, ia7; 00147 uint32_t i1, i2, i3, i4, i5, i6, i7, i8; 00148 uint32_t id; 00149 uint32_t n1, n2, j; 00150 00151 float32_t r1, r2, r3, r4, r5, r6, r7, r8; 00152 float32_t t1, t2; 00153 float32_t s1, s2, s3, s4, s5, s6, s7, s8; 00154 float32_t p1, p2, p3, p4; 00155 float32_t co2, co3, co4, co5, co6, co7, co8; 00156 float32_t si2, si3, si4, si5, si6, si7, si8; 00157 const float32_t C81 = 0.70710678118f; 00158 00159 n2 = fftLen; 00160 00161 do 00162 { 00163 n1 = n2; 00164 n2 = n2 >> 3; 00165 i1 = 0; 00166 00167 do 00168 { 00169 i2 = i1 + n2; 00170 i3 = i2 + n2; 00171 i4 = i3 + n2; 00172 i5 = i4 + n2; 00173 i6 = i5 + n2; 00174 i7 = i6 + n2; 00175 i8 = i7 + n2; 00176 r1 = pSrc[2 * i1] + pSrc[2 * i5]; 00177 r5 = pSrc[2 * i1] - pSrc[2 * i5]; 00178 r2 = pSrc[2 * i2] + pSrc[2 * i6]; 00179 r6 = pSrc[2 * i2] - pSrc[2 * i6]; 00180 r3 = pSrc[2 * i3] + pSrc[2 * i7]; 00181 r7 = pSrc[2 * i3] - pSrc[2 * i7]; 00182 r4 = pSrc[2 * i4] + pSrc[2 * i8]; 00183 r8 = pSrc[2 * i4] - pSrc[2 * i8]; 00184 t1 = r1 - r3; 00185 r1 = r1 + r3; 00186 r3 = r2 - r4; 00187 r2 = r2 + r4; 00188 pSrc[2 * i1] = r1 + r2; 00189 pSrc[2 * i5] = r1 - r2; 00190 r1 = pSrc[2 * i1 + 1] + pSrc[2 * i5 + 1]; 00191 s5 = pSrc[2 * i1 + 1] - pSrc[2 * i5 + 1]; 00192 r2 = pSrc[2 * i2 + 1] + pSrc[2 * i6 + 1]; 00193 s6 = pSrc[2 * i2 + 1] - pSrc[2 * i6 + 1]; 00194 s3 = pSrc[2 * i3 + 1] + pSrc[2 * i7 + 1]; 00195 s7 = pSrc[2 * i3 + 1] - pSrc[2 * i7 + 1]; 00196 r4 = pSrc[2 * i4 + 1] + pSrc[2 * i8 + 1]; 00197 s8 = pSrc[2 * i4 + 1] - pSrc[2 * i8 + 1]; 00198 t2 = r1 - s3; 00199 r1 = r1 + s3; 00200 s3 = r2 - r4; 00201 r2 = r2 + r4; 00202 pSrc[2 * i1 + 1] = r1 + r2; 00203 pSrc[2 * i5 + 1] = r1 - r2; 00204 pSrc[2 * i3] = t1 + s3; 00205 pSrc[2 * i7] = t1 - s3; 00206 pSrc[2 * i3 + 1] = t2 - r3; 00207 pSrc[2 * i7 + 1] = t2 + r3; 00208 r1 = (r6 - r8) * C81; 00209 r6 = (r6 + r8) * C81; 00210 r2 = (s6 - s8) * C81; 00211 s6 = (s6 + s8) * C81; 00212 t1 = r5 - r1; 00213 r5 = r5 + r1; 00214 r8 = r7 - r6; 00215 r7 = r7 + r6; 00216 t2 = s5 - r2; 00217 s5 = s5 + r2; 00218 s8 = s7 - s6; 00219 s7 = s7 + s6; 00220 pSrc[2 * i2] = r5 + s7; 00221 pSrc[2 * i8] = r5 - s7; 00222 pSrc[2 * i6] = t1 + s8; 00223 pSrc[2 * i4] = t1 - s8; 00224 pSrc[2 * i2 + 1] = s5 - r7; 00225 pSrc[2 * i8 + 1] = s5 + r7; 00226 pSrc[2 * i6 + 1] = t2 - r8; 00227 pSrc[2 * i4 + 1] = t2 + r8; 00228 00229 i1 += n1; 00230 } while(i1 < fftLen); 00231 00232 if(n2 < 8) 00233 break; 00234 00235 ia1 = 0; 00236 j = 1; 00237 00238 do 00239 { 00240 /* index calculation for the coefficients */ 00241 id = ia1 + twidCoefModifier; 00242 ia1 = id; 00243 ia2 = ia1 + id; 00244 ia3 = ia2 + id; 00245 ia4 = ia3 + id; 00246 ia5 = ia4 + id; 00247 ia6 = ia5 + id; 00248 ia7 = ia6 + id; 00249 00250 co2 = pCoef[2 * ia1]; 00251 co3 = pCoef[2 * ia2]; 00252 co4 = pCoef[2 * ia3]; 00253 co5 = pCoef[2 * ia4]; 00254 co6 = pCoef[2 * ia5]; 00255 co7 = pCoef[2 * ia6]; 00256 co8 = pCoef[2 * ia7]; 00257 si2 = pCoef[2 * ia1 + 1]; 00258 si3 = pCoef[2 * ia2 + 1]; 00259 si4 = pCoef[2 * ia3 + 1]; 00260 si5 = pCoef[2 * ia4 + 1]; 00261 si6 = pCoef[2 * ia5 + 1]; 00262 si7 = pCoef[2 * ia6 + 1]; 00263 si8 = pCoef[2 * ia7 + 1]; 00264 00265 i1 = j; 00266 00267 do 00268 { 00269 /* index calculation for the input */ 00270 i2 = i1 + n2; 00271 i3 = i2 + n2; 00272 i4 = i3 + n2; 00273 i5 = i4 + n2; 00274 i6 = i5 + n2; 00275 i7 = i6 + n2; 00276 i8 = i7 + n2; 00277 r1 = pSrc[2 * i1] + pSrc[2 * i5]; 00278 r5 = pSrc[2 * i1] - pSrc[2 * i5]; 00279 r2 = pSrc[2 * i2] + pSrc[2 * i6]; 00280 r6 = pSrc[2 * i2] - pSrc[2 * i6]; 00281 r3 = pSrc[2 * i3] + pSrc[2 * i7]; 00282 r7 = pSrc[2 * i3] - pSrc[2 * i7]; 00283 r4 = pSrc[2 * i4] + pSrc[2 * i8]; 00284 r8 = pSrc[2 * i4] - pSrc[2 * i8]; 00285 t1 = r1 - r3; 00286 r1 = r1 + r3; 00287 r3 = r2 - r4; 00288 r2 = r2 + r4; 00289 pSrc[2 * i1] = r1 + r2; 00290 r2 = r1 - r2; 00291 s1 = pSrc[2 * i1 + 1] + pSrc[2 * i5 + 1]; 00292 s5 = pSrc[2 * i1 + 1] - pSrc[2 * i5 + 1]; 00293 s2 = pSrc[2 * i2 + 1] + pSrc[2 * i6 + 1]; 00294 s6 = pSrc[2 * i2 + 1] - pSrc[2 * i6 + 1]; 00295 s3 = pSrc[2 * i3 + 1] + pSrc[2 * i7 + 1]; 00296 s7 = pSrc[2 * i3 + 1] - pSrc[2 * i7 + 1]; 00297 s4 = pSrc[2 * i4 + 1] + pSrc[2 * i8 + 1]; 00298 s8 = pSrc[2 * i4 + 1] - pSrc[2 * i8 + 1]; 00299 t2 = s1 - s3; 00300 s1 = s1 + s3; 00301 s3 = s2 - s4; 00302 s2 = s2 + s4; 00303 r1 = t1 + s3; 00304 t1 = t1 - s3; 00305 pSrc[2 * i1 + 1] = s1 + s2; 00306 s2 = s1 - s2; 00307 s1 = t2 - r3; 00308 t2 = t2 + r3; 00309 p1 = co5 * r2; 00310 p2 = si5 * s2; 00311 p3 = co5 * s2; 00312 p4 = si5 * r2; 00313 pSrc[2 * i5] = p1 + p2; 00314 pSrc[2 * i5 + 1] = p3 - p4; 00315 p1 = co3 * r1; 00316 p2 = si3 * s1; 00317 p3 = co3 * s1; 00318 p4 = si3 * r1; 00319 pSrc[2 * i3] = p1 + p2; 00320 pSrc[2 * i3 + 1] = p3 - p4; 00321 p1 = co7 * t1; 00322 p2 = si7 * t2; 00323 p3 = co7 * t2; 00324 p4 = si7 * t1; 00325 pSrc[2 * i7] = p1 + p2; 00326 pSrc[2 * i7 + 1] = p3 - p4; 00327 r1 = (r6 - r8) * C81; 00328 r6 = (r6 + r8) * C81; 00329 s1 = (s6 - s8) * C81; 00330 s6 = (s6 + s8) * C81; 00331 t1 = r5 - r1; 00332 r5 = r5 + r1; 00333 r8 = r7 - r6; 00334 r7 = r7 + r6; 00335 t2 = s5 - s1; 00336 s5 = s5 + s1; 00337 s8 = s7 - s6; 00338 s7 = s7 + s6; 00339 r1 = r5 + s7; 00340 r5 = r5 - s7; 00341 r6 = t1 + s8; 00342 t1 = t1 - s8; 00343 s1 = s5 - r7; 00344 s5 = s5 + r7; 00345 s6 = t2 - r8; 00346 t2 = t2 + r8; 00347 p1 = co2 * r1; 00348 p2 = si2 * s1; 00349 p3 = co2 * s1; 00350 p4 = si2 * r1; 00351 pSrc[2 * i2] = p1 + p2; 00352 pSrc[2 * i2 + 1] = p3 - p4; 00353 p1 = co8 * r5; 00354 p2 = si8 * s5; 00355 p3 = co8 * s5; 00356 p4 = si8 * r5; 00357 pSrc[2 * i8] = p1 + p2; 00358 pSrc[2 * i8 + 1] = p3 - p4; 00359 p1 = co6 * r6; 00360 p2 = si6 * s6; 00361 p3 = co6 * s6; 00362 p4 = si6 * r6; 00363 pSrc[2 * i6] = p1 + p2; 00364 pSrc[2 * i6 + 1] = p3 - p4; 00365 p1 = co4 * t1; 00366 p2 = si4 * t2; 00367 p3 = co4 * t2; 00368 p4 = si4 * t1; 00369 pSrc[2 * i4] = p1 + p2; 00370 pSrc[2 * i4 + 1] = p3 - p4; 00371 00372 i1 += n1; 00373 } while(i1 < fftLen); 00374 00375 j++; 00376 } while(j < n2); 00377 00378 twidCoefModifier <<= 3; 00379 } while(n2 > 7); 00380 } 00381 00382 /** 00383 * @} end of Radix8_CFFT_CIFFT group 00384 */
Generated on Tue Jul 12 2022 11:59:15 by 1.7.2