arm_cfft_radix2_q31.c
1 /* ---------------------------------------------------------------------- 2 * Project: CMSIS DSP Library 3 * Title: arm_cfft_radix2_q31.c 4 * Description: Radix-2 Decimation in Frequency CFFT & CIFFT Fixed point processing function 5 * 6 * $Date: 23 April 2021 7 * $Revision: V1.9.0 8 * 9 * Target Processor: Cortex-M and Cortex-A cores 10 * -------------------------------------------------------------------- */ 11 /* 12 * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. 13 * 14 * SPDX-License-Identifier: Apache-2.0 15 * 16 * Licensed under the Apache License, Version 2.0 (the License); you may 17 * not use this file except in compliance with the License. 18 * You may obtain a copy of the License at 19 * 20 * www.apache.org/licenses/LICENSE-2.0 21 * 22 * Unless required by applicable law or agreed to in writing, software 23 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 24 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25 * See the License for the specific language governing permissions and 26 * limitations under the License. 27 */ 28 29 #include "dsp/transform_functions.h" 30 31 void arm_radix2_butterfly_q31( 32 q31_t * pSrc, 33 uint32_t fftLen, 34 const q31_t * pCoef, 35 uint16_t twidCoefModifier); 36 37 void arm_radix2_butterfly_inverse_q31( 38 q31_t * pSrc, 39 uint32_t fftLen, 40 const q31_t * pCoef, 41 uint16_t twidCoefModifier); 42 43 void arm_bitreversal_q31( 44 q31_t * pSrc, 45 uint32_t fftLen, 46 uint16_t bitRevFactor, 47 const uint16_t * pBitRevTab); 48 49 /** 50 @ingroup groupTransforms 51 */ 52 53 /** 54 @addtogroup ComplexFFT 55 @{ 56 */ 57 58 /** 59 @brief Processing function for the fixed-point CFFT/CIFFT. 60 @deprecated Do not use this function. It has been superseded by \ref arm_cfft_q31 and will be removed in the future. 61 @param[in] S points to an instance of the fixed-point CFFT/CIFFT structure 62 @param[in,out] pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place 63 @return none 64 */ 65 66 void arm_cfft_radix2_q31( 67 const arm_cfft_radix2_instance_q31 * S, 68 q31_t * pSrc) 69 { 70 71 if (S->ifftFlag == 1U) 72 { 73 arm_radix2_butterfly_inverse_q31(pSrc, S->fftLen, 74 S->pTwiddle, S->twidCoefModifier); 75 } 76 else 77 { 78 arm_radix2_butterfly_q31(pSrc, S->fftLen, 79 S->pTwiddle, S->twidCoefModifier); 80 } 81 82 arm_bitreversal_q31(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable); 83 } 84 85 /** 86 @} end of ComplexFFT group 87 */ 88 89 void arm_radix2_butterfly_q31( 90 q31_t * pSrc, 91 uint32_t fftLen, 92 const q31_t * pCoef, 93 uint16_t twidCoefModifier) 94 { 95 96 unsigned i, j, k, l, m; 97 unsigned n1, n2, ia; 98 q31_t xt, yt, cosVal, sinVal; 99 q31_t p0, p1; 100 101 //N = fftLen; 102 n2 = fftLen; 103 104 n1 = n2; 105 n2 = n2 >> 1; 106 ia = 0; 107 108 // loop for groups 109 for (i = 0; i < n2; i++) 110 { 111 cosVal = pCoef[ia * 2]; 112 sinVal = pCoef[(ia * 2) + 1]; 113 ia = ia + twidCoefModifier; 114 115 l = i + n2; 116 xt = (pSrc[2 * i] >> 1U) - (pSrc[2 * l] >> 1U); 117 pSrc[2 * i] = ((pSrc[2 * i] >> 1U) + (pSrc[2 * l] >> 1U)) >> 1U; 118 119 yt = (pSrc[2 * i + 1] >> 1U) - (pSrc[2 * l + 1] >> 1U); 120 pSrc[2 * i + 1] = 121 ((pSrc[2 * l + 1] >> 1U) + (pSrc[2 * i + 1] >> 1U)) >> 1U; 122 123 mult_32x32_keep32_R(p0, xt, cosVal); 124 mult_32x32_keep32_R(p1, yt, cosVal); 125 multAcc_32x32_keep32_R(p0, yt, sinVal); 126 multSub_32x32_keep32_R(p1, xt, sinVal); 127 128 pSrc[2U * l] = p0; 129 pSrc[2U * l + 1U] = p1; 130 131 } // groups loop end 132 133 twidCoefModifier <<= 1U; 134 135 // loop for stage 136 for (k = fftLen / 2; k > 2; k = k >> 1) 137 { 138 n1 = n2; 139 n2 = n2 >> 1; 140 ia = 0; 141 142 // loop for groups 143 for (j = 0; j < n2; j++) 144 { 145 cosVal = pCoef[ia * 2]; 146 sinVal = pCoef[(ia * 2) + 1]; 147 ia = ia + twidCoefModifier; 148 149 // loop for butterfly 150 i = j; 151 m = fftLen / n1; 152 do 153 { 154 l = i + n2; 155 xt = pSrc[2 * i] - pSrc[2 * l]; 156 pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1U; 157 158 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; 159 pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1U; 160 161 mult_32x32_keep32_R(p0, xt, cosVal); 162 mult_32x32_keep32_R(p1, yt, cosVal); 163 multAcc_32x32_keep32_R(p0, yt, sinVal); 164 multSub_32x32_keep32_R(p1, xt, sinVal); 165 166 pSrc[2U * l] = p0; 167 pSrc[2U * l + 1U] = p1; 168 i += n1; 169 m--; 170 } while ( m > 0); // butterfly loop end 171 172 } // groups loop end 173 174 twidCoefModifier <<= 1U; 175 } // stages loop end 176 177 n1 = n2; 178 n2 = n2 >> 1; 179 ia = 0; 180 181 cosVal = pCoef[ia * 2]; 182 sinVal = pCoef[(ia * 2) + 1]; 183 ia = ia + twidCoefModifier; 184 185 // loop for butterfly 186 for (i = 0; i < fftLen; i += n1) 187 { 188 l = i + n2; 189 xt = pSrc[2 * i] - pSrc[2 * l]; 190 pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]); 191 192 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; 193 pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]); 194 195 pSrc[2U * l] = xt; 196 197 pSrc[2U * l + 1U] = yt; 198 199 i += n1; 200 l = i + n2; 201 202 xt = pSrc[2 * i] - pSrc[2 * l]; 203 pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]); 204 205 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; 206 pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]); 207 208 pSrc[2U * l] = xt; 209 210 pSrc[2U * l + 1U] = yt; 211 212 } // butterfly loop end 213 214 } 215 216 217 void arm_radix2_butterfly_inverse_q31( 218 q31_t * pSrc, 219 uint32_t fftLen, 220 const q31_t * pCoef, 221 uint16_t twidCoefModifier) 222 { 223 224 unsigned i, j, k, l; 225 unsigned n1, n2, ia; 226 q31_t xt, yt, cosVal, sinVal; 227 q31_t p0, p1; 228 229 //N = fftLen; 230 n2 = fftLen; 231 232 n1 = n2; 233 n2 = n2 >> 1; 234 ia = 0; 235 236 // loop for groups 237 for (i = 0; i < n2; i++) 238 { 239 cosVal = pCoef[ia * 2]; 240 sinVal = pCoef[(ia * 2) + 1]; 241 ia = ia + twidCoefModifier; 242 243 l = i + n2; 244 xt = (pSrc[2 * i] >> 1U) - (pSrc[2 * l] >> 1U); 245 pSrc[2 * i] = ((pSrc[2 * i] >> 1U) + (pSrc[2 * l] >> 1U)) >> 1U; 246 247 yt = (pSrc[2 * i + 1] >> 1U) - (pSrc[2 * l + 1] >> 1U); 248 pSrc[2 * i + 1] = 249 ((pSrc[2 * l + 1] >> 1U) + (pSrc[2 * i + 1] >> 1U)) >> 1U; 250 251 mult_32x32_keep32_R(p0, xt, cosVal); 252 mult_32x32_keep32_R(p1, yt, cosVal); 253 multSub_32x32_keep32_R(p0, yt, sinVal); 254 multAcc_32x32_keep32_R(p1, xt, sinVal); 255 256 pSrc[2U * l] = p0; 257 pSrc[2U * l + 1U] = p1; 258 } // groups loop end 259 260 twidCoefModifier = twidCoefModifier << 1U; 261 262 // loop for stage 263 for (k = fftLen / 2; k > 2; k = k >> 1) 264 { 265 n1 = n2; 266 n2 = n2 >> 1; 267 ia = 0; 268 269 // loop for groups 270 for (j = 0; j < n2; j++) 271 { 272 cosVal = pCoef[ia * 2]; 273 sinVal = pCoef[(ia * 2) + 1]; 274 ia = ia + twidCoefModifier; 275 276 // loop for butterfly 277 for (i = j; i < fftLen; i += n1) 278 { 279 l = i + n2; 280 xt = pSrc[2 * i] - pSrc[2 * l]; 281 pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1U; 282 283 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; 284 pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1U; 285 286 mult_32x32_keep32_R(p0, xt, cosVal); 287 mult_32x32_keep32_R(p1, yt, cosVal); 288 multSub_32x32_keep32_R(p0, yt, sinVal); 289 multAcc_32x32_keep32_R(p1, xt, sinVal); 290 291 pSrc[2U * l] = p0; 292 pSrc[2U * l + 1U] = p1; 293 } // butterfly loop end 294 295 } // groups loop end 296 297 twidCoefModifier = twidCoefModifier << 1U; 298 } // stages loop end 299 300 n1 = n2; 301 n2 = n2 >> 1; 302 ia = 0; 303 304 cosVal = pCoef[ia * 2]; 305 sinVal = pCoef[(ia * 2) + 1]; 306 ia = ia + twidCoefModifier; 307 308 // loop for butterfly 309 for (i = 0; i < fftLen; i += n1) 310 { 311 l = i + n2; 312 xt = pSrc[2 * i] - pSrc[2 * l]; 313 pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]); 314 315 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; 316 pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]); 317 318 pSrc[2U * l] = xt; 319 320 pSrc[2U * l + 1U] = yt; 321 322 i += n1; 323 l = i + n2; 324 325 xt = pSrc[2 * i] - pSrc[2 * l]; 326 pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]); 327 328 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; 329 pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]); 330 331 pSrc[2U * l] = xt; 332 333 pSrc[2U * l + 1U] = yt; 334 335 } // butterfly loop end 336 337 }