mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-15 17:53:33 +08:00
Added CMSIS library.
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_bitreversal.c
|
||||
*
|
||||
* Description: This file has common tables like Bitreverse, reciprocal etc which are used across different functions
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 1.0.10 2011/7/15
|
||||
* Initial Version
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
#include "arm_common_tables.h"
|
||||
|
||||
/*
|
||||
* @brief In-place bit reversal function.
|
||||
* @param[in, out] *pSrc points to the in-place buffer of floating-point data type.
|
||||
* @param[in] fftSize length of the FFT.
|
||||
* @param[in] bitRevFactor bit reversal modifier that supports different size FFTs with the same bit reversal table.
|
||||
* @param[in] *pBitRevTab points to the bit reversal table.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_bitreversal_f32(
|
||||
float32_t * pSrc,
|
||||
uint16_t fftSize,
|
||||
uint16_t bitRevFactor,
|
||||
uint16_t * pBitRevTab)
|
||||
{
|
||||
uint16_t fftLenBy2, fftLenBy2p1;
|
||||
uint16_t i, j;
|
||||
float32_t in;
|
||||
|
||||
/* Initializations */
|
||||
j = 0u;
|
||||
fftLenBy2 = fftSize >> 1u;
|
||||
fftLenBy2p1 = (fftSize >> 1u) + 1u;
|
||||
|
||||
/* Bit Reversal Implementation */
|
||||
for (i = 0u; i <= (fftLenBy2 - 2u); i += 2u)
|
||||
{
|
||||
if(i < j)
|
||||
{
|
||||
/* pSrc[i] <-> pSrc[j]; */
|
||||
in = pSrc[2u * i];
|
||||
pSrc[2u * i] = pSrc[2u * j];
|
||||
pSrc[2u * j] = in;
|
||||
|
||||
/* pSrc[i+1u] <-> pSrc[j+1u] */
|
||||
in = pSrc[(2u * i) + 1u];
|
||||
pSrc[(2u * i) + 1u] = pSrc[(2u * j) + 1u];
|
||||
pSrc[(2u * j) + 1u] = in;
|
||||
|
||||
/* pSrc[i+fftLenBy2p1] <-> pSrc[j+fftLenBy2p1] */
|
||||
in = pSrc[2u * (i + fftLenBy2p1)];
|
||||
pSrc[2u * (i + fftLenBy2p1)] = pSrc[2u * (j + fftLenBy2p1)];
|
||||
pSrc[2u * (j + fftLenBy2p1)] = in;
|
||||
|
||||
/* pSrc[i+fftLenBy2p1+1u] <-> pSrc[j+fftLenBy2p1+1u] */
|
||||
in = pSrc[(2u * (i + fftLenBy2p1)) + 1u];
|
||||
pSrc[(2u * (i + fftLenBy2p1)) + 1u] =
|
||||
pSrc[(2u * (j + fftLenBy2p1)) + 1u];
|
||||
pSrc[(2u * (j + fftLenBy2p1)) + 1u] = in;
|
||||
|
||||
}
|
||||
|
||||
/* pSrc[i+1u] <-> pSrc[j+1u] */
|
||||
in = pSrc[2u * (i + 1u)];
|
||||
pSrc[2u * (i + 1u)] = pSrc[2u * (j + fftLenBy2)];
|
||||
pSrc[2u * (j + fftLenBy2)] = in;
|
||||
|
||||
/* pSrc[i+2u] <-> pSrc[j+2u] */
|
||||
in = pSrc[(2u * (i + 1u)) + 1u];
|
||||
pSrc[(2u * (i + 1u)) + 1u] = pSrc[(2u * (j + fftLenBy2)) + 1u];
|
||||
pSrc[(2u * (j + fftLenBy2)) + 1u] = in;
|
||||
|
||||
/* Reading the index for the bit reversal */
|
||||
j = *pBitRevTab;
|
||||
|
||||
/* Updating the bit reversal index depending on the fft length */
|
||||
pBitRevTab += bitRevFactor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* @brief In-place bit reversal function.
|
||||
* @param[in, out] *pSrc points to the in-place buffer of Q31 data type.
|
||||
* @param[in] fftLen length of the FFT.
|
||||
* @param[in] bitRevFactor bit reversal modifier that supports different size FFTs with the same bit reversal table
|
||||
* @param[in] *pBitRevTab points to bit reversal table.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_bitreversal_q31(
|
||||
q31_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
uint16_t bitRevFactor,
|
||||
uint16_t * pBitRevTable)
|
||||
{
|
||||
uint32_t fftLenBy2, fftLenBy2p1, i, j;
|
||||
q31_t in;
|
||||
|
||||
/* Initializations */
|
||||
j = 0u;
|
||||
fftLenBy2 = fftLen / 2u;
|
||||
fftLenBy2p1 = (fftLen / 2u) + 1u;
|
||||
|
||||
/* Bit Reversal Implementation */
|
||||
for (i = 0u; i <= (fftLenBy2 - 2u); i += 2u)
|
||||
{
|
||||
if(i < j)
|
||||
{
|
||||
/* pSrc[i] <-> pSrc[j]; */
|
||||
in = pSrc[2u * i];
|
||||
pSrc[2u * i] = pSrc[2u * j];
|
||||
pSrc[2u * j] = in;
|
||||
|
||||
/* pSrc[i+1u] <-> pSrc[j+1u] */
|
||||
in = pSrc[(2u * i) + 1u];
|
||||
pSrc[(2u * i) + 1u] = pSrc[(2u * j) + 1u];
|
||||
pSrc[(2u * j) + 1u] = in;
|
||||
|
||||
/* pSrc[i+fftLenBy2p1] <-> pSrc[j+fftLenBy2p1] */
|
||||
in = pSrc[2u * (i + fftLenBy2p1)];
|
||||
pSrc[2u * (i + fftLenBy2p1)] = pSrc[2u * (j + fftLenBy2p1)];
|
||||
pSrc[2u * (j + fftLenBy2p1)] = in;
|
||||
|
||||
/* pSrc[i+fftLenBy2p1+1u] <-> pSrc[j+fftLenBy2p1+1u] */
|
||||
in = pSrc[(2u * (i + fftLenBy2p1)) + 1u];
|
||||
pSrc[(2u * (i + fftLenBy2p1)) + 1u] =
|
||||
pSrc[(2u * (j + fftLenBy2p1)) + 1u];
|
||||
pSrc[(2u * (j + fftLenBy2p1)) + 1u] = in;
|
||||
|
||||
}
|
||||
|
||||
/* pSrc[i+1u] <-> pSrc[j+1u] */
|
||||
in = pSrc[2u * (i + 1u)];
|
||||
pSrc[2u * (i + 1u)] = pSrc[2u * (j + fftLenBy2)];
|
||||
pSrc[2u * (j + fftLenBy2)] = in;
|
||||
|
||||
/* pSrc[i+2u] <-> pSrc[j+2u] */
|
||||
in = pSrc[(2u * (i + 1u)) + 1u];
|
||||
pSrc[(2u * (i + 1u)) + 1u] = pSrc[(2u * (j + fftLenBy2)) + 1u];
|
||||
pSrc[(2u * (j + fftLenBy2)) + 1u] = in;
|
||||
|
||||
/* Reading the index for the bit reversal */
|
||||
j = *pBitRevTable;
|
||||
|
||||
/* Updating the bit reversal index depending on the fft length */
|
||||
pBitRevTable += bitRevFactor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* @brief In-place bit reversal function.
|
||||
* @param[in, out] *pSrc points to the in-place buffer of Q15 data type.
|
||||
* @param[in] fftLen length of the FFT.
|
||||
* @param[in] bitRevFactor bit reversal modifier that supports different size FFTs with the same bit reversal table
|
||||
* @param[in] *pBitRevTab points to bit reversal table.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_bitreversal_q15(
|
||||
q15_t * pSrc16,
|
||||
uint32_t fftLen,
|
||||
uint16_t bitRevFactor,
|
||||
uint16_t * pBitRevTab)
|
||||
{
|
||||
q31_t *pSrc = (q31_t *) pSrc16;
|
||||
q31_t in;
|
||||
uint32_t fftLenBy2, fftLenBy2p1;
|
||||
uint32_t i, j;
|
||||
|
||||
/* Initializations */
|
||||
j = 0u;
|
||||
fftLenBy2 = fftLen / 2u;
|
||||
fftLenBy2p1 = (fftLen / 2u) + 1u;
|
||||
|
||||
/* Bit Reversal Implementation */
|
||||
for (i = 0u; i <= (fftLenBy2 - 2u); i += 2u)
|
||||
{
|
||||
if(i < j)
|
||||
{
|
||||
/* pSrc[i] <-> pSrc[j]; */
|
||||
/* pSrc[i+1u] <-> pSrc[j+1u] */
|
||||
in = pSrc[i];
|
||||
pSrc[i] = pSrc[j];
|
||||
pSrc[j] = in;
|
||||
|
||||
/* pSrc[i + fftLenBy2p1] <-> pSrc[j + fftLenBy2p1]; */
|
||||
/* pSrc[i + fftLenBy2p1+1u] <-> pSrc[j + fftLenBy2p1+1u] */
|
||||
in = pSrc[i + fftLenBy2p1];
|
||||
pSrc[i + fftLenBy2p1] = pSrc[j + fftLenBy2p1];
|
||||
pSrc[j + fftLenBy2p1] = in;
|
||||
}
|
||||
|
||||
/* pSrc[i+1u] <-> pSrc[j+fftLenBy2]; */
|
||||
/* pSrc[i+2] <-> pSrc[j+fftLenBy2+1u] */
|
||||
in = pSrc[i + 1u];
|
||||
pSrc[i + 1u] = pSrc[j + fftLenBy2];
|
||||
pSrc[j + fftLenBy2] = in;
|
||||
|
||||
/* Reading the index for the bit reversal */
|
||||
j = *pBitRevTab;
|
||||
|
||||
/* Updating the bit reversal index depending on the fft length */
|
||||
pBitRevTab += bitRevFactor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,511 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_cfft_radix2_f32.c
|
||||
*
|
||||
* Description: Radix-2 Decimation in Frequency CFFT & CIFFT Floating point processing function
|
||||
*
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 1.0.3 2010/11/29
|
||||
* Initial version
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupTransforms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup Radix2_CFFT_CIFFT Radix-2 Complex FFT Functions
|
||||
*
|
||||
* \par
|
||||
* 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).
|
||||
* Computational complexity of CFFT reduces drastically when compared to DFT.
|
||||
* \par
|
||||
* This set of functions implements CFFT/CIFFT
|
||||
* for Q15, Q31, and floating-point data types. The functions operates on in-place buffer which uses same buffer for input and output.
|
||||
* Complex input is stored in input buffer in an interleaved fashion.
|
||||
*
|
||||
* \par
|
||||
* The functions operate on blocks of input and output data and each call to the function processes
|
||||
* <code>2*fftLen</code> samples through the transform. <code>pSrc</code> points to In-place arrays containing <code>2*fftLen</code> values.
|
||||
* \par
|
||||
* 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.
|
||||
* <pre> {real[0], imag[0], real[1], imag[1],..} </pre>
|
||||
*
|
||||
* \par Lengths supported by the transform:
|
||||
* \par
|
||||
* Internally, the function utilize a radix-2 decimation in frequency(DIF) algorithm
|
||||
* and the size of the FFT supported are of the lengths [16, 32, 64, 128, 256, 512, 1024, 2048, 4096].
|
||||
*
|
||||
*
|
||||
* \par Algorithm:
|
||||
*
|
||||
* <b>Complex Fast Fourier Transform:</b>
|
||||
* \par
|
||||
* Input real and imaginary data:
|
||||
* <pre>
|
||||
* x(n) = xa + j * ya
|
||||
* x(n+N/2 ) = xb + j * yb
|
||||
* </pre>
|
||||
* where N is length of FFT
|
||||
* \par
|
||||
* Output real and imaginary data:
|
||||
* <pre>
|
||||
* X(2r) = xa'+ j * ya'
|
||||
* X(2r+1) = xb'+ j * yb'
|
||||
* </pre>
|
||||
* \par
|
||||
* Twiddle factors for radix-2 FFT:
|
||||
* <pre>
|
||||
* Wn = cosVal + j * (- sinVal)
|
||||
* </pre>
|
||||
*
|
||||
* \par
|
||||
* \image html CFFT_Radix2.gif "Radix-2 Decimation-in Frequency Complex Fast Fourier Transform"
|
||||
*
|
||||
* \par
|
||||
* Output from Radix-2 CFFT Results in Digit reversal order. Interchange middle two branches of every butterfly results in Bit reversed output.
|
||||
* \par
|
||||
* <b> Butterfly CFFT equations:</b>
|
||||
* <pre>
|
||||
* xa' = xa + xb
|
||||
* ya' = ya + yb
|
||||
* xb' = (xa-xb)* cosVal + (ya-yb) * sinVal
|
||||
* yb' = (ya-yb)* cosVal - (xa-xb) * sinVal
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* <b>Complex Inverse Fast Fourier Transform:</b>
|
||||
* \par
|
||||
* CIFFT uses same twiddle factor table as CFFT with modifications in the design equation as shown below.
|
||||
*
|
||||
* \par
|
||||
* <b> Modified Butterfly CIFFT equations:</b>
|
||||
* <pre>
|
||||
* xa' = xa + xb
|
||||
* ya' = ya + yb
|
||||
* xb' = (xa-xb)* cosVal - (ya-yb) * sinVal
|
||||
* yb' = (ya-yb)* cosVal + (xa-xb) * sinVal
|
||||
* </pre>
|
||||
*
|
||||
* \par Instance Structure
|
||||
* A separate instance structure must be defined for each Instance but the twiddle factors and bit reversal tables can be reused.
|
||||
* There are separate instance structure declarations for each of the 3 supported data types.
|
||||
*
|
||||
* \par Initialization Functions
|
||||
* There is also an associated initialization function for each data type.
|
||||
* The initialization function performs the following operations:
|
||||
* - Sets the values of the internal structure fields.
|
||||
* - Initializes twiddle factor table and bit reversal table pointers
|
||||
* \par
|
||||
* Use of the initialization function is optional.
|
||||
* However, if the initialization function is used, then the instance structure cannot be placed into a const data section.
|
||||
* To place an instance structure into a const data section, the instance structure must be manually initialized.
|
||||
* Manually initialize the instance structure as follows:
|
||||
* <pre>
|
||||
*arm_cfft_radix2_instance_f32 S = {fftLen, ifftFlag, bitReverseFlag, pTwiddle, pBitRevTable, twidCoefModifier, bitRevFactor, onebyfftLen};
|
||||
*arm_cfft_radix2_instance_q31 S = {fftLen, ifftFlag, bitReverseFlag, pTwiddle, pBitRevTable, twidCoefModifier, bitRevFactor};
|
||||
*arm_cfft_radix2_instance_q15 S = {fftLen, ifftFlag, bitReverseFlag, pTwiddle, pBitRevTable, twidCoefModifier, bitRevFactor};
|
||||
* </pre>
|
||||
* \par
|
||||
* 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);
|
||||
* <code>bitReverseFlag</code> Flag for selection of output order(Set bitReverseFlag to output in normal order otherwise output in bit reversed order);
|
||||
* <code>pTwiddle</code>points to array of twiddle coefficients; <code>pBitRevTable</code> points to the array of bit reversal table.
|
||||
* <code>twidCoefModifier</code> modifier for twiddle factor table which supports all FFT lengths with same table;
|
||||
* <code>pBitRevTable</code> modifier for bit reversal table which supports all FFT lengths with same table.
|
||||
* <code>onebyfftLen</code> value of 1/fftLen to calculate CIFFT;
|
||||
*
|
||||
* \par Fixed-Point Behavior
|
||||
* Care must be taken when using the fixed-point versions of the CFFT/CIFFT function.
|
||||
* Refer to the function specific documentation below for usage guidelines.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup Radix2_CFFT_CIFFT
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @details
|
||||
* @brief Processing function for the floating-point Radix-2 CFFT/CIFFT.
|
||||
* @param[in] *S points to an instance of the floating-point Radix-2 CFFT/CIFFT structure.
|
||||
* @param[in, out] *pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_cfft_radix2_f32(
|
||||
const arm_cfft_radix2_instance_f32 * S,
|
||||
float32_t * pSrc)
|
||||
{
|
||||
|
||||
if(S->ifftFlag == 1u)
|
||||
{
|
||||
/* Complex IFFT radix-2 */
|
||||
arm_radix2_butterfly_inverse_f32(pSrc, S->fftLen, S->pTwiddle,
|
||||
S->twidCoefModifier, S->onebyfftLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Complex FFT radix-2 */
|
||||
arm_radix2_butterfly_f32(pSrc, S->fftLen, S->pTwiddle,
|
||||
S->twidCoefModifier);
|
||||
}
|
||||
|
||||
if(S->bitReverseFlag == 1u)
|
||||
{
|
||||
/* Bit Reversal */
|
||||
arm_bitreversal_f32(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @} end of Radix2_CFFT_CIFFT group
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
** Internal helper function used by the FFTs
|
||||
** ------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* @brief Core function for the floating-point CFFT butterfly process.
|
||||
* @param[in, out] *pSrc points to the in-place buffer of floating-point data type.
|
||||
* @param[in] fftLen length of the FFT.
|
||||
* @param[in] *pCoef points to the twiddle coefficient buffer.
|
||||
* @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_radix2_butterfly_f32(
|
||||
float32_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
float32_t * pCoef,
|
||||
uint16_t twidCoefModifier)
|
||||
{
|
||||
|
||||
int i, j, k, l;
|
||||
int n1, n2, ia;
|
||||
float32_t xt, yt, cosVal, sinVal;
|
||||
|
||||
#ifndef ARM_MATH_CM0
|
||||
|
||||
/* Initializations for the first stage */
|
||||
n2 = fftLen;
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (i = 0; i < n2; i++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
|
||||
/* Twiddle coefficients index modifier */
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
/* index calculation for the input as, */
|
||||
/* pSrc[i + 0], pSrc[i + fftLen/1] */
|
||||
l = i + n2;
|
||||
|
||||
/* Butterfly implementation */
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = pSrc[2 * i] + pSrc[2 * l];
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = pSrc[2 * l + 1] + pSrc[2 * i + 1];
|
||||
|
||||
pSrc[2u * l] = xt * cosVal + yt * sinVal;
|
||||
|
||||
pSrc[2u * l + 1u] = yt * cosVal - xt * sinVal;
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
|
||||
// loop for stage
|
||||
for (k = fftLen / 2; k > 2; k = k >> 1)
|
||||
{
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (j = 0; j < n2; j++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = j; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = pSrc[2 * i] + pSrc[2 * l];
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = pSrc[2 * l + 1] + pSrc[2 * i + 1];
|
||||
|
||||
pSrc[2u * l] = xt * cosVal + yt * sinVal;
|
||||
|
||||
pSrc[2u * l + 1u] = yt * cosVal - xt * sinVal;
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
} // stages loop end
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = 0; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
|
||||
|
||||
pSrc[2u * l] = xt;
|
||||
|
||||
pSrc[2u * l + 1u] = yt;
|
||||
|
||||
} // groups loop end
|
||||
|
||||
#else
|
||||
|
||||
//N = fftLen;
|
||||
n2 = fftLen;
|
||||
|
||||
// loop for stage
|
||||
for (k = fftLen; k > 1; k = k >> 1)
|
||||
{
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (j = 0; j < n2; j++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = j; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = pSrc[2 * i] + pSrc[2 * l];
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = pSrc[2 * l + 1] + pSrc[2 * i + 1];
|
||||
|
||||
pSrc[2 * l] = (cosVal * xt + sinVal * yt); // >> 15;
|
||||
pSrc[2 * l + 1] = (cosVal * yt - sinVal * xt); // >> 15;
|
||||
|
||||
}
|
||||
}
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
}
|
||||
|
||||
#endif // #ifndef ARM_MATH_CM0
|
||||
|
||||
}
|
||||
|
||||
|
||||
void arm_radix2_butterfly_inverse_f32(
|
||||
float32_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
float32_t * pCoef,
|
||||
uint16_t twidCoefModifier,
|
||||
float32_t onebyfftLen)
|
||||
{
|
||||
|
||||
int i, j, k, l;
|
||||
int n1, n2, ia;
|
||||
float32_t xt, yt, cosVal, sinVal;
|
||||
|
||||
#ifndef ARM_MATH_CM0
|
||||
|
||||
//N = fftLen;
|
||||
n2 = fftLen;
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (i = 0; i < n2; i++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = pSrc[2 * i] + pSrc[2 * l];
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = pSrc[2 * l + 1] + pSrc[2 * i + 1];
|
||||
|
||||
pSrc[2u * l] = xt * cosVal - yt * sinVal;
|
||||
|
||||
pSrc[2u * l + 1u] = yt * cosVal + xt * sinVal;
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
|
||||
// loop for stage
|
||||
for (k = fftLen / 2; k > 2; k = k >> 1)
|
||||
{
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (j = 0; j < n2; j++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = j; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = pSrc[2 * i] + pSrc[2 * l];
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = pSrc[2 * l + 1] + pSrc[2 * i + 1];
|
||||
|
||||
pSrc[2u * l] = xt * cosVal - yt * sinVal;
|
||||
|
||||
pSrc[2u * l + 1u] = yt * cosVal + xt * sinVal;
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
} // stages loop end
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = 0; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) * onebyfftLen;
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) * onebyfftLen;
|
||||
|
||||
pSrc[2u * l] = xt * onebyfftLen;
|
||||
|
||||
pSrc[2u * l + 1u] = yt * onebyfftLen;
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
#else
|
||||
|
||||
//N = fftLen;
|
||||
n2 = fftLen;
|
||||
|
||||
// loop for stage
|
||||
for (k = fftLen; k > 2; k = k >> 1)
|
||||
{
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (j = 0; j < n2; j++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = j; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = pSrc[2 * i] + pSrc[2 * l];
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = pSrc[2 * l + 1] + pSrc[2 * i + 1];
|
||||
|
||||
pSrc[2u * l] = xt * cosVal - yt * sinVal;
|
||||
|
||||
pSrc[2u * l + 1u] = yt * cosVal + xt * sinVal;
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
} // stages loop end
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = 0; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) * onebyfftLen;
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) * onebyfftLen;
|
||||
|
||||
pSrc[2u * l] = xt * onebyfftLen;
|
||||
|
||||
pSrc[2u * l + 1u] = yt * onebyfftLen;
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
#endif // #ifndef ARM_MATH_CM0
|
||||
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_cfft_radix4_init_f32.c
|
||||
*
|
||||
* Description: Radix-4 Decimation in Frequency Floating-point CFFT & CIFFT Initialization function
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 1.0.3 2010/11/29
|
||||
* Re-organized the CMSIS folders and updated documentation.
|
||||
*
|
||||
* Version 1.0.2 2010/11/11
|
||||
* Documentation updated.
|
||||
*
|
||||
* Version 1.0.1 2010/10/05
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 1.0.0 2010/09/20
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 0.0.5 2010/04/26
|
||||
* incorporated review comments and updated with latest CMSIS layer
|
||||
*
|
||||
* Version 0.0.3 2010/03/10
|
||||
* Initial version
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "arm_math.h"
|
||||
#include "arm_common_tables.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupTransforms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup Radix2_CFFT_CIFFT
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialization function for the floating-point CFFT/CIFFT.
|
||||
* @param[in,out] *S points to an instance of the floating-point CFFT/CIFFT structure.
|
||||
* @param[in] fftLen length of the FFT.
|
||||
* @param[in] ifftFlag flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
|
||||
* @param[in] bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
|
||||
* @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLen</code> is not a supported value.
|
||||
*
|
||||
* \par Description:
|
||||
* \par
|
||||
* The parameter <code>ifftFlag</code> controls whether a forward or inverse transform is computed.
|
||||
* Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated
|
||||
* \par
|
||||
* The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order.
|
||||
* Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order.
|
||||
* \par
|
||||
* The parameter <code>fftLen</code> Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024.
|
||||
* \par
|
||||
* This Function also initializes Twiddle factor table pointer and Bit reversal table pointer.
|
||||
*/
|
||||
arm_status arm_cfft_radix2_init_f32(
|
||||
arm_cfft_radix2_instance_f32 * S,
|
||||
uint16_t fftLen,
|
||||
uint8_t ifftFlag,
|
||||
uint8_t bitReverseFlag)
|
||||
{
|
||||
/* Initialise the default arm status */
|
||||
arm_status status = ARM_MATH_SUCCESS;
|
||||
|
||||
/* Initialise the FFT length */
|
||||
S->fftLen = fftLen;
|
||||
|
||||
/* Initialise the Twiddle coefficient pointer */
|
||||
S->pTwiddle = (float32_t *) twiddleCoef;
|
||||
|
||||
/* Initialise the Flag for selection of CFFT or CIFFT */
|
||||
S->ifftFlag = ifftFlag;
|
||||
|
||||
/* Initialise the Flag for calculation Bit reversal or not */
|
||||
S->bitReverseFlag = bitReverseFlag;
|
||||
|
||||
/* Initializations of structure parameters depending on the FFT length */
|
||||
switch (S->fftLen)
|
||||
{
|
||||
|
||||
case 4096u:
|
||||
/* Initializations of structure parameters for 4096 point FFT */
|
||||
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 1u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 1u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) armBitRevTable;
|
||||
/* Initialise the 1/fftLen Value */
|
||||
S->onebyfftLen = 0.000244140625;
|
||||
break;
|
||||
|
||||
case 2048u:
|
||||
/* Initializations of structure parameters for 2048 point FFT */
|
||||
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 2u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 2u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[1];
|
||||
/* Initialise the 1/fftLen Value */
|
||||
S->onebyfftLen = 0.00048828125;
|
||||
break;
|
||||
|
||||
case 1024u:
|
||||
/* Initializations of structure parameters for 1024 point FFT */
|
||||
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 4u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 4u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[3];
|
||||
/* Initialise the 1/fftLen Value */
|
||||
S->onebyfftLen = 0.0009765625f;
|
||||
break;
|
||||
|
||||
case 512u:
|
||||
/* Initializations of structure parameters for 512 point FFT */
|
||||
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 8u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 8u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[7];
|
||||
/* Initialise the 1/fftLen Value */
|
||||
S->onebyfftLen = 0.001953125;
|
||||
break;
|
||||
|
||||
case 256u:
|
||||
/* Initializations of structure parameters for 256 point FFT */
|
||||
S->twidCoefModifier = 16u;
|
||||
S->bitRevFactor = 16u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[15];
|
||||
S->onebyfftLen = 0.00390625f;
|
||||
break;
|
||||
|
||||
case 128u:
|
||||
/* Initializations of structure parameters for 128 point FFT */
|
||||
S->twidCoefModifier = 32u;
|
||||
S->bitRevFactor = 32u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[31];
|
||||
S->onebyfftLen = 0.0078125;
|
||||
break;
|
||||
|
||||
case 64u:
|
||||
/* Initializations of structure parameters for 64 point FFT */
|
||||
S->twidCoefModifier = 64u;
|
||||
S->bitRevFactor = 64u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[63];
|
||||
S->onebyfftLen = 0.015625f;
|
||||
break;
|
||||
|
||||
case 32u:
|
||||
/* Initializations of structure parameters for 64 point FFT */
|
||||
S->twidCoefModifier = 128u;
|
||||
S->bitRevFactor = 128u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[127];
|
||||
S->onebyfftLen = 0.03125;
|
||||
break;
|
||||
|
||||
case 16u:
|
||||
/* Initializations of structure parameters for 16 point FFT */
|
||||
S->twidCoefModifier = 256u;
|
||||
S->bitRevFactor = 256u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[255];
|
||||
S->onebyfftLen = 0.0625f;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
/* Reporting argument error if fftSize is not valid value */
|
||||
status = ARM_MATH_ARGUMENT_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of Radix2_CFFT_CIFFT group
|
||||
*/
|
||||
@@ -0,0 +1,186 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_cfft_radix2_init_q15.c
|
||||
*
|
||||
* Description: Radix-2 Decimation in Frequency Q15 FFT & IFFT initialization function
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 1.0.10 2011/7/15
|
||||
* Big Endian support added and Merged M0 and M3/M4 Source code.
|
||||
*
|
||||
* Version 1.0.3 2010/11/29
|
||||
* Re-organized the CMSIS folders and updated documentation.
|
||||
*
|
||||
* Version 1.0.2 2010/11/11
|
||||
* Documentation updated.
|
||||
*
|
||||
* Version 1.0.1 2010/10/05
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 1.0.0 2010/09/20
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 0.0.5 2010/04/26
|
||||
* incorporated review comments and updated with latest CMSIS layer
|
||||
*
|
||||
* Version 0.0.3 2010/03/10
|
||||
* Initial version
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
#include "arm_common_tables.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupTransforms
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup Radix2_CFFT_CIFFT
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialization function for the Q15 CFFT/CIFFT.
|
||||
* @param[in,out] *S points to an instance of the Q15 CFFT/CIFFT structure.
|
||||
* @param[in] fftLen length of the FFT.
|
||||
* @param[in] ifftFlag flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
|
||||
* @param[in] bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
|
||||
* @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLen</code> is not a supported value.
|
||||
*
|
||||
* \par Description:
|
||||
* \par
|
||||
* The parameter <code>ifftFlag</code> controls whether a forward or inverse transform is computed.
|
||||
* Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated
|
||||
* \par
|
||||
* The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order.
|
||||
* Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order.
|
||||
* \par
|
||||
* The parameter <code>fftLen</code> Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024.
|
||||
* \par
|
||||
* This Function also initializes Twiddle factor table pointer and Bit reversal table pointer.
|
||||
*/
|
||||
|
||||
arm_status arm_cfft_radix2_init_q15(
|
||||
arm_cfft_radix2_instance_q15 * S,
|
||||
uint16_t fftLen,
|
||||
uint8_t ifftFlag,
|
||||
uint8_t bitReverseFlag)
|
||||
{
|
||||
/* Initialise the default arm status */
|
||||
arm_status status = ARM_MATH_SUCCESS;
|
||||
|
||||
/* Initialise the FFT length */
|
||||
S->fftLen = fftLen;
|
||||
|
||||
/* Initialise the Twiddle coefficient pointer */
|
||||
S->pTwiddle = (q15_t *) twiddleCoefQ15;
|
||||
/* Initialise the Flag for selection of CFFT or CIFFT */
|
||||
S->ifftFlag = ifftFlag;
|
||||
/* Initialise the Flag for calculation Bit reversal or not */
|
||||
S->bitReverseFlag = bitReverseFlag;
|
||||
|
||||
/* Initializations of structure parameters depending on the FFT length */
|
||||
switch (S->fftLen)
|
||||
{
|
||||
case 4096u:
|
||||
/* Initializations of structure parameters for 4096 point FFT */
|
||||
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 1u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 1u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) armBitRevTable;
|
||||
|
||||
break;
|
||||
|
||||
case 2048u:
|
||||
/* Initializations of structure parameters for 2048 point FFT */
|
||||
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 2u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 2u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[1];
|
||||
|
||||
break;
|
||||
|
||||
case 1024u:
|
||||
/* Initializations of structure parameters for 1024 point FFT */
|
||||
S->twidCoefModifier = 4u;
|
||||
S->bitRevFactor = 4u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[3];
|
||||
|
||||
break;
|
||||
|
||||
case 512u:
|
||||
/* Initializations of structure parameters for 512 point FFT */
|
||||
S->twidCoefModifier = 8u;
|
||||
S->bitRevFactor = 8u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[7];
|
||||
|
||||
break;
|
||||
|
||||
case 256u:
|
||||
/* Initializations of structure parameters for 256 point FFT */
|
||||
S->twidCoefModifier = 16u;
|
||||
S->bitRevFactor = 16u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[15];
|
||||
|
||||
break;
|
||||
|
||||
case 128u:
|
||||
/* Initializations of structure parameters for 128 point FFT */
|
||||
S->twidCoefModifier = 32u;
|
||||
S->bitRevFactor = 32u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[31];
|
||||
|
||||
break;
|
||||
|
||||
case 64u:
|
||||
/* Initializations of structure parameters for 64 point FFT */
|
||||
S->twidCoefModifier = 64u;
|
||||
S->bitRevFactor = 64u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[63];
|
||||
|
||||
break;
|
||||
|
||||
case 32u:
|
||||
/* Initializations of structure parameters for 32 point FFT */
|
||||
S->twidCoefModifier = 128u;
|
||||
S->bitRevFactor = 128u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[127];
|
||||
|
||||
break;
|
||||
|
||||
case 16u:
|
||||
/* Initializations of structure parameters for 16 point FFT */
|
||||
S->twidCoefModifier = 256u;
|
||||
S->bitRevFactor = 256u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[255];
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Reporting argument error if fftSize is not valid value */
|
||||
status = ARM_MATH_ARGUMENT_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of Radix2_CFFT_CIFFT group
|
||||
*/
|
||||
@@ -0,0 +1,164 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_cfft_radix2_init_q31.c
|
||||
*
|
||||
* Description: Radix-2 Decimation in Frequency Fixed-point CFFT & CIFFT Initialization function
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "arm_math.h"
|
||||
#include "arm_common_tables.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupTransforms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup Radix2_CFFT_CIFFT
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Initialization function for the Q31 CFFT/CIFFT.
|
||||
* @param[in,out] *S points to an instance of the Q31 CFFT/CIFFT structure.
|
||||
* @param[in] fftLen length of the FFT.
|
||||
* @param[in] ifftFlag flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
|
||||
* @param[in] bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
|
||||
* @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLen</code> is not a supported value.
|
||||
*
|
||||
* \par Description:
|
||||
* \par
|
||||
* The parameter <code>ifftFlag</code> controls whether a forward or inverse transform is computed.
|
||||
* Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated
|
||||
* \par
|
||||
* The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order.
|
||||
* Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order.
|
||||
* \par
|
||||
* The parameter <code>fftLen</code> Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024.
|
||||
* \par
|
||||
* This Function also initializes Twiddle factor table pointer and Bit reversal table pointer.
|
||||
*/
|
||||
|
||||
arm_status arm_cfft_radix2_init_q31(
|
||||
arm_cfft_radix2_instance_q31 * S,
|
||||
uint16_t fftLen,
|
||||
uint8_t ifftFlag,
|
||||
uint8_t bitReverseFlag)
|
||||
{
|
||||
/* Initialise the default arm status */
|
||||
arm_status status = ARM_MATH_SUCCESS;
|
||||
|
||||
/* Initialise the FFT length */
|
||||
S->fftLen = fftLen;
|
||||
|
||||
/* Initialise the Twiddle coefficient pointer */
|
||||
S->pTwiddle = (q31_t *) twiddleCoefQ31;
|
||||
/* Initialise the Flag for selection of CFFT or CIFFT */
|
||||
S->ifftFlag = ifftFlag;
|
||||
/* Initialise the Flag for calculation Bit reversal or not */
|
||||
S->bitReverseFlag = bitReverseFlag;
|
||||
|
||||
/* Initializations of Instance structure depending on the FFT length */
|
||||
switch (S->fftLen)
|
||||
{
|
||||
/* Initializations of structure parameters for 4096 point FFT */
|
||||
case 4096u:
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 1u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 1u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) armBitRevTable;
|
||||
break;
|
||||
|
||||
/* Initializations of structure parameters for 2048 point FFT */
|
||||
case 2048u:
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 2u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 2u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[1];
|
||||
break;
|
||||
|
||||
/* Initializations of structure parameters for 1024 point FFT */
|
||||
case 1024u:
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 4u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 4u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[3];
|
||||
break;
|
||||
|
||||
/* Initializations of structure parameters for 512 point FFT */
|
||||
case 512u:
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 8u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 8u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[7];
|
||||
break;
|
||||
|
||||
case 256u:
|
||||
/* Initializations of structure parameters for 256 point FFT */
|
||||
S->twidCoefModifier = 16u;
|
||||
S->bitRevFactor = 16u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[15];
|
||||
break;
|
||||
|
||||
case 128u:
|
||||
/* Initializations of structure parameters for 128 point FFT */
|
||||
S->twidCoefModifier = 32u;
|
||||
S->bitRevFactor = 32u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[31];
|
||||
break;
|
||||
|
||||
case 64u:
|
||||
/* Initializations of structure parameters for 64 point FFT */
|
||||
S->twidCoefModifier = 64u;
|
||||
S->bitRevFactor = 64u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[63];
|
||||
break;
|
||||
|
||||
case 32u:
|
||||
/* Initializations of structure parameters for 32 point FFT */
|
||||
S->twidCoefModifier = 128u;
|
||||
S->bitRevFactor = 128u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[127];
|
||||
break;
|
||||
|
||||
case 16u:
|
||||
/* Initializations of structure parameters for 16 point FFT */
|
||||
S->twidCoefModifier = 256u;
|
||||
S->bitRevFactor = 256u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[255];
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
/* Reporting argument error if fftSize is not valid value */
|
||||
status = ARM_MATH_ARGUMENT_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of Radix2_CFFT_CIFFT group
|
||||
*/
|
||||
@@ -0,0 +1,712 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_cfft_radix2_q15.c
|
||||
*
|
||||
* Description: Radix-2 Decimation in Frequency CFFT & CIFFT Fixed point processing function
|
||||
*
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 0.0.3 2010/03/10
|
||||
* Initial version
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupTransforms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup Radix2_CFFT_CIFFT Radix-2 Complex FFT Functions
|
||||
*
|
||||
* \par
|
||||
* 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).
|
||||
* Computational complexity of CFFT reduces drastically when compared to DFT.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup Radix2_CFFT_CIFFT
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @details
|
||||
* @brief Processing function for the fixed-point CFFT/CIFFT.
|
||||
* @param[in] *S points to an instance of the fixed-point CFFT/CIFFT structure.
|
||||
* @param[in, out] *pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_cfft_radix2_q15(
|
||||
const arm_cfft_radix2_instance_q15 * S,
|
||||
q15_t * pSrc)
|
||||
{
|
||||
|
||||
if(S->ifftFlag == 1u)
|
||||
{
|
||||
arm_radix2_butterfly_inverse_q15(pSrc, S->fftLen,
|
||||
S->pTwiddle, S->twidCoefModifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
arm_radix2_butterfly_q15(pSrc, S->fftLen,
|
||||
S->pTwiddle, S->twidCoefModifier);
|
||||
}
|
||||
|
||||
arm_bitreversal_q15(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of Radix2_CFFT_CIFFT group
|
||||
*/
|
||||
|
||||
void arm_radix2_butterfly_q15(
|
||||
q15_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
q15_t * pCoef,
|
||||
uint16_t twidCoefModifier)
|
||||
{
|
||||
#ifndef ARM_MATH_CM0
|
||||
|
||||
int i, j, k, l;
|
||||
int n1, n2, ia;
|
||||
q15_t in;
|
||||
q31_t T, S, R;
|
||||
q31_t coeff, out1, out2;
|
||||
|
||||
//N = fftLen;
|
||||
n2 = fftLen;
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (i = 0; i < n2; i++)
|
||||
{
|
||||
coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
|
||||
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
l = i + n2;
|
||||
|
||||
T = _SIMD32_OFFSET(pSrc + (2 * i));
|
||||
in = ((int16_t) (T & 0xFFFF)) >> 2;
|
||||
T = ((T >> 2) & 0xFFFF0000) | (in & 0xFFFF);
|
||||
|
||||
S = _SIMD32_OFFSET(pSrc + (2 * l));
|
||||
in = ((int16_t) (S & 0xFFFF)) >> 2;
|
||||
S = ((S >> 2) & 0xFFFF0000) | (in & 0xFFFF);
|
||||
|
||||
R = __QSUB16(T, S);
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
out1 = __SMUAD(coeff, R) >> 16;
|
||||
out2 = __SMUSDX(coeff, R);
|
||||
|
||||
#else
|
||||
|
||||
out1 = __SMUSDX(R, coeff) >> 16u;
|
||||
out2 = __SMUAD(coeff, R);
|
||||
|
||||
#endif // #ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2u * l)) =
|
||||
(q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
|
||||
|
||||
coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
|
||||
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
i++;
|
||||
l++;
|
||||
|
||||
T = _SIMD32_OFFSET(pSrc + (2 * i));
|
||||
in = ((int16_t) (T & 0xFFFF)) >> 2;
|
||||
T = ((T >> 2) & 0xFFFF0000) | (in & 0xFFFF);
|
||||
|
||||
S = _SIMD32_OFFSET(pSrc + (2 * l));
|
||||
in = ((int16_t) (S & 0xFFFF)) >> 2;
|
||||
S = ((S >> 2) & 0xFFFF0000) | (in & 0xFFFF);
|
||||
|
||||
R = __QSUB16(T, S);
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
out1 = __SMUAD(coeff, R) >> 16;
|
||||
out2 = __SMUSDX(coeff, R);
|
||||
|
||||
#else
|
||||
|
||||
out1 = __SMUSDX(R, coeff) >> 16u;
|
||||
out2 = __SMUAD(coeff, R);
|
||||
|
||||
#endif // #ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2u * l)) =
|
||||
(q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
|
||||
// loop for stage
|
||||
for (k = fftLen / 2; k > 2; k = k >> 1)
|
||||
{
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (j = 0; j < n2; j++)
|
||||
{
|
||||
coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
|
||||
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = j; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
|
||||
T = _SIMD32_OFFSET(pSrc + (2 * i));
|
||||
|
||||
S = _SIMD32_OFFSET(pSrc + (2 * l));
|
||||
|
||||
R = __QSUB16(T, S);
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
out1 = __SMUAD(coeff, R) >> 16;
|
||||
out2 = __SMUSDX(coeff, R);
|
||||
|
||||
#else
|
||||
|
||||
out1 = __SMUSDX(R, coeff) >> 16u;
|
||||
out2 = __SMUAD(coeff, R);
|
||||
|
||||
#endif // #ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2u * l)) =
|
||||
(q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
|
||||
|
||||
i += n1;
|
||||
|
||||
l = i + n2;
|
||||
|
||||
T = _SIMD32_OFFSET(pSrc + (2 * i));
|
||||
|
||||
S = _SIMD32_OFFSET(pSrc + (2 * l));
|
||||
|
||||
R = __QSUB16(T, S);
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
out1 = __SMUAD(coeff, R) >> 16;
|
||||
out2 = __SMUSDX(coeff, R);
|
||||
|
||||
#else
|
||||
|
||||
out1 = __SMUSDX(R, coeff) >> 16u;
|
||||
out2 = __SMUAD(coeff, R);
|
||||
|
||||
#endif // #ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2u * l)) =
|
||||
(q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
} // stages loop end
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
|
||||
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = 0; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
|
||||
T = _SIMD32_OFFSET(pSrc + (2 * i));
|
||||
|
||||
S = _SIMD32_OFFSET(pSrc + (2 * l));
|
||||
|
||||
R = __QSUB16(T, S);
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2 * i)) = __QADD16(T, S);
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2u * l)) = R;
|
||||
|
||||
i += n1;
|
||||
l = i + n2;
|
||||
|
||||
T = _SIMD32_OFFSET(pSrc + (2 * i));
|
||||
|
||||
S = _SIMD32_OFFSET(pSrc + (2 * l));
|
||||
|
||||
R = __QSUB16(T, S);
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2 * i)) = __QADD16(T, S);
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2u * l)) = R;
|
||||
|
||||
} // groups loop end
|
||||
|
||||
|
||||
#else
|
||||
|
||||
int i, j, k, l;
|
||||
int n1, n2, ia;
|
||||
q15_t xt, yt, cosVal, sinVal;
|
||||
|
||||
|
||||
//N = fftLen;
|
||||
n2 = fftLen;
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (j = 0; j < n2; j++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = j; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = (pSrc[2 * i] >> 2u) - (pSrc[2 * l] >> 2u);
|
||||
pSrc[2 * i] = ((pSrc[2 * i] >> 2u) + (pSrc[2 * l] >> 2u)) >> 1u;
|
||||
|
||||
yt = (pSrc[2 * i + 1] >> 2u) - (pSrc[2 * l + 1] >> 2u);
|
||||
pSrc[2 * i + 1] =
|
||||
((pSrc[2 * l + 1] >> 2u) + (pSrc[2 * i + 1] >> 2u)) >> 1u;
|
||||
|
||||
pSrc[2u * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16)) +
|
||||
((int16_t) (((q31_t) yt * sinVal) >> 16)));
|
||||
|
||||
pSrc[2u * l + 1u] = (((int16_t) (((q31_t) yt * cosVal) >> 16)) -
|
||||
((int16_t) (((q31_t) xt * sinVal) >> 16)));
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
|
||||
// loop for stage
|
||||
for (k = fftLen / 2; k > 2; k = k >> 1)
|
||||
{
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (j = 0; j < n2; j++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = j; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1u;
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1u;
|
||||
|
||||
pSrc[2u * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16)) +
|
||||
((int16_t) (((q31_t) yt * sinVal) >> 16)));
|
||||
|
||||
pSrc[2u * l + 1u] = (((int16_t) (((q31_t) yt * cosVal) >> 16)) -
|
||||
((int16_t) (((q31_t) xt * sinVal) >> 16)));
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
} // stages loop end
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (j = 0; j < n2; j++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = j; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
|
||||
|
||||
pSrc[2u * l] = xt;
|
||||
|
||||
pSrc[2u * l + 1u] = yt;
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
|
||||
#endif // #ifndef ARM_MATH_CM0
|
||||
|
||||
}
|
||||
|
||||
|
||||
void arm_radix2_butterfly_inverse_q15(
|
||||
q15_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
q15_t * pCoef,
|
||||
uint16_t twidCoefModifier)
|
||||
{
|
||||
#ifndef ARM_MATH_CM0
|
||||
|
||||
int i, j, k, l;
|
||||
int n1, n2, ia;
|
||||
q15_t in;
|
||||
q31_t T, S, R;
|
||||
q31_t coeff, out1, out2;
|
||||
|
||||
//N = fftLen;
|
||||
n2 = fftLen;
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (i = 0; i < n2; i++)
|
||||
{
|
||||
coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
|
||||
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
l = i + n2;
|
||||
|
||||
T = _SIMD32_OFFSET(pSrc + (2 * i));
|
||||
in = ((int16_t) (T & 0xFFFF)) >> 2;
|
||||
T = ((T >> 2) & 0xFFFF0000) | (in & 0xFFFF);
|
||||
|
||||
S = _SIMD32_OFFSET(pSrc + (2 * l));
|
||||
in = ((int16_t) (S & 0xFFFF)) >> 2;
|
||||
S = ((S >> 2) & 0xFFFF0000) | (in & 0xFFFF);
|
||||
|
||||
R = __QSUB16(T, S);
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
out1 = __SMUSD(coeff, R) >> 16;
|
||||
out2 = __SMUADX(coeff, R);
|
||||
#else
|
||||
|
||||
out1 = __SMUADX(R, coeff) >> 16u;
|
||||
out2 = __SMUSD(__QSUB(0, coeff), R);
|
||||
|
||||
#endif // #ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2u * l)) =
|
||||
(q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
|
||||
|
||||
coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
|
||||
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
i++;
|
||||
l++;
|
||||
|
||||
T = _SIMD32_OFFSET(pSrc + (2 * i));
|
||||
in = ((int16_t) (T & 0xFFFF)) >> 2;
|
||||
T = ((T >> 2) & 0xFFFF0000) | (in & 0xFFFF);
|
||||
|
||||
S = _SIMD32_OFFSET(pSrc + (2 * l));
|
||||
in = ((int16_t) (S & 0xFFFF)) >> 2;
|
||||
S = ((S >> 2) & 0xFFFF0000) | (in & 0xFFFF);
|
||||
|
||||
R = __QSUB16(T, S);
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
out1 = __SMUSD(coeff, R) >> 16;
|
||||
out2 = __SMUADX(coeff, R);
|
||||
#else
|
||||
|
||||
out1 = __SMUADX(R, coeff) >> 16u;
|
||||
out2 = __SMUSD(__QSUB(0, coeff), R);
|
||||
|
||||
#endif // #ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2u * l)) =
|
||||
(q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
|
||||
// loop for stage
|
||||
for (k = fftLen / 2; k > 2; k = k >> 1)
|
||||
{
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (j = 0; j < n2; j++)
|
||||
{
|
||||
coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
|
||||
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = j; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
|
||||
T = _SIMD32_OFFSET(pSrc + (2 * i));
|
||||
|
||||
S = _SIMD32_OFFSET(pSrc + (2 * l));
|
||||
|
||||
R = __QSUB16(T, S);
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
out1 = __SMUSD(coeff, R) >> 16;
|
||||
out2 = __SMUADX(coeff, R);
|
||||
|
||||
#else
|
||||
|
||||
out1 = __SMUADX(R, coeff) >> 16u;
|
||||
out2 = __SMUSD(__QSUB(0, coeff), R);
|
||||
|
||||
#endif // #ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2u * l)) =
|
||||
(q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
|
||||
|
||||
i += n1;
|
||||
|
||||
l = i + n2;
|
||||
|
||||
T = _SIMD32_OFFSET(pSrc + (2 * i));
|
||||
|
||||
S = _SIMD32_OFFSET(pSrc + (2 * l));
|
||||
|
||||
R = __QSUB16(T, S);
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2 * i)) = __SHADD16(T, S);
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
out1 = __SMUSD(coeff, R) >> 16;
|
||||
out2 = __SMUADX(coeff, R);
|
||||
#else
|
||||
|
||||
out1 = __SMUADX(R, coeff) >> 16u;
|
||||
out2 = __SMUSD(__QSUB(0, coeff), R);
|
||||
|
||||
#endif // #ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2u * l)) =
|
||||
(q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
} // stages loop end
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (j = 0; j < n2; j++)
|
||||
{
|
||||
coeff = _SIMD32_OFFSET(pCoef + (ia * 2u));
|
||||
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = j; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
|
||||
T = _SIMD32_OFFSET(pSrc + (2 * i));
|
||||
|
||||
S = _SIMD32_OFFSET(pSrc + (2 * l));
|
||||
|
||||
R = __QSUB16(T, S);
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2 * i)) = __QADD16(T, S);
|
||||
|
||||
_SIMD32_OFFSET(pSrc + (2u * l)) = R;
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
|
||||
#else
|
||||
|
||||
|
||||
int i, j, k, l;
|
||||
int n1, n2, ia;
|
||||
q15_t xt, yt, cosVal, sinVal;
|
||||
|
||||
//N = fftLen;
|
||||
n2 = fftLen;
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (j = 0; j < n2; j++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = j; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = (pSrc[2 * i] >> 2u) - (pSrc[2 * l] >> 2u);
|
||||
pSrc[2 * i] = ((pSrc[2 * i] >> 2u) + (pSrc[2 * l] >> 2u)) >> 1u;
|
||||
|
||||
yt = (pSrc[2 * i + 1] >> 2u) - (pSrc[2 * l + 1] >> 2u);
|
||||
pSrc[2 * i + 1] =
|
||||
((pSrc[2 * l + 1] >> 2u) + (pSrc[2 * i + 1] >> 2u)) >> 1u;
|
||||
|
||||
pSrc[2u * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16)) -
|
||||
((int16_t) (((q31_t) yt * sinVal) >> 16)));
|
||||
|
||||
pSrc[2u * l + 1u] = (((int16_t) (((q31_t) yt * cosVal) >> 16)) +
|
||||
((int16_t) (((q31_t) xt * sinVal) >> 16)));
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
|
||||
// loop for stage
|
||||
for (k = fftLen / 2; k > 2; k = k >> 1)
|
||||
{
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (j = 0; j < n2; j++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = j; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1u;
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1u;
|
||||
|
||||
pSrc[2u * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16)) -
|
||||
((int16_t) (((q31_t) yt * sinVal) >> 16)));
|
||||
|
||||
pSrc[2u * l + 1u] = (((int16_t) (((q31_t) yt * cosVal) >> 16)) +
|
||||
((int16_t) (((q31_t) xt * sinVal) >> 16)));
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
} // stages loop end
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = 0; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
|
||||
|
||||
pSrc[2u * l] = xt;
|
||||
|
||||
pSrc[2u * l + 1u] = yt;
|
||||
|
||||
} // groups loop end
|
||||
|
||||
|
||||
#endif // #ifndef ARM_MATH_CM0
|
||||
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_cfft_radix2_q31.c
|
||||
*
|
||||
* Description: Radix-2 Decimation in Frequency CFFT & CIFFT Fixed point processing function
|
||||
*
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 0.0.3 2010/03/10
|
||||
* Initial version
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupTransforms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup Radix2_CFFT_CIFFT Radix-2 Complex FFT Functions
|
||||
*
|
||||
* \par
|
||||
* 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).
|
||||
* Computational complexity of CFFT reduces drastically when compared to DFT.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup Radix2_CFFT_CIFFT
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @details
|
||||
* @brief Processing function for the fixed-point CFFT/CIFFT.
|
||||
* @param[in] *S points to an instance of the fixed-point CFFT/CIFFT structure.
|
||||
* @param[in, out] *pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_cfft_radix2_q31(
|
||||
const arm_cfft_radix2_instance_q31 * S,
|
||||
q31_t * pSrc)
|
||||
{
|
||||
|
||||
if(S->ifftFlag == 1u)
|
||||
{
|
||||
arm_radix2_butterfly_inverse_q31(pSrc, S->fftLen,
|
||||
S->pTwiddle, S->twidCoefModifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
arm_radix2_butterfly_q31(pSrc, S->fftLen,
|
||||
S->pTwiddle, S->twidCoefModifier);
|
||||
}
|
||||
|
||||
arm_bitreversal_q31(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of Radix2_CFFT_CIFFT group
|
||||
*/
|
||||
|
||||
void arm_radix2_butterfly_q31(
|
||||
q31_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
q31_t * pCoef,
|
||||
uint16_t twidCoefModifier)
|
||||
{
|
||||
|
||||
int i, j, k, l;
|
||||
int n1, n2, ia;
|
||||
q31_t xt, yt, cosVal, sinVal;
|
||||
|
||||
//N = fftLen;
|
||||
n2 = fftLen;
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (i = 0; i < n2; i++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
l = i + n2;
|
||||
xt = (pSrc[2 * i] >> 2u) - (pSrc[2 * l] >> 2u);
|
||||
pSrc[2 * i] = ((pSrc[2 * i] >> 2u) + (pSrc[2 * l] >> 2u)) >> 1u;
|
||||
|
||||
yt = (pSrc[2 * i + 1] >> 2u) - (pSrc[2 * l + 1] >> 2u);
|
||||
pSrc[2 * i + 1] =
|
||||
((pSrc[2 * l + 1] >> 2u) + (pSrc[2 * i + 1] >> 2u)) >> 1u;
|
||||
|
||||
pSrc[2u * l] = (((int32_t) (((q63_t) xt * cosVal) >> 32)) +
|
||||
((int32_t) (((q63_t) yt * sinVal) >> 32)));
|
||||
|
||||
pSrc[2u * l + 1u] = (((int32_t) (((q63_t) yt * cosVal) >> 32)) -
|
||||
((int32_t) (((q63_t) xt * sinVal) >> 32)));
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
|
||||
// loop for stage
|
||||
for (k = fftLen / 2; k > 2; k = k >> 1)
|
||||
{
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (j = 0; j < n2; j++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = j; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1u;
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1u;
|
||||
|
||||
pSrc[2u * l] = (((int32_t) (((q63_t) xt * cosVal) >> 32)) +
|
||||
((int32_t) (((q63_t) yt * sinVal) >> 32)));
|
||||
|
||||
pSrc[2u * l + 1u] = (((int32_t) (((q63_t) yt * cosVal) >> 32)) -
|
||||
((int32_t) (((q63_t) xt * sinVal) >> 32)));
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
} // stages loop end
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = 0; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
|
||||
|
||||
pSrc[2u * l] = xt;
|
||||
|
||||
pSrc[2u * l + 1u] = yt;
|
||||
|
||||
i += n1;
|
||||
l = i + n2;
|
||||
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
|
||||
|
||||
pSrc[2u * l] = xt;
|
||||
|
||||
pSrc[2u * l + 1u] = yt;
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
}
|
||||
|
||||
|
||||
void arm_radix2_butterfly_inverse_q31(
|
||||
q31_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
q31_t * pCoef,
|
||||
uint16_t twidCoefModifier)
|
||||
{
|
||||
|
||||
int i, j, k, l;
|
||||
int n1, n2, ia;
|
||||
q31_t xt, yt, cosVal, sinVal;
|
||||
|
||||
//N = fftLen;
|
||||
n2 = fftLen;
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (i = 0; i < n2; i++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
l = i + n2;
|
||||
xt = (pSrc[2 * i] >> 2u) - (pSrc[2 * l] >> 2u);
|
||||
pSrc[2 * i] = ((pSrc[2 * i] >> 2u) + (pSrc[2 * l] >> 2u)) >> 1u;
|
||||
|
||||
yt = (pSrc[2 * i + 1] >> 2u) - (pSrc[2 * l + 1] >> 2u);
|
||||
pSrc[2 * i + 1] =
|
||||
((pSrc[2 * l + 1] >> 2u) + (pSrc[2 * i + 1] >> 2u)) >> 1u;
|
||||
|
||||
pSrc[2u * l] = (((int32_t) (((q63_t) xt * cosVal) >> 32)) -
|
||||
((int32_t) (((q63_t) yt * sinVal) >> 32)));
|
||||
|
||||
pSrc[2u * l + 1u] = (((int32_t) (((q63_t) yt * cosVal) >> 32)) +
|
||||
((int32_t) (((q63_t) xt * sinVal) >> 32)));
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
|
||||
// loop for stage
|
||||
for (k = fftLen / 2; k > 2; k = k >> 1)
|
||||
{
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
// loop for groups
|
||||
for (j = 0; j < n2; j++)
|
||||
{
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = j; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1u;
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1u;
|
||||
|
||||
pSrc[2u * l] = (((int32_t) (((q63_t) xt * cosVal) >> 32)) -
|
||||
((int32_t) (((q63_t) yt * sinVal) >> 32)));
|
||||
|
||||
pSrc[2u * l + 1u] = (((int32_t) (((q63_t) yt * cosVal) >> 32)) +
|
||||
((int32_t) (((q63_t) xt * sinVal) >> 32)));
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
} // groups loop end
|
||||
|
||||
twidCoefModifier = twidCoefModifier << 1u;
|
||||
} // stages loop end
|
||||
|
||||
n1 = n2;
|
||||
n2 = n2 >> 1;
|
||||
ia = 0;
|
||||
|
||||
cosVal = pCoef[ia * 2];
|
||||
sinVal = pCoef[(ia * 2) + 1];
|
||||
ia = ia + twidCoefModifier;
|
||||
|
||||
// loop for butterfly
|
||||
for (i = 0; i < fftLen; i += n1)
|
||||
{
|
||||
l = i + n2;
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
|
||||
|
||||
pSrc[2u * l] = xt;
|
||||
|
||||
pSrc[2u * l + 1u] = yt;
|
||||
|
||||
i += n1;
|
||||
l = i + n2;
|
||||
|
||||
xt = pSrc[2 * i] - pSrc[2 * l];
|
||||
pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
|
||||
|
||||
yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
|
||||
pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
|
||||
|
||||
pSrc[2u * l] = xt;
|
||||
|
||||
pSrc[2u * l + 1u] = yt;
|
||||
|
||||
} // butterfly loop end
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,161 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_cfft_radix4_init_f32.c
|
||||
*
|
||||
* Description: Radix-4 Decimation in Frequency Floating-point CFFT & CIFFT Initialization function
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 1.0.10 2011/7/15
|
||||
* Big Endian support added and Merged M0 and M3/M4 Source code.
|
||||
*
|
||||
* Version 1.0.3 2010/11/29
|
||||
* Re-organized the CMSIS folders and updated documentation.
|
||||
*
|
||||
* Version 1.0.2 2010/11/11
|
||||
* Documentation updated.
|
||||
*
|
||||
* Version 1.0.1 2010/10/05
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 1.0.0 2010/09/20
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 0.0.5 2010/04/26
|
||||
* incorporated review comments and updated with latest CMSIS layer
|
||||
*
|
||||
* Version 0.0.3 2010/03/10
|
||||
* Initial version
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "arm_math.h"
|
||||
#include "arm_common_tables.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupTransforms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup Radix4_CFFT_CIFFT
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialization function for the floating-point CFFT/CIFFT.
|
||||
* @param[in,out] *S points to an instance of the floating-point CFFT/CIFFT structure.
|
||||
* @param[in] fftLen length of the FFT.
|
||||
* @param[in] ifftFlag flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
|
||||
* @param[in] bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
|
||||
* @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLen</code> is not a supported value.
|
||||
*
|
||||
* \par Description:
|
||||
* \par
|
||||
* The parameter <code>ifftFlag</code> controls whether a forward or inverse transform is computed.
|
||||
* Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated
|
||||
* \par
|
||||
* The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order.
|
||||
* Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order.
|
||||
* \par
|
||||
* The parameter <code>fftLen</code> Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024.
|
||||
* \par
|
||||
* This Function also initializes Twiddle factor table pointer and Bit reversal table pointer.
|
||||
*/
|
||||
|
||||
arm_status arm_cfft_radix4_init_f32(
|
||||
arm_cfft_radix4_instance_f32 * S,
|
||||
uint16_t fftLen,
|
||||
uint8_t ifftFlag,
|
||||
uint8_t bitReverseFlag)
|
||||
{
|
||||
/* Initialise the default arm status */
|
||||
arm_status status = ARM_MATH_SUCCESS;
|
||||
|
||||
/* Initialise the FFT length */
|
||||
S->fftLen = fftLen;
|
||||
|
||||
/* Initialise the Twiddle coefficient pointer */
|
||||
S->pTwiddle = (float32_t *) twiddleCoef;
|
||||
|
||||
/* Initialise the Flag for selection of CFFT or CIFFT */
|
||||
S->ifftFlag = ifftFlag;
|
||||
|
||||
/* Initialise the Flag for calculation Bit reversal or not */
|
||||
S->bitReverseFlag = bitReverseFlag;
|
||||
|
||||
/* Initializations of structure parameters depending on the FFT length */
|
||||
switch (S->fftLen)
|
||||
{
|
||||
|
||||
case 4096u:
|
||||
/* Initializations of structure parameters for 4096 point FFT */
|
||||
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 1u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 1u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) armBitRevTable;
|
||||
/* Initialise the 1/fftLen Value */
|
||||
S->onebyfftLen = 0.000244140625;
|
||||
break;
|
||||
|
||||
case 1024u:
|
||||
/* Initializations of structure parameters for 1024 point FFT */
|
||||
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 4u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 4u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[3];
|
||||
/* Initialise the 1/fftLen Value */
|
||||
S->onebyfftLen = 0.0009765625f;
|
||||
break;
|
||||
|
||||
|
||||
case 256u:
|
||||
/* Initializations of structure parameters for 256 point FFT */
|
||||
S->twidCoefModifier = 16u;
|
||||
S->bitRevFactor = 16u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[15];
|
||||
S->onebyfftLen = 0.00390625f;
|
||||
break;
|
||||
|
||||
case 64u:
|
||||
/* Initializations of structure parameters for 64 point FFT */
|
||||
S->twidCoefModifier = 64u;
|
||||
S->bitRevFactor = 64u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[63];
|
||||
S->onebyfftLen = 0.015625f;
|
||||
break;
|
||||
|
||||
case 16u:
|
||||
/* Initializations of structure parameters for 16 point FFT */
|
||||
S->twidCoefModifier = 256u;
|
||||
S->bitRevFactor = 256u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[255];
|
||||
S->onebyfftLen = 0.0625f;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
/* Reporting argument error if fftSize is not valid value */
|
||||
status = ARM_MATH_ARGUMENT_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of Radix4_CFFT_CIFFT group
|
||||
*/
|
||||
@@ -0,0 +1,149 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_cfft_radix4_init_q15.c
|
||||
*
|
||||
* Description: Radix-4 Decimation in Frequency Q15 FFT & IFFT initialization function
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 1.0.10 2011/7/15
|
||||
* Big Endian support added and Merged M0 and M3/M4 Source code.
|
||||
*
|
||||
* Version 1.0.3 2010/11/29
|
||||
* Re-organized the CMSIS folders and updated documentation.
|
||||
*
|
||||
* Version 1.0.2 2010/11/11
|
||||
* Documentation updated.
|
||||
*
|
||||
* Version 1.0.1 2010/10/05
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 1.0.0 2010/09/20
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 0.0.5 2010/04/26
|
||||
* incorporated review comments and updated with latest CMSIS layer
|
||||
*
|
||||
* Version 0.0.3 2010/03/10
|
||||
* Initial version
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
#include "arm_common_tables.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupTransforms
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup Radix4_CFFT_CIFFT
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialization function for the Q15 CFFT/CIFFT.
|
||||
* @param[in,out] *S points to an instance of the Q15 CFFT/CIFFT structure.
|
||||
* @param[in] fftLen length of the FFT.
|
||||
* @param[in] ifftFlag flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
|
||||
* @param[in] bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
|
||||
* @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLen</code> is not a supported value.
|
||||
*
|
||||
* \par Description:
|
||||
* \par
|
||||
* The parameter <code>ifftFlag</code> controls whether a forward or inverse transform is computed.
|
||||
* Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated
|
||||
* \par
|
||||
* The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order.
|
||||
* Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order.
|
||||
* \par
|
||||
* The parameter <code>fftLen</code> Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024.
|
||||
* \par
|
||||
* This Function also initializes Twiddle factor table pointer and Bit reversal table pointer.
|
||||
*/
|
||||
|
||||
arm_status arm_cfft_radix4_init_q15(
|
||||
arm_cfft_radix4_instance_q15 * S,
|
||||
uint16_t fftLen,
|
||||
uint8_t ifftFlag,
|
||||
uint8_t bitReverseFlag)
|
||||
{
|
||||
/* Initialise the default arm status */
|
||||
arm_status status = ARM_MATH_SUCCESS;
|
||||
/* Initialise the FFT length */
|
||||
S->fftLen = fftLen;
|
||||
/* Initialise the Twiddle coefficient pointer */
|
||||
S->pTwiddle = (q15_t *) twiddleCoefQ15;
|
||||
/* Initialise the Flag for selection of CFFT or CIFFT */
|
||||
S->ifftFlag = ifftFlag;
|
||||
/* Initialise the Flag for calculation Bit reversal or not */
|
||||
S->bitReverseFlag = bitReverseFlag;
|
||||
|
||||
/* Initializations of structure parameters depending on the FFT length */
|
||||
switch (S->fftLen)
|
||||
{
|
||||
case 4096u:
|
||||
/* Initializations of structure parameters for 4096 point FFT */
|
||||
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 1u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 1u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) armBitRevTable;
|
||||
|
||||
break;
|
||||
|
||||
case 1024u:
|
||||
/* Initializations of structure parameters for 1024 point FFT */
|
||||
S->twidCoefModifier = 4u;
|
||||
S->bitRevFactor = 4u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[3];
|
||||
|
||||
break;
|
||||
|
||||
case 256u:
|
||||
/* Initializations of structure parameters for 256 point FFT */
|
||||
S->twidCoefModifier = 16u;
|
||||
S->bitRevFactor = 16u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[15];
|
||||
|
||||
break;
|
||||
|
||||
case 64u:
|
||||
/* Initializations of structure parameters for 64 point FFT */
|
||||
S->twidCoefModifier = 64u;
|
||||
S->bitRevFactor = 64u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[63];
|
||||
|
||||
break;
|
||||
|
||||
case 16u:
|
||||
/* Initializations of structure parameters for 16 point FFT */
|
||||
S->twidCoefModifier = 256u;
|
||||
S->bitRevFactor = 256u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[255];
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Reporting argument error if fftSize is not valid value */
|
||||
status = ARM_MATH_ARGUMENT_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of Radix4_CFFT_CIFFT group
|
||||
*/
|
||||
@@ -0,0 +1,145 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_cfft_radix4_init_q31.c
|
||||
*
|
||||
* Description: Radix-4 Decimation in Frequency Q31 FFT & IFFT initialization function
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 1.0.10 2011/7/15
|
||||
* Big Endian support added and Merged M0 and M3/M4 Source code.
|
||||
*
|
||||
* Version 1.0.3 2010/11/29
|
||||
* Re-organized the CMSIS folders and updated documentation.
|
||||
*
|
||||
* Version 1.0.2 2010/11/11
|
||||
* Documentation updated.
|
||||
*
|
||||
* Version 1.0.1 2010/10/05
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 1.0.0 2010/09/20
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 0.0.5 2010/04/26
|
||||
* incorporated review comments and updated with latest CMSIS layer
|
||||
*
|
||||
* Version 0.0.3 2010/03/10
|
||||
* Initial version
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
#include "arm_common_tables.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupTransforms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup Radix4_CFFT_CIFFT
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Initialization function for the Q31 CFFT/CIFFT.
|
||||
* @param[in,out] *S points to an instance of the Q31 CFFT/CIFFT structure.
|
||||
* @param[in] fftLen length of the FFT.
|
||||
* @param[in] ifftFlag flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
|
||||
* @param[in] bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
|
||||
* @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLen</code> is not a supported value.
|
||||
*
|
||||
* \par Description:
|
||||
* \par
|
||||
* The parameter <code>ifftFlag</code> controls whether a forward or inverse transform is computed.
|
||||
* Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated
|
||||
* \par
|
||||
* The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order.
|
||||
* Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order.
|
||||
* \par
|
||||
* The parameter <code>fftLen</code> Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024.
|
||||
* \par
|
||||
* This Function also initializes Twiddle factor table pointer and Bit reversal table pointer.
|
||||
*/
|
||||
|
||||
arm_status arm_cfft_radix4_init_q31(
|
||||
arm_cfft_radix4_instance_q31 * S,
|
||||
uint16_t fftLen,
|
||||
uint8_t ifftFlag,
|
||||
uint8_t bitReverseFlag)
|
||||
{
|
||||
/* Initialise the default arm status */
|
||||
arm_status status = ARM_MATH_SUCCESS;
|
||||
/* Initialise the FFT length */
|
||||
S->fftLen = fftLen;
|
||||
/* Initialise the Twiddle coefficient pointer */
|
||||
S->pTwiddle = (q31_t *) twiddleCoefQ31;
|
||||
/* Initialise the Flag for selection of CFFT or CIFFT */
|
||||
S->ifftFlag = ifftFlag;
|
||||
/* Initialise the Flag for calculation Bit reversal or not */
|
||||
S->bitReverseFlag = bitReverseFlag;
|
||||
|
||||
/* Initializations of Instance structure depending on the FFT length */
|
||||
switch (S->fftLen)
|
||||
{
|
||||
/* Initializations of structure parameters for 4096 point FFT */
|
||||
case 4096u:
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 1u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 1u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) armBitRevTable;
|
||||
break;
|
||||
|
||||
/* Initializations of structure parameters for 1024 point FFT */
|
||||
case 1024u:
|
||||
/* Initialise the twiddle coef modifier value */
|
||||
S->twidCoefModifier = 4u;
|
||||
/* Initialise the bit reversal table modifier */
|
||||
S->bitRevFactor = 4u;
|
||||
/* Initialise the bit reversal table pointer */
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[3];
|
||||
break;
|
||||
|
||||
case 256u:
|
||||
/* Initializations of structure parameters for 256 point FFT */
|
||||
S->twidCoefModifier = 16u;
|
||||
S->bitRevFactor = 16u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[15];
|
||||
break;
|
||||
|
||||
case 64u:
|
||||
/* Initializations of structure parameters for 64 point FFT */
|
||||
S->twidCoefModifier = 64u;
|
||||
S->bitRevFactor = 64u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[63];
|
||||
break;
|
||||
|
||||
case 16u:
|
||||
/* Initializations of structure parameters for 16 point FFT */
|
||||
S->twidCoefModifier = 256u;
|
||||
S->bitRevFactor = 256u;
|
||||
S->pBitRevTable = (uint16_t *) & armBitRevTable[255];
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Reporting argument error if fftSize is not valid value */
|
||||
status = ARM_MATH_ARGUMENT_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of Radix4_CFFT_CIFFT group
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,891 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_cfft_radix4_q31.c
|
||||
*
|
||||
* Description: This file has function definition of Radix-4 FFT & IFFT function and
|
||||
* In-place bit reversal using bit reversal table
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 1.0.10 2011/7/15
|
||||
* Big Endian support added and Merged M0 and M3/M4 Source code.
|
||||
*
|
||||
* Version 1.0.3 2010/11/29
|
||||
* Re-organized the CMSIS folders and updated documentation.
|
||||
*
|
||||
* Version 1.0.2 2010/11/11
|
||||
* Documentation updated.
|
||||
*
|
||||
* Version 1.0.1 2010/10/05
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 1.0.0 2010/09/20
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 0.0.5 2010/04/26
|
||||
* incorporated review comments and updated with latest CMSIS layer
|
||||
*
|
||||
* Version 0.0.3 2010/03/10
|
||||
* Initial version
|
||||
* -------------------------------------------------------------------- */
|
||||
#include "arm_math.h"
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup groupTransforms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup Radix4_CFFT_CIFFT
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @details
|
||||
* @brief Processing function for the Q31 CFFT/CIFFT.
|
||||
* @param[in] *S points to an instance of the Q31 CFFT/CIFFT structure.
|
||||
* @param[in, out] *pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place.
|
||||
* @return none.
|
||||
*
|
||||
* \par Input and output formats:
|
||||
* \par
|
||||
* Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process.
|
||||
* Hence the output format is different for different FFT sizes.
|
||||
* The input and output formats for different FFT sizes and number of bits to upscale are mentioned in the tables below for CFFT and CIFFT:
|
||||
* \par
|
||||
* \image html CFFTQ31.gif "Input and Output Formats for Q31 CFFT"
|
||||
* \image html CIFFTQ31.gif "Input and Output Formats for Q31 CIFFT"
|
||||
*
|
||||
*/
|
||||
|
||||
void arm_cfft_radix4_q31(
|
||||
const arm_cfft_radix4_instance_q31 * S,
|
||||
q31_t * pSrc)
|
||||
{
|
||||
if(S->ifftFlag == 1u)
|
||||
{
|
||||
/* Complex IFFT radix-4 */
|
||||
arm_radix4_butterfly_inverse_q31(pSrc, S->fftLen, S->pTwiddle,
|
||||
S->twidCoefModifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Complex FFT radix-4 */
|
||||
arm_radix4_butterfly_q31(pSrc, S->fftLen, S->pTwiddle,
|
||||
S->twidCoefModifier);
|
||||
}
|
||||
|
||||
|
||||
if(S->bitReverseFlag == 1u)
|
||||
{
|
||||
/* Bit Reversal */
|
||||
arm_bitreversal_q31(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of Radix4_CFFT_CIFFT group
|
||||
*/
|
||||
|
||||
/*
|
||||
* Radix-4 FFT algorithm used is :
|
||||
*
|
||||
* Input real and imaginary data:
|
||||
* x(n) = xa + j * ya
|
||||
* x(n+N/4 ) = xb + j * yb
|
||||
* x(n+N/2 ) = xc + j * yc
|
||||
* x(n+3N 4) = xd + j * yd
|
||||
*
|
||||
*
|
||||
* Output real and imaginary data:
|
||||
* x(4r) = xa'+ j * ya'
|
||||
* x(4r+1) = xb'+ j * yb'
|
||||
* x(4r+2) = xc'+ j * yc'
|
||||
* x(4r+3) = xd'+ j * yd'
|
||||
*
|
||||
*
|
||||
* Twiddle factors for radix-4 FFT:
|
||||
* Wn = co1 + j * (- si1)
|
||||
* W2n = co2 + j * (- si2)
|
||||
* W3n = co3 + j * (- si3)
|
||||
*
|
||||
* Butterfly implementation:
|
||||
* xa' = xa + xb + xc + xd
|
||||
* ya' = ya + yb + yc + yd
|
||||
* xb' = (xa+yb-xc-yd)* co1 + (ya-xb-yc+xd)* (si1)
|
||||
* yb' = (ya-xb-yc+xd)* co1 - (xa+yb-xc-yd)* (si1)
|
||||
* xc' = (xa-xb+xc-xd)* co2 + (ya-yb+yc-yd)* (si2)
|
||||
* yc' = (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2)
|
||||
* xd' = (xa-yb-xc+yd)* co3 + (ya+xb-yc-xd)* (si3)
|
||||
* yd' = (ya+xb-yc-xd)* co3 - (xa-yb-xc+yd)* (si3)
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Core function for the Q31 CFFT butterfly process.
|
||||
* @param[in, out] *pSrc points to the in-place buffer of Q31 data type.
|
||||
* @param[in] fftLen length of the FFT.
|
||||
* @param[in] *pCoef points to twiddle coefficient buffer.
|
||||
* @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_radix4_butterfly_q31(
|
||||
q31_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
q31_t * pCoef,
|
||||
uint32_t twidCoefModifier)
|
||||
{
|
||||
uint32_t n1, n2, ia1, ia2, ia3, i0, i1, i2, i3, j, k;
|
||||
q31_t t1, t2, r1, r2, s1, s2, co1, co2, co3, si1, si2, si3;
|
||||
|
||||
q31_t xa, xb, xc, xd;
|
||||
q31_t ya, yb, yc, yd;
|
||||
q31_t xa_out, xb_out, xc_out, xd_out;
|
||||
q31_t ya_out, yb_out, yc_out, yd_out;
|
||||
|
||||
q31_t *ptr1;
|
||||
q63_t xaya, xbyb, xcyc, xdyd;
|
||||
/* Total process is divided into three stages */
|
||||
|
||||
/* process first stage, middle stages, & last stage */
|
||||
|
||||
|
||||
/* start of first stage process */
|
||||
|
||||
/* Initializations for the first stage */
|
||||
n2 = fftLen;
|
||||
n1 = n2;
|
||||
/* n2 = fftLen/4 */
|
||||
n2 >>= 2u;
|
||||
i0 = 0u;
|
||||
ia1 = 0u;
|
||||
|
||||
j = n2;
|
||||
|
||||
/* Calculation of first stage */
|
||||
do
|
||||
{
|
||||
/* index calculation for the input as, */
|
||||
/* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2u], pSrc[i0 + 3fftLen/4] */
|
||||
i1 = i0 + n2;
|
||||
i2 = i1 + n2;
|
||||
i3 = i2 + n2;
|
||||
|
||||
/* input is in 1.31(q31) format and provide 4 guard bits for the input */
|
||||
|
||||
/* Butterfly implementation */
|
||||
/* xa + xc */
|
||||
r1 = (pSrc[(2u * i0)] >> 4u) + (pSrc[(2u * i2)] >> 4u);
|
||||
/* xa - xc */
|
||||
r2 = (pSrc[2u * i0] >> 4u) - (pSrc[2u * i2] >> 4u);
|
||||
|
||||
/* xb + xd */
|
||||
t1 = (pSrc[2u * i1] >> 4u) + (pSrc[2u * i3] >> 4u);
|
||||
|
||||
/* ya + yc */
|
||||
s1 = (pSrc[(2u * i0) + 1u] >> 4u) + (pSrc[(2u * i2) + 1u] >> 4u);
|
||||
/* ya - yc */
|
||||
s2 = (pSrc[(2u * i0) + 1u] >> 4u) - (pSrc[(2u * i2) + 1u] >> 4u);
|
||||
|
||||
/* xa' = xa + xb + xc + xd */
|
||||
pSrc[2u * i0] = (r1 + t1);
|
||||
/* (xa + xc) - (xb + xd) */
|
||||
r1 = r1 - t1;
|
||||
/* yb + yd */
|
||||
t2 = (pSrc[(2u * i1) + 1u] >> 4u) + (pSrc[(2u * i3) + 1u] >> 4u);
|
||||
|
||||
/* ya' = ya + yb + yc + yd */
|
||||
pSrc[(2u * i0) + 1u] = (s1 + t2);
|
||||
|
||||
/* (ya + yc) - (yb + yd) */
|
||||
s1 = s1 - t2;
|
||||
|
||||
/* yb - yd */
|
||||
t1 = (pSrc[(2u * i1) + 1u] >> 4u) - (pSrc[(2u * i3) + 1u] >> 4u);
|
||||
/* xb - xd */
|
||||
t2 = (pSrc[2u * i1] >> 4u) - (pSrc[2u * i3] >> 4u);
|
||||
|
||||
/* index calculation for the coefficients */
|
||||
ia2 = 2u * ia1;
|
||||
co2 = pCoef[ia2 * 2u];
|
||||
si2 = pCoef[(ia2 * 2u) + 1u];
|
||||
|
||||
/* xc' = (xa-xb+xc-xd)co2 + (ya-yb+yc-yd)(si2) */
|
||||
pSrc[2u * i1] = (((int32_t) (((q63_t) r1 * co2) >> 32)) +
|
||||
((int32_t) (((q63_t) s1 * si2) >> 32))) << 1u;
|
||||
|
||||
/* yc' = (ya-yb+yc-yd)co2 - (xa-xb+xc-xd)(si2) */
|
||||
pSrc[(2u * i1) + 1u] = (((int32_t) (((q63_t) s1 * co2) >> 32)) -
|
||||
((int32_t) (((q63_t) r1 * si2) >> 32))) << 1u;
|
||||
|
||||
/* (xa - xc) + (yb - yd) */
|
||||
r1 = r2 + t1;
|
||||
/* (xa - xc) - (yb - yd) */
|
||||
r2 = r2 - t1;
|
||||
|
||||
/* (ya - yc) - (xb - xd) */
|
||||
s1 = s2 - t2;
|
||||
/* (ya - yc) + (xb - xd) */
|
||||
s2 = s2 + t2;
|
||||
|
||||
co1 = pCoef[ia1 * 2u];
|
||||
si1 = pCoef[(ia1 * 2u) + 1u];
|
||||
|
||||
/* xb' = (xa+yb-xc-yd)co1 + (ya-xb-yc+xd)(si1) */
|
||||
pSrc[2u * i2] = (((int32_t) (((q63_t) r1 * co1) >> 32)) +
|
||||
((int32_t) (((q63_t) s1 * si1) >> 32))) << 1u;
|
||||
|
||||
/* yb' = (ya-xb-yc+xd)co1 - (xa+yb-xc-yd)(si1) */
|
||||
pSrc[(2u * i2) + 1u] = (((int32_t) (((q63_t) s1 * co1) >> 32)) -
|
||||
((int32_t) (((q63_t) r1 * si1) >> 32))) << 1u;
|
||||
|
||||
/* index calculation for the coefficients */
|
||||
ia3 = 3u * ia1;
|
||||
co3 = pCoef[ia3 * 2u];
|
||||
si3 = pCoef[(ia3 * 2u) + 1u];
|
||||
|
||||
/* xd' = (xa-yb-xc+yd)co3 + (ya+xb-yc-xd)(si3) */
|
||||
pSrc[2u * i3] = (((int32_t) (((q63_t) r2 * co3) >> 32)) +
|
||||
((int32_t) (((q63_t) s2 * si3) >> 32))) << 1u;
|
||||
|
||||
/* yd' = (ya+xb-yc-xd)co3 - (xa-yb-xc+yd)(si3) */
|
||||
pSrc[(2u * i3) + 1u] = (((int32_t) (((q63_t) s2 * co3) >> 32)) -
|
||||
((int32_t) (((q63_t) r2 * si3) >> 32))) << 1u;
|
||||
|
||||
/* Twiddle coefficients index modifier */
|
||||
ia1 = ia1 + twidCoefModifier;
|
||||
|
||||
/* Updating input index */
|
||||
i0 = i0 + 1u;
|
||||
|
||||
} while(--j);
|
||||
|
||||
/* end of first stage process */
|
||||
|
||||
/* data is in 5.27(q27) format */
|
||||
|
||||
|
||||
/* start of Middle stages process */
|
||||
|
||||
|
||||
/* each stage in middle stages provides two down scaling of the input */
|
||||
|
||||
twidCoefModifier <<= 2u;
|
||||
|
||||
|
||||
for (k = fftLen / 4u; k > 4u; k >>= 2u)
|
||||
{
|
||||
/* Initializations for the first stage */
|
||||
n1 = n2;
|
||||
n2 >>= 2u;
|
||||
ia1 = 0u;
|
||||
|
||||
/* Calculation of first stage */
|
||||
for (j = 0u; j <= (n2 - 1u); j++)
|
||||
{
|
||||
/* index calculation for the coefficients */
|
||||
ia2 = ia1 + ia1;
|
||||
ia3 = ia2 + ia1;
|
||||
co1 = pCoef[ia1 * 2u];
|
||||
si1 = pCoef[(ia1 * 2u) + 1u];
|
||||
co2 = pCoef[ia2 * 2u];
|
||||
si2 = pCoef[(ia2 * 2u) + 1u];
|
||||
co3 = pCoef[ia3 * 2u];
|
||||
si3 = pCoef[(ia3 * 2u) + 1u];
|
||||
/* Twiddle coefficients index modifier */
|
||||
ia1 = ia1 + twidCoefModifier;
|
||||
|
||||
for (i0 = j; i0 < fftLen; i0 += n1)
|
||||
{
|
||||
/* index calculation for the input as, */
|
||||
/* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2u], pSrc[i0 + 3fftLen/4] */
|
||||
i1 = i0 + n2;
|
||||
i2 = i1 + n2;
|
||||
i3 = i2 + n2;
|
||||
|
||||
/* Butterfly implementation */
|
||||
/* xa + xc */
|
||||
r1 = pSrc[2u * i0] + pSrc[2u * i2];
|
||||
/* xa - xc */
|
||||
r2 = pSrc[2u * i0] - pSrc[2u * i2];
|
||||
|
||||
/* ya + yc */
|
||||
s1 = pSrc[(2u * i0) + 1u] + pSrc[(2u * i2) + 1u];
|
||||
/* ya - yc */
|
||||
s2 = pSrc[(2u * i0) + 1u] - pSrc[(2u * i2) + 1u];
|
||||
|
||||
/* xb + xd */
|
||||
t1 = pSrc[2u * i1] + pSrc[2u * i3];
|
||||
|
||||
/* xa' = xa + xb + xc + xd */
|
||||
pSrc[2u * i0] = (r1 + t1) >> 2u;
|
||||
/* xa + xc -(xb + xd) */
|
||||
r1 = r1 - t1;
|
||||
|
||||
/* yb + yd */
|
||||
t2 = pSrc[(2u * i1) + 1u] + pSrc[(2u * i3) + 1u];
|
||||
/* ya' = ya + yb + yc + yd */
|
||||
pSrc[(2u * i0) + 1u] = (s1 + t2) >> 2u;
|
||||
|
||||
/* (ya + yc) - (yb + yd) */
|
||||
s1 = s1 - t2;
|
||||
|
||||
/* (yb - yd) */
|
||||
t1 = pSrc[(2u * i1) + 1u] - pSrc[(2u * i3) + 1u];
|
||||
/* (xb - xd) */
|
||||
t2 = pSrc[2u * i1] - pSrc[2u * i3];
|
||||
|
||||
/* xc' = (xa-xb+xc-xd)co2 + (ya-yb+yc-yd)(si2) */
|
||||
pSrc[2u * i1] = (((int32_t) (((q63_t) r1 * co2) >> 32)) +
|
||||
((int32_t) (((q63_t) s1 * si2) >> 32))) >> 1u;
|
||||
|
||||
/* yc' = (ya-yb+yc-yd)co2 - (xa-xb+xc-xd)(si2) */
|
||||
pSrc[(2u * i1) + 1u] = (((int32_t) (((q63_t) s1 * co2) >> 32)) -
|
||||
((int32_t) (((q63_t) r1 * si2) >> 32))) >> 1u;
|
||||
|
||||
/* (xa - xc) + (yb - yd) */
|
||||
r1 = r2 + t1;
|
||||
/* (xa - xc) - (yb - yd) */
|
||||
r2 = r2 - t1;
|
||||
|
||||
/* (ya - yc) - (xb - xd) */
|
||||
s1 = s2 - t2;
|
||||
/* (ya - yc) + (xb - xd) */
|
||||
s2 = s2 + t2;
|
||||
|
||||
/* xb' = (xa+yb-xc-yd)co1 + (ya-xb-yc+xd)(si1) */
|
||||
pSrc[2u * i2] = (((int32_t) (((q63_t) r1 * co1) >> 32)) +
|
||||
((int32_t) (((q63_t) s1 * si1) >> 32))) >> 1u;
|
||||
|
||||
/* yb' = (ya-xb-yc+xd)co1 - (xa+yb-xc-yd)(si1) */
|
||||
pSrc[(2u * i2) + 1u] = (((int32_t) (((q63_t) s1 * co1) >> 32)) -
|
||||
((int32_t) (((q63_t) r1 * si1) >> 32))) >> 1u;
|
||||
|
||||
/* xd' = (xa-yb-xc+yd)co3 + (ya+xb-yc-xd)(si3) */
|
||||
pSrc[2u * i3] = (((int32_t) (((q63_t) r2 * co3) >> 32)) +
|
||||
((int32_t) (((q63_t) s2 * si3) >> 32))) >> 1u;
|
||||
|
||||
/* yd' = (ya+xb-yc-xd)co3 - (xa-yb-xc+yd)(si3) */
|
||||
pSrc[(2u * i3) + 1u] = (((int32_t) (((q63_t) s2 * co3) >> 32)) -
|
||||
((int32_t) (((q63_t) r2 * si3) >> 32))) >> 1u;
|
||||
}
|
||||
}
|
||||
twidCoefModifier <<= 2u;
|
||||
}
|
||||
|
||||
/* End of Middle stages process */
|
||||
|
||||
/* data is in 11.21(q21) format for the 1024 point as there are 3 middle stages */
|
||||
/* data is in 9.23(q23) format for the 256 point as there are 2 middle stages */
|
||||
/* data is in 7.25(q25) format for the 64 point as there are 1 middle stage */
|
||||
/* data is in 5.27(q27) format for the 16 point as there are no middle stages */
|
||||
|
||||
|
||||
/* start of Last stage process */
|
||||
/* Initializations for the last stage */
|
||||
j = fftLen >> 2;
|
||||
ptr1 = &pSrc[0];
|
||||
|
||||
/* Calculations of last stage */
|
||||
do
|
||||
{
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
/* Read xa (real), ya(imag) input */
|
||||
xaya = *__SIMD64(ptr1)++;
|
||||
xa = (q31_t) xaya;
|
||||
ya = (q31_t) (xaya >> 32);
|
||||
|
||||
/* Read xb (real), yb(imag) input */
|
||||
xbyb = *__SIMD64(ptr1)++;
|
||||
xb = (q31_t) xbyb;
|
||||
yb = (q31_t) (xbyb >> 32);
|
||||
|
||||
/* Read xc (real), yc(imag) input */
|
||||
xcyc = *__SIMD64(ptr1)++;
|
||||
xc = (q31_t) xcyc;
|
||||
yc = (q31_t) (xcyc >> 32);
|
||||
|
||||
/* Read xc (real), yc(imag) input */
|
||||
xdyd = *__SIMD64(ptr1)++;
|
||||
xd = (q31_t) xdyd;
|
||||
yd = (q31_t) (xdyd >> 32);
|
||||
|
||||
#else
|
||||
|
||||
/* Read xa (real), ya(imag) input */
|
||||
xaya = *__SIMD64(ptr1)++;
|
||||
ya = (q31_t) xaya;
|
||||
xa = (q31_t) (xaya >> 32);
|
||||
|
||||
/* Read xb (real), yb(imag) input */
|
||||
xbyb = *__SIMD64(ptr1)++;
|
||||
yb = (q31_t) xbyb;
|
||||
xb = (q31_t) (xbyb >> 32);
|
||||
|
||||
/* Read xc (real), yc(imag) input */
|
||||
xcyc = *__SIMD64(ptr1)++;
|
||||
yc = (q31_t) xcyc;
|
||||
xc = (q31_t) (xcyc >> 32);
|
||||
|
||||
/* Read xc (real), yc(imag) input */
|
||||
xdyd = *__SIMD64(ptr1)++;
|
||||
yd = (q31_t) xdyd;
|
||||
xd = (q31_t) (xdyd >> 32);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* xa' = xa + xb + xc + xd */
|
||||
xa_out = xa + xb + xc + xd;
|
||||
|
||||
/* ya' = ya + yb + yc + yd */
|
||||
ya_out = ya + yb + yc + yd;
|
||||
|
||||
/* pointer updation for writing */
|
||||
ptr1 = ptr1 - 8u;
|
||||
|
||||
/* writing xa' and ya' */
|
||||
*ptr1++ = xa_out;
|
||||
*ptr1++ = ya_out;
|
||||
|
||||
xc_out = (xa - xb + xc - xd);
|
||||
yc_out = (ya - yb + yc - yd);
|
||||
|
||||
/* writing xc' and yc' */
|
||||
*ptr1++ = xc_out;
|
||||
*ptr1++ = yc_out;
|
||||
|
||||
xb_out = (xa + yb - xc - yd);
|
||||
yb_out = (ya - xb - yc + xd);
|
||||
|
||||
/* writing xb' and yb' */
|
||||
*ptr1++ = xb_out;
|
||||
*ptr1++ = yb_out;
|
||||
|
||||
xd_out = (xa - yb - xc + yd);
|
||||
yd_out = (ya + xb - yc - xd);
|
||||
|
||||
/* writing xd' and yd' */
|
||||
*ptr1++ = xd_out;
|
||||
*ptr1++ = yd_out;
|
||||
|
||||
|
||||
} while(--j);
|
||||
|
||||
/* output is in 11.21(q21) format for the 1024 point */
|
||||
/* output is in 9.23(q23) format for the 256 point */
|
||||
/* output is in 7.25(q25) format for the 64 point */
|
||||
/* output is in 5.27(q27) format for the 16 point */
|
||||
|
||||
/* End of last stage process */
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Core function for the Q31 CIFFT butterfly process.
|
||||
* @param[in, out] *pSrc points to the in-place buffer of Q31 data type.
|
||||
* @param[in] fftLen length of the FFT.
|
||||
* @param[in] *pCoef points to twiddle coefficient buffer.
|
||||
* @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Radix-4 IFFT algorithm used is :
|
||||
*
|
||||
* CIFFT uses same twiddle coefficients as CFFT Function
|
||||
* x[k] = x[n] + (j)k * x[n + fftLen/4] + (-1)k * x[n+fftLen/2] + (-j)k * x[n+3*fftLen/4]
|
||||
*
|
||||
*
|
||||
* IFFT is implemented with following changes in equations from FFT
|
||||
*
|
||||
* Input real and imaginary data:
|
||||
* x(n) = xa + j * ya
|
||||
* x(n+N/4 ) = xb + j * yb
|
||||
* x(n+N/2 ) = xc + j * yc
|
||||
* x(n+3N 4) = xd + j * yd
|
||||
*
|
||||
*
|
||||
* Output real and imaginary data:
|
||||
* x(4r) = xa'+ j * ya'
|
||||
* x(4r+1) = xb'+ j * yb'
|
||||
* x(4r+2) = xc'+ j * yc'
|
||||
* x(4r+3) = xd'+ j * yd'
|
||||
*
|
||||
*
|
||||
* Twiddle factors for radix-4 IFFT:
|
||||
* Wn = co1 + j * (si1)
|
||||
* W2n = co2 + j * (si2)
|
||||
* W3n = co3 + j * (si3)
|
||||
|
||||
* The real and imaginary output values for the radix-4 butterfly are
|
||||
* xa' = xa + xb + xc + xd
|
||||
* ya' = ya + yb + yc + yd
|
||||
* xb' = (xa-yb-xc+yd)* co1 - (ya+xb-yc-xd)* (si1)
|
||||
* yb' = (ya+xb-yc-xd)* co1 + (xa-yb-xc+yd)* (si1)
|
||||
* xc' = (xa-xb+xc-xd)* co2 - (ya-yb+yc-yd)* (si2)
|
||||
* yc' = (ya-yb+yc-yd)* co2 + (xa-xb+xc-xd)* (si2)
|
||||
* xd' = (xa+yb-xc-yd)* co3 - (ya-xb-yc+xd)* (si3)
|
||||
* yd' = (ya-xb-yc+xd)* co3 + (xa+yb-xc-yd)* (si3)
|
||||
*
|
||||
*/
|
||||
|
||||
void arm_radix4_butterfly_inverse_q31(
|
||||
q31_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
q31_t * pCoef,
|
||||
uint32_t twidCoefModifier)
|
||||
{
|
||||
uint32_t n1, n2, ia1, ia2, ia3, i0, i1, i2, i3, j, k;
|
||||
q31_t t1, t2, r1, r2, s1, s2, co1, co2, co3, si1, si2, si3;
|
||||
q31_t xa, xb, xc, xd;
|
||||
q31_t ya, yb, yc, yd;
|
||||
q31_t xa_out, xb_out, xc_out, xd_out;
|
||||
q31_t ya_out, yb_out, yc_out, yd_out;
|
||||
|
||||
q31_t *ptr1;
|
||||
q63_t xaya, xbyb, xcyc, xdyd;
|
||||
|
||||
/* input is be 1.31(q31) format for all FFT sizes */
|
||||
/* Total process is divided into three stages */
|
||||
/* process first stage, middle stages, & last stage */
|
||||
|
||||
/* Start of first stage process */
|
||||
|
||||
/* Initializations for the first stage */
|
||||
n2 = fftLen;
|
||||
n1 = n2;
|
||||
/* n2 = fftLen/4 */
|
||||
n2 >>= 2u;
|
||||
i0 = 0u;
|
||||
ia1 = 0u;
|
||||
|
||||
j = n2;
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
/* input is in 1.31(q31) format and provide 4 guard bits for the input */
|
||||
|
||||
/* index calculation for the input as, */
|
||||
/* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2u], pSrc[i0 + 3fftLen/4] */
|
||||
i1 = i0 + n2;
|
||||
i2 = i1 + n2;
|
||||
i3 = i2 + n2;
|
||||
|
||||
/* Butterfly implementation */
|
||||
/* xa + xc */
|
||||
r1 = (pSrc[2u * i0] >> 4u) + (pSrc[2u * i2] >> 4u);
|
||||
/* xa - xc */
|
||||
r2 = (pSrc[2u * i0] >> 4u) - (pSrc[2u * i2] >> 4u);
|
||||
|
||||
/* xb + xd */
|
||||
t1 = (pSrc[2u * i1] >> 4u) + (pSrc[2u * i3] >> 4u);
|
||||
|
||||
/* ya + yc */
|
||||
s1 = (pSrc[(2u * i0) + 1u] >> 4u) + (pSrc[(2u * i2) + 1u] >> 4u);
|
||||
/* ya - yc */
|
||||
s2 = (pSrc[(2u * i0) + 1u] >> 4u) - (pSrc[(2u * i2) + 1u] >> 4u);
|
||||
|
||||
/* xa' = xa + xb + xc + xd */
|
||||
pSrc[2u * i0] = (r1 + t1);
|
||||
/* (xa + xc) - (xb + xd) */
|
||||
r1 = r1 - t1;
|
||||
/* yb + yd */
|
||||
t2 = (pSrc[(2u * i1) + 1u] >> 4u) + (pSrc[(2u * i3) + 1u] >> 4u);
|
||||
/* ya' = ya + yb + yc + yd */
|
||||
pSrc[(2u * i0) + 1u] = (s1 + t2);
|
||||
|
||||
/* (ya + yc) - (yb + yd) */
|
||||
s1 = s1 - t2;
|
||||
|
||||
/* yb - yd */
|
||||
t1 = (pSrc[(2u * i1) + 1u] >> 4u) - (pSrc[(2u * i3) + 1u] >> 4u);
|
||||
/* xb - xd */
|
||||
t2 = (pSrc[2u * i1] >> 4u) - (pSrc[2u * i3] >> 4u);
|
||||
|
||||
/* index calculation for the coefficients */
|
||||
ia2 = 2u * ia1;
|
||||
co2 = pCoef[ia2 * 2u];
|
||||
si2 = pCoef[(ia2 * 2u) + 1u];
|
||||
|
||||
/* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */
|
||||
pSrc[2u * i1] = (((int32_t) (((q63_t) r1 * co2) >> 32)) -
|
||||
((int32_t) (((q63_t) s1 * si2) >> 32))) << 1u;
|
||||
|
||||
/* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */
|
||||
pSrc[2u * i1 + 1u] = (((int32_t) (((q63_t) s1 * co2) >> 32)) +
|
||||
((int32_t) (((q63_t) r1 * si2) >> 32))) << 1u;
|
||||
|
||||
/* (xa - xc) - (yb - yd) */
|
||||
r1 = r2 - t1;
|
||||
/* (xa - xc) + (yb - yd) */
|
||||
r2 = r2 + t1;
|
||||
|
||||
/* (ya - yc) + (xb - xd) */
|
||||
s1 = s2 + t2;
|
||||
/* (ya - yc) - (xb - xd) */
|
||||
s2 = s2 - t2;
|
||||
|
||||
co1 = pCoef[ia1 * 2u];
|
||||
si1 = pCoef[(ia1 * 2u) + 1u];
|
||||
|
||||
/* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */
|
||||
pSrc[2u * i2] = (((int32_t) (((q63_t) r1 * co1) >> 32)) -
|
||||
((int32_t) (((q63_t) s1 * si1) >> 32))) << 1u;
|
||||
|
||||
/* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */
|
||||
pSrc[(2u * i2) + 1u] = (((int32_t) (((q63_t) s1 * co1) >> 32)) +
|
||||
((int32_t) (((q63_t) r1 * si1) >> 32))) << 1u;
|
||||
|
||||
/* index calculation for the coefficients */
|
||||
ia3 = 3u * ia1;
|
||||
co3 = pCoef[ia3 * 2u];
|
||||
si3 = pCoef[(ia3 * 2u) + 1u];
|
||||
|
||||
/* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */
|
||||
pSrc[2u * i3] = (((int32_t) (((q63_t) r2 * co3) >> 32)) -
|
||||
((int32_t) (((q63_t) s2 * si3) >> 32))) << 1u;
|
||||
|
||||
/* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */
|
||||
pSrc[(2u * i3) + 1u] = (((int32_t) (((q63_t) s2 * co3) >> 32)) +
|
||||
((int32_t) (((q63_t) r2 * si3) >> 32))) << 1u;
|
||||
|
||||
/* Twiddle coefficients index modifier */
|
||||
ia1 = ia1 + twidCoefModifier;
|
||||
|
||||
/* Updating input index */
|
||||
i0 = i0 + 1u;
|
||||
|
||||
} while(--j);
|
||||
|
||||
/* data is in 5.27(q27) format */
|
||||
/* each stage provides two down scaling of the input */
|
||||
|
||||
|
||||
/* Start of Middle stages process */
|
||||
|
||||
twidCoefModifier <<= 2u;
|
||||
|
||||
/* Calculation of second stage to excluding last stage */
|
||||
for (k = fftLen / 4u; k > 4u; k >>= 2u)
|
||||
{
|
||||
/* Initializations for the first stage */
|
||||
n1 = n2;
|
||||
n2 >>= 2u;
|
||||
ia1 = 0u;
|
||||
|
||||
for (j = 0; j <= (n2 - 1u); j++)
|
||||
{
|
||||
/* index calculation for the coefficients */
|
||||
ia2 = ia1 + ia1;
|
||||
ia3 = ia2 + ia1;
|
||||
co1 = pCoef[ia1 * 2u];
|
||||
si1 = pCoef[(ia1 * 2u) + 1u];
|
||||
co2 = pCoef[ia2 * 2u];
|
||||
si2 = pCoef[(ia2 * 2u) + 1u];
|
||||
co3 = pCoef[ia3 * 2u];
|
||||
si3 = pCoef[(ia3 * 2u) + 1u];
|
||||
/* Twiddle coefficients index modifier */
|
||||
ia1 = ia1 + twidCoefModifier;
|
||||
|
||||
for (i0 = j; i0 < fftLen; i0 += n1)
|
||||
{
|
||||
/* index calculation for the input as, */
|
||||
/* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2u], pSrc[i0 + 3fftLen/4] */
|
||||
i1 = i0 + n2;
|
||||
i2 = i1 + n2;
|
||||
i3 = i2 + n2;
|
||||
|
||||
/* Butterfly implementation */
|
||||
/* xa + xc */
|
||||
r1 = pSrc[2u * i0] + pSrc[2u * i2];
|
||||
/* xa - xc */
|
||||
r2 = pSrc[2u * i0] - pSrc[2u * i2];
|
||||
|
||||
/* ya + yc */
|
||||
s1 = pSrc[(2u * i0) + 1u] + pSrc[(2u * i2) + 1u];
|
||||
/* ya - yc */
|
||||
s2 = pSrc[(2u * i0) + 1u] - pSrc[(2u * i2) + 1u];
|
||||
|
||||
/* xb + xd */
|
||||
t1 = pSrc[2u * i1] + pSrc[2u * i3];
|
||||
|
||||
/* xa' = xa + xb + xc + xd */
|
||||
pSrc[2u * i0] = (r1 + t1) >> 2u;
|
||||
/* xa + xc -(xb + xd) */
|
||||
r1 = r1 - t1;
|
||||
/* yb + yd */
|
||||
t2 = pSrc[(2u * i1) + 1u] + pSrc[(2u * i3) + 1u];
|
||||
/* ya' = ya + yb + yc + yd */
|
||||
pSrc[(2u * i0) + 1u] = (s1 + t2) >> 2u;
|
||||
|
||||
/* (ya + yc) - (yb + yd) */
|
||||
s1 = s1 - t2;
|
||||
|
||||
/* (yb - yd) */
|
||||
t1 = pSrc[(2u * i1) + 1u] - pSrc[(2u * i3) + 1u];
|
||||
/* (xb - xd) */
|
||||
t2 = pSrc[2u * i1] - pSrc[2u * i3];
|
||||
|
||||
/* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */
|
||||
pSrc[2u * i1] = (((int32_t) (((q63_t) r1 * co2) >> 32u)) -
|
||||
((int32_t) (((q63_t) s1 * si2) >> 32u))) >> 1u;
|
||||
|
||||
/* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */
|
||||
pSrc[(2u * i1) + 1u] =
|
||||
(((int32_t) (((q63_t) s1 * co2) >> 32u)) +
|
||||
((int32_t) (((q63_t) r1 * si2) >> 32u))) >> 1u;
|
||||
|
||||
/* (xa - xc) - (yb - yd) */
|
||||
r1 = r2 - t1;
|
||||
/* (xa - xc) + (yb - yd) */
|
||||
r2 = r2 + t1;
|
||||
|
||||
/* (ya - yc) + (xb - xd) */
|
||||
s1 = s2 + t2;
|
||||
/* (ya - yc) - (xb - xd) */
|
||||
s2 = s2 - t2;
|
||||
|
||||
/* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */
|
||||
pSrc[2u * i2] = (((int32_t) (((q63_t) r1 * co1) >> 32)) -
|
||||
((int32_t) (((q63_t) s1 * si1) >> 32))) >> 1u;
|
||||
|
||||
/* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */
|
||||
pSrc[(2u * i2) + 1u] = (((int32_t) (((q63_t) s1 * co1) >> 32)) +
|
||||
((int32_t) (((q63_t) r1 * si1) >> 32))) >> 1u;
|
||||
|
||||
/* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */
|
||||
pSrc[(2u * i3)] = (((int32_t) (((q63_t) r2 * co3) >> 32)) -
|
||||
((int32_t) (((q63_t) s2 * si3) >> 32))) >> 1u;
|
||||
|
||||
/* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */
|
||||
pSrc[(2u * i3) + 1u] = (((int32_t) (((q63_t) s2 * co3) >> 32)) +
|
||||
((int32_t) (((q63_t) r2 * si3) >> 32))) >> 1u;
|
||||
}
|
||||
}
|
||||
twidCoefModifier <<= 2u;
|
||||
}
|
||||
|
||||
/* End of Middle stages process */
|
||||
|
||||
/* data is in 11.21(q21) format for the 1024 point as there are 3 middle stages */
|
||||
/* data is in 9.23(q23) format for the 256 point as there are 2 middle stages */
|
||||
/* data is in 7.25(q25) format for the 64 point as there are 1 middle stage */
|
||||
/* data is in 5.27(q27) format for the 16 point as there are no middle stages */
|
||||
|
||||
|
||||
/* Start of last stage process */
|
||||
|
||||
|
||||
/* Initializations for the last stage */
|
||||
j = fftLen >> 2;
|
||||
ptr1 = &pSrc[0];
|
||||
|
||||
/* Calculations of last stage */
|
||||
do
|
||||
{
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
/* Read xa (real), ya(imag) input */
|
||||
xaya = *__SIMD64(ptr1)++;
|
||||
xa = (q31_t) xaya;
|
||||
ya = (q31_t) (xaya >> 32);
|
||||
|
||||
/* Read xb (real), yb(imag) input */
|
||||
xbyb = *__SIMD64(ptr1)++;
|
||||
xb = (q31_t) xbyb;
|
||||
yb = (q31_t) (xbyb >> 32);
|
||||
|
||||
/* Read xc (real), yc(imag) input */
|
||||
xcyc = *__SIMD64(ptr1)++;
|
||||
xc = (q31_t) xcyc;
|
||||
yc = (q31_t) (xcyc >> 32);
|
||||
|
||||
/* Read xc (real), yc(imag) input */
|
||||
xdyd = *__SIMD64(ptr1)++;
|
||||
xd = (q31_t) xdyd;
|
||||
yd = (q31_t) (xdyd >> 32);
|
||||
|
||||
#else
|
||||
|
||||
/* Read xa (real), ya(imag) input */
|
||||
xaya = *__SIMD64(ptr1)++;
|
||||
ya = (q31_t) xaya;
|
||||
xa = (q31_t) (xaya >> 32);
|
||||
|
||||
/* Read xb (real), yb(imag) input */
|
||||
xbyb = *__SIMD64(ptr1)++;
|
||||
yb = (q31_t) xbyb;
|
||||
xb = (q31_t) (xbyb >> 32);
|
||||
|
||||
/* Read xc (real), yc(imag) input */
|
||||
xcyc = *__SIMD64(ptr1)++;
|
||||
yc = (q31_t) xcyc;
|
||||
xc = (q31_t) (xcyc >> 32);
|
||||
|
||||
/* Read xc (real), yc(imag) input */
|
||||
xdyd = *__SIMD64(ptr1)++;
|
||||
yd = (q31_t) xdyd;
|
||||
xd = (q31_t) (xdyd >> 32);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* xa' = xa + xb + xc + xd */
|
||||
xa_out = xa + xb + xc + xd;
|
||||
|
||||
/* ya' = ya + yb + yc + yd */
|
||||
ya_out = ya + yb + yc + yd;
|
||||
|
||||
/* pointer updation for writing */
|
||||
ptr1 = ptr1 - 8u;
|
||||
|
||||
/* writing xa' and ya' */
|
||||
*ptr1++ = xa_out;
|
||||
*ptr1++ = ya_out;
|
||||
|
||||
xc_out = (xa - xb + xc - xd);
|
||||
yc_out = (ya - yb + yc - yd);
|
||||
|
||||
/* writing xc' and yc' */
|
||||
*ptr1++ = xc_out;
|
||||
*ptr1++ = yc_out;
|
||||
|
||||
xb_out = (xa - yb - xc + yd);
|
||||
yb_out = (ya + xb - yc - xd);
|
||||
|
||||
/* writing xb' and yb' */
|
||||
*ptr1++ = xb_out;
|
||||
*ptr1++ = yb_out;
|
||||
|
||||
xd_out = (xa + yb - xc - yd);
|
||||
yd_out = (ya - xb - yc + xd);
|
||||
|
||||
/* writing xd' and yd' */
|
||||
*ptr1++ = xd_out;
|
||||
*ptr1++ = yd_out;
|
||||
|
||||
|
||||
} while(--j);
|
||||
|
||||
/* output is in 11.21(q21) format for the 1024 point */
|
||||
/* output is in 9.23(q23) format for the 256 point */
|
||||
/* output is in 7.25(q25) format for the 64 point */
|
||||
/* output is in 5.27(q27) format for the 16 point */
|
||||
|
||||
/* End of last stage process */
|
||||
}
|
||||
@@ -0,0 +1,453 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_dct4_f32.c
|
||||
*
|
||||
* Description: Processing function of DCT4 & IDCT4 F32.
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 1.0.10 2011/7/15
|
||||
* Big Endian support added and Merged M0 and M3/M4 Source code.
|
||||
*
|
||||
* Version 1.0.3 2010/11/29
|
||||
* Re-organized the CMSIS folders and updated documentation.
|
||||
*
|
||||
* Version 1.0.2 2010/11/11
|
||||
* Documentation updated.
|
||||
*
|
||||
* Version 1.0.1 2010/10/05
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 1.0.0 2010/09/20
|
||||
* Production release and review comments incorporated.
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupTransforms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup DCT4_IDCT4 DCT Type IV Functions
|
||||
* Representation of signals by minimum number of values is important for storage and transmission.
|
||||
* The possibility of large discontinuity between the beginning and end of a period of a signal
|
||||
* in DFT can be avoided by extending the signal so that it is even-symmetric.
|
||||
* Discrete Cosine Transform (DCT) is constructed such that its energy is heavily concentrated in the lower part of the
|
||||
* spectrum and is very widely used in signal and image coding applications.
|
||||
* The family of DCTs (DCT type- 1,2,3,4) is the outcome of different combinations of homogeneous boundary conditions.
|
||||
* DCT has an excellent energy-packing capability, hence has many applications and in data compression in particular.
|
||||
*
|
||||
* DCT is essentially the Discrete Fourier Transform(DFT) of an even-extended real signal.
|
||||
* Reordering of the input data makes the computation of DCT just a problem of
|
||||
* computing the DFT of a real signal with a few additional operations.
|
||||
* This approach provides regular, simple, and very efficient DCT algorithms for practical hardware and software implementations.
|
||||
*
|
||||
* DCT type-II can be implemented using Fast fourier transform (FFT) internally, as the transform is applied on real values, Real FFT can be used.
|
||||
* DCT4 is implemented using DCT2 as their implementations are similar except with some added pre-processing and post-processing.
|
||||
* DCT2 implementation can be described in the following steps:
|
||||
* - Re-ordering input
|
||||
* - Calculating Real FFT
|
||||
* - Multiplication of weights and Real FFT output and getting real part from the product.
|
||||
*
|
||||
* This process is explained by the block diagram below:
|
||||
* \image html DCT4.gif "Discrete Cosine Transform - type-IV"
|
||||
*
|
||||
* \par Algorithm:
|
||||
* The N-point type-IV DCT is defined as a real, linear transformation by the formula:
|
||||
* \image html DCT4Equation.gif
|
||||
* where <code>k = 0,1,2,.....N-1</code>
|
||||
*\par
|
||||
* Its inverse is defined as follows:
|
||||
* \image html IDCT4Equation.gif
|
||||
* where <code>n = 0,1,2,.....N-1</code>
|
||||
*\par
|
||||
* The DCT4 matrices become involutory (i.e. they are self-inverse) by multiplying with an overall scale factor of sqrt(2/N).
|
||||
* The symmetry of the transform matrix indicates that the fast algorithms for the forward
|
||||
* and inverse transform computation are identical.
|
||||
* Note that the implementation of Inverse DCT4 and DCT4 is same, hence same process function can be used for both.
|
||||
*
|
||||
* \par Lengths supported by the transform:
|
||||
* As DCT4 internally uses Real FFT, it supports all the lengths supported by arm_rfft_f32().
|
||||
* The library provides separate functions for Q15, Q31, and floating-point data types.
|
||||
* \par Instance Structure
|
||||
* The instances for Real FFT and FFT, cosine values table and twiddle factor table are stored in an instance data structure.
|
||||
* A separate instance structure must be defined for each transform.
|
||||
* There are separate instance structure declarations for each of the 3 supported data types.
|
||||
*
|
||||
* \par Initialization Functions
|
||||
* There is also an associated initialization function for each data type.
|
||||
* The initialization function performs the following operations:
|
||||
* - Sets the values of the internal structure fields.
|
||||
* - Initializes Real FFT as its process function is used internally in DCT4, by calling arm_rfft_init_f32().
|
||||
* \par
|
||||
* Use of the initialization function is optional.
|
||||
* However, if the initialization function is used, then the instance structure cannot be placed into a const data section.
|
||||
* To place an instance structure into a const data section, the instance structure must be manually initialized.
|
||||
* Manually initialize the instance structure as follows:
|
||||
* <pre>
|
||||
*arm_dct4_instance_f32 S = {N, Nby2, normalize, pTwiddle, pCosFactor, pRfft, pCfft};
|
||||
*arm_dct4_instance_q31 S = {N, Nby2, normalize, pTwiddle, pCosFactor, pRfft, pCfft};
|
||||
*arm_dct4_instance_q15 S = {N, Nby2, normalize, pTwiddle, pCosFactor, pRfft, pCfft};
|
||||
* </pre>
|
||||
* where \c N is the length of the DCT4; \c Nby2 is half of the length of the DCT4;
|
||||
* \c normalize is normalizing factor used and is equal to <code>sqrt(2/N)</code>;
|
||||
* \c pTwiddle points to the twiddle factor table;
|
||||
* \c pCosFactor points to the cosFactor table;
|
||||
* \c pRfft points to the real FFT instance;
|
||||
* \c pCfft points to the complex FFT instance;
|
||||
* The CFFT and RFFT structures also needs to be initialized, refer to arm_cfft_radix4_f32()
|
||||
* and arm_rfft_f32() respectively for details regarding static initialization.
|
||||
*
|
||||
* \par Fixed-Point Behavior
|
||||
* Care must be taken when using the fixed-point versions of the DCT4 transform functions.
|
||||
* In particular, the overflow and saturation behavior of the accumulator used in each function must be considered.
|
||||
* Refer to the function specific documentation below for usage guidelines.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup DCT4_IDCT4
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Processing function for the floating-point DCT4/IDCT4.
|
||||
* @param[in] *S points to an instance of the floating-point DCT4/IDCT4 structure.
|
||||
* @param[in] *pState points to state buffer.
|
||||
* @param[in,out] *pInlineBuffer points to the in-place input and output buffer.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_dct4_f32(
|
||||
const arm_dct4_instance_f32 * S,
|
||||
float32_t * pState,
|
||||
float32_t * pInlineBuffer)
|
||||
{
|
||||
uint32_t i; /* Loop counter */
|
||||
float32_t *weights = S->pTwiddle; /* Pointer to the Weights table */
|
||||
float32_t *cosFact = S->pCosFactor; /* Pointer to the cos factors table */
|
||||
float32_t *pS1, *pS2, *pbuff; /* Temporary pointers for input buffer and pState buffer */
|
||||
float32_t in; /* Temporary variable */
|
||||
|
||||
|
||||
/* DCT4 computation involves DCT2 (which is calculated using RFFT)
|
||||
* along with some pre-processing and post-processing.
|
||||
* Computational procedure is explained as follows:
|
||||
* (a) Pre-processing involves multiplying input with cos factor,
|
||||
* r(n) = 2 * u(n) * cos(pi*(2*n+1)/(4*n))
|
||||
* where,
|
||||
* r(n) -- output of preprocessing
|
||||
* u(n) -- input to preprocessing(actual Source buffer)
|
||||
* (b) Calculation of DCT2 using FFT is divided into three steps:
|
||||
* Step1: Re-ordering of even and odd elements of input.
|
||||
* Step2: Calculating FFT of the re-ordered input.
|
||||
* Step3: Taking the real part of the product of FFT output and weights.
|
||||
* (c) Post-processing - DCT4 can be obtained from DCT2 output using the following equation:
|
||||
* Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
|
||||
* where,
|
||||
* Y4 -- DCT4 output, Y2 -- DCT2 output
|
||||
* (d) Multiplying the output with the normalizing factor sqrt(2/N).
|
||||
*/
|
||||
|
||||
/*-------- Pre-processing ------------*/
|
||||
/* Multiplying input with cos factor i.e. r(n) = 2 * x(n) * cos(pi*(2*n+1)/(4*n)) */
|
||||
arm_scale_f32(pInlineBuffer, 2.0f, pInlineBuffer, S->N);
|
||||
arm_mult_f32(pInlineBuffer, cosFact, pInlineBuffer, S->N);
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Step1: Re-ordering of even and odd elements as,
|
||||
* pState[i] = pInlineBuffer[2*i] and
|
||||
* pState[N-i-1] = pInlineBuffer[2*i+1] where i = 0 to N/2
|
||||
---------------------------------------------------------------------*/
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* pS2 initialized to pState+N-1, so that it points to the end of the state buffer */
|
||||
pS2 = pState + (S->N - 1u);
|
||||
|
||||
/* pbuff initialized to input buffer */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
#ifndef ARM_MATH_CM0
|
||||
|
||||
/* Run the below code for Cortex-M4 and Cortex-M3 */
|
||||
|
||||
/* Initializing the loop counter to N/2 >> 2 for loop unrolling by 4 */
|
||||
i = (uint32_t) S->Nby2 >> 2u;
|
||||
|
||||
/* First part of the processing with loop unrolling. Compute 4 outputs at a time.
|
||||
** a second loop below computes the remaining 1 to 3 samples. */
|
||||
do
|
||||
{
|
||||
/* Re-ordering of even and odd elements */
|
||||
/* pState[i] = pInlineBuffer[2*i] */
|
||||
*pS1++ = *pbuff++;
|
||||
/* pState[N-i-1] = pInlineBuffer[2*i+1] */
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
*pS1++ = *pbuff++;
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
*pS1++ = *pbuff++;
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
*pS1++ = *pbuff++;
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
/* pbuff initialized to input buffer */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* Initializing the loop counter to N/4 instead of N for loop unrolling */
|
||||
i = (uint32_t) S->N >> 2u;
|
||||
|
||||
/* Processing with loop unrolling 4 times as N is always multiple of 4.
|
||||
* Compute 4 outputs at a time */
|
||||
do
|
||||
{
|
||||
/* Writing the re-ordered output back to inplace input buffer */
|
||||
*pbuff++ = *pS1++;
|
||||
*pbuff++ = *pS1++;
|
||||
*pbuff++ = *pS1++;
|
||||
*pbuff++ = *pS1++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
* Step2: Calculate RFFT for N-point input
|
||||
* ---------------------------------------------------------- */
|
||||
/* pInlineBuffer is real input of length N , pState is the complex output of length 2N */
|
||||
arm_rfft_f32(S->pRfft, pInlineBuffer, pState);
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Step3: Multiply the FFT output with the weights.
|
||||
*----------------------------------------------------------------------*/
|
||||
arm_cmplx_mult_cmplx_f32(pState, weights, pState, S->N);
|
||||
|
||||
/* ----------- Post-processing ---------- */
|
||||
/* DCT-IV can be obtained from DCT-II by the equation,
|
||||
* Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
|
||||
* Hence, Y4(0) = Y2(0)/2 */
|
||||
/* Getting only real part from the output and Converting to DCT-IV */
|
||||
|
||||
/* Initializing the loop counter to N >> 2 for loop unrolling by 4 */
|
||||
i = ((uint32_t) S->N - 1u) >> 2u;
|
||||
|
||||
/* pbuff initialized to input buffer. */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* Calculating Y4(0) from Y2(0) using Y4(0) = Y2(0)/2 */
|
||||
in = *pS1++ * (float32_t) 0.5;
|
||||
/* input buffer acts as inplace, so output values are stored in the input itself. */
|
||||
*pbuff++ = in;
|
||||
|
||||
/* pState pointer is incremented twice as the real values are located alternatively in the array */
|
||||
pS1++;
|
||||
|
||||
/* First part of the processing with loop unrolling. Compute 4 outputs at a time.
|
||||
** a second loop below computes the remaining 1 to 3 samples. */
|
||||
do
|
||||
{
|
||||
/* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
|
||||
/* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
/* points to the next real value */
|
||||
pS1++;
|
||||
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
pS1++;
|
||||
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
pS1++;
|
||||
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
pS1++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
/* If the blockSize is not a multiple of 4, compute any remaining output samples here.
|
||||
** No loop unrolling is used. */
|
||||
i = ((uint32_t) S->N - 1u) % 0x4u;
|
||||
|
||||
while(i > 0u)
|
||||
{
|
||||
/* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
|
||||
/* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
/* points to the next real value */
|
||||
pS1++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
}
|
||||
|
||||
|
||||
/*------------ Normalizing the output by multiplying with the normalizing factor ----------*/
|
||||
|
||||
/* Initializing the loop counter to N/4 instead of N for loop unrolling */
|
||||
i = (uint32_t) S->N >> 2u;
|
||||
|
||||
/* pbuff initialized to the pInlineBuffer(now contains the output values) */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* Processing with loop unrolling 4 times as N is always multiple of 4. Compute 4 outputs at a time */
|
||||
do
|
||||
{
|
||||
/* Multiplying pInlineBuffer with the normalizing factor sqrt(2/N) */
|
||||
in = *pbuff;
|
||||
*pbuff++ = in * S->normalize;
|
||||
|
||||
in = *pbuff;
|
||||
*pbuff++ = in * S->normalize;
|
||||
|
||||
in = *pbuff;
|
||||
*pbuff++ = in * S->normalize;
|
||||
|
||||
in = *pbuff;
|
||||
*pbuff++ = in * S->normalize;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* Run the below code for Cortex-M0 */
|
||||
|
||||
/* Initializing the loop counter to N/2 */
|
||||
i = (uint32_t) S->Nby2;
|
||||
|
||||
do
|
||||
{
|
||||
/* Re-ordering of even and odd elements */
|
||||
/* pState[i] = pInlineBuffer[2*i] */
|
||||
*pS1++ = *pbuff++;
|
||||
/* pState[N-i-1] = pInlineBuffer[2*i+1] */
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
/* pbuff initialized to input buffer */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* Initializing the loop counter */
|
||||
i = (uint32_t) S->N;
|
||||
|
||||
do
|
||||
{
|
||||
/* Writing the re-ordered output back to inplace input buffer */
|
||||
*pbuff++ = *pS1++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
* Step2: Calculate RFFT for N-point input
|
||||
* ---------------------------------------------------------- */
|
||||
/* pInlineBuffer is real input of length N , pState is the complex output of length 2N */
|
||||
arm_rfft_f32(S->pRfft, pInlineBuffer, pState);
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Step3: Multiply the FFT output with the weights.
|
||||
*----------------------------------------------------------------------*/
|
||||
arm_cmplx_mult_cmplx_f32(pState, weights, pState, S->N);
|
||||
|
||||
/* ----------- Post-processing ---------- */
|
||||
/* DCT-IV can be obtained from DCT-II by the equation,
|
||||
* Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
|
||||
* Hence, Y4(0) = Y2(0)/2 */
|
||||
/* Getting only real part from the output and Converting to DCT-IV */
|
||||
|
||||
/* pbuff initialized to input buffer. */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* Calculating Y4(0) from Y2(0) using Y4(0) = Y2(0)/2 */
|
||||
in = *pS1++ * (float32_t) 0.5;
|
||||
/* input buffer acts as inplace, so output values are stored in the input itself. */
|
||||
*pbuff++ = in;
|
||||
|
||||
/* pState pointer is incremented twice as the real values are located alternatively in the array */
|
||||
pS1++;
|
||||
|
||||
/* Initializing the loop counter */
|
||||
i = ((uint32_t) S->N - 1u);
|
||||
|
||||
do
|
||||
{
|
||||
/* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
|
||||
/* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
/* points to the next real value */
|
||||
pS1++;
|
||||
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
|
||||
/*------------ Normalizing the output by multiplying with the normalizing factor ----------*/
|
||||
|
||||
/* Initializing the loop counter */
|
||||
i = (uint32_t) S->N;
|
||||
|
||||
/* pbuff initialized to the pInlineBuffer(now contains the output values) */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
do
|
||||
{
|
||||
/* Multiplying pInlineBuffer with the normalizing factor sqrt(2/N) */
|
||||
in = *pbuff;
|
||||
*pbuff++ = in * S->normalize;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
#endif /* #ifndef ARM_MATH_CM0 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of DCT4_IDCT4 group
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,386 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_dct4_q15.c
|
||||
*
|
||||
* Description: Processing function of DCT4 & IDCT4 Q15.
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 1.0.10 2011/7/15
|
||||
* Big Endian support added and Merged M0 and M3/M4 Source code.
|
||||
*
|
||||
* Version 1.0.3 2010/11/29
|
||||
* Re-organized the CMSIS folders and updated documentation.
|
||||
*
|
||||
* Version 1.0.2 2010/11/11
|
||||
* Documentation updated.
|
||||
*
|
||||
* Version 1.0.1 2010/10/05
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 1.0.0 2010/09/20
|
||||
* Production release and review comments incorporated.
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
|
||||
/**
|
||||
* @addtogroup DCT4_IDCT4
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Processing function for the Q15 DCT4/IDCT4.
|
||||
* @param[in] *S points to an instance of the Q15 DCT4 structure.
|
||||
* @param[in] *pState points to state buffer.
|
||||
* @param[in,out] *pInlineBuffer points to the in-place input and output buffer.
|
||||
* @return none.
|
||||
*
|
||||
* \par Input an output formats:
|
||||
* Internally inputs are downscaled in the RFFT process function to avoid overflows.
|
||||
* Number of bits downscaled, depends on the size of the transform.
|
||||
* The input and output formats for different DCT sizes and number of bits to upscale are mentioned in the table below:
|
||||
*
|
||||
* \image html dct4FormatsQ15Table.gif
|
||||
*/
|
||||
|
||||
void arm_dct4_q15(
|
||||
const arm_dct4_instance_q15 * S,
|
||||
q15_t * pState,
|
||||
q15_t * pInlineBuffer)
|
||||
{
|
||||
uint32_t i; /* Loop counter */
|
||||
q15_t *weights = S->pTwiddle; /* Pointer to the Weights table */
|
||||
q15_t *cosFact = S->pCosFactor; /* Pointer to the cos factors table */
|
||||
q15_t *pS1, *pS2, *pbuff; /* Temporary pointers for input buffer and pState buffer */
|
||||
q15_t in; /* Temporary variable */
|
||||
|
||||
|
||||
/* DCT4 computation involves DCT2 (which is calculated using RFFT)
|
||||
* along with some pre-processing and post-processing.
|
||||
* Computational procedure is explained as follows:
|
||||
* (a) Pre-processing involves multiplying input with cos factor,
|
||||
* r(n) = 2 * u(n) * cos(pi*(2*n+1)/(4*n))
|
||||
* where,
|
||||
* r(n) -- output of preprocessing
|
||||
* u(n) -- input to preprocessing(actual Source buffer)
|
||||
* (b) Calculation of DCT2 using FFT is divided into three steps:
|
||||
* Step1: Re-ordering of even and odd elements of input.
|
||||
* Step2: Calculating FFT of the re-ordered input.
|
||||
* Step3: Taking the real part of the product of FFT output and weights.
|
||||
* (c) Post-processing - DCT4 can be obtained from DCT2 output using the following equation:
|
||||
* Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
|
||||
* where,
|
||||
* Y4 -- DCT4 output, Y2 -- DCT2 output
|
||||
* (d) Multiplying the output with the normalizing factor sqrt(2/N).
|
||||
*/
|
||||
|
||||
/*-------- Pre-processing ------------*/
|
||||
/* Multiplying input with cos factor i.e. r(n) = 2 * x(n) * cos(pi*(2*n+1)/(4*n)) */
|
||||
arm_mult_q15(pInlineBuffer, cosFact, pInlineBuffer, S->N);
|
||||
arm_shift_q15(pInlineBuffer, 1, pInlineBuffer, S->N);
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Step1: Re-ordering of even and odd elements as
|
||||
* pState[i] = pInlineBuffer[2*i] and
|
||||
* pState[N-i-1] = pInlineBuffer[2*i+1] where i = 0 to N/2
|
||||
---------------------------------------------------------------------*/
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* pS2 initialized to pState+N-1, so that it points to the end of the state buffer */
|
||||
pS2 = pState + (S->N - 1u);
|
||||
|
||||
/* pbuff initialized to input buffer */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
|
||||
#ifndef ARM_MATH_CM0
|
||||
|
||||
/* Run the below code for Cortex-M4 and Cortex-M3 */
|
||||
|
||||
/* Initializing the loop counter to N/2 >> 2 for loop unrolling by 4 */
|
||||
i = (uint32_t) S->Nby2 >> 2u;
|
||||
|
||||
/* First part of the processing with loop unrolling. Compute 4 outputs at a time.
|
||||
** a second loop below computes the remaining 1 to 3 samples. */
|
||||
do
|
||||
{
|
||||
/* Re-ordering of even and odd elements */
|
||||
/* pState[i] = pInlineBuffer[2*i] */
|
||||
*pS1++ = *pbuff++;
|
||||
/* pState[N-i-1] = pInlineBuffer[2*i+1] */
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
*pS1++ = *pbuff++;
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
*pS1++ = *pbuff++;
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
*pS1++ = *pbuff++;
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
/* pbuff initialized to input buffer */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* Initializing the loop counter to N/4 instead of N for loop unrolling */
|
||||
i = (uint32_t) S->N >> 2u;
|
||||
|
||||
/* Processing with loop unrolling 4 times as N is always multiple of 4.
|
||||
* Compute 4 outputs at a time */
|
||||
do
|
||||
{
|
||||
/* Writing the re-ordered output back to inplace input buffer */
|
||||
*pbuff++ = *pS1++;
|
||||
*pbuff++ = *pS1++;
|
||||
*pbuff++ = *pS1++;
|
||||
*pbuff++ = *pS1++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
* Step2: Calculate RFFT for N-point input
|
||||
* ---------------------------------------------------------- */
|
||||
/* pInlineBuffer is real input of length N , pState is the complex output of length 2N */
|
||||
arm_rfft_q15(S->pRfft, pInlineBuffer, pState);
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Step3: Multiply the FFT output with the weights.
|
||||
*----------------------------------------------------------------------*/
|
||||
arm_cmplx_mult_cmplx_q15(pState, weights, pState, S->N);
|
||||
|
||||
/* The output of complex multiplication is in 3.13 format.
|
||||
* Hence changing the format of N (i.e. 2*N elements) complex numbers to 1.15 format by shifting left by 2 bits. */
|
||||
arm_shift_q15(pState, 2, pState, S->N * 2);
|
||||
|
||||
/* ----------- Post-processing ---------- */
|
||||
/* DCT-IV can be obtained from DCT-II by the equation,
|
||||
* Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
|
||||
* Hence, Y4(0) = Y2(0)/2 */
|
||||
/* Getting only real part from the output and Converting to DCT-IV */
|
||||
|
||||
/* Initializing the loop counter to N >> 2 for loop unrolling by 4 */
|
||||
i = ((uint32_t) S->N - 1u) >> 2u;
|
||||
|
||||
/* pbuff initialized to input buffer. */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* Calculating Y4(0) from Y2(0) using Y4(0) = Y2(0)/2 */
|
||||
in = *pS1++ >> 1u;
|
||||
/* input buffer acts as inplace, so output values are stored in the input itself. */
|
||||
*pbuff++ = in;
|
||||
|
||||
/* pState pointer is incremented twice as the real values are located alternatively in the array */
|
||||
pS1++;
|
||||
|
||||
/* First part of the processing with loop unrolling. Compute 4 outputs at a time.
|
||||
** a second loop below computes the remaining 1 to 3 samples. */
|
||||
do
|
||||
{
|
||||
/* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
|
||||
/* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
/* points to the next real value */
|
||||
pS1++;
|
||||
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
pS1++;
|
||||
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
pS1++;
|
||||
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
pS1++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
/* If the blockSize is not a multiple of 4, compute any remaining output samples here.
|
||||
** No loop unrolling is used. */
|
||||
i = ((uint32_t) S->N - 1u) % 0x4u;
|
||||
|
||||
while(i > 0u)
|
||||
{
|
||||
/* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
|
||||
/* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
/* points to the next real value */
|
||||
pS1++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
}
|
||||
|
||||
|
||||
/*------------ Normalizing the output by multiplying with the normalizing factor ----------*/
|
||||
|
||||
/* Initializing the loop counter to N/4 instead of N for loop unrolling */
|
||||
i = (uint32_t) S->N >> 2u;
|
||||
|
||||
/* pbuff initialized to the pInlineBuffer(now contains the output values) */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* Processing with loop unrolling 4 times as N is always multiple of 4. Compute 4 outputs at a time */
|
||||
do
|
||||
{
|
||||
/* Multiplying pInlineBuffer with the normalizing factor sqrt(2/N) */
|
||||
in = *pbuff;
|
||||
*pbuff++ = ((q15_t) (((q31_t) in * S->normalize) >> 15));
|
||||
|
||||
in = *pbuff;
|
||||
*pbuff++ = ((q15_t) (((q31_t) in * S->normalize) >> 15));
|
||||
|
||||
in = *pbuff;
|
||||
*pbuff++ = ((q15_t) (((q31_t) in * S->normalize) >> 15));
|
||||
|
||||
in = *pbuff;
|
||||
*pbuff++ = ((q15_t) (((q31_t) in * S->normalize) >> 15));
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* Run the below code for Cortex-M0 */
|
||||
|
||||
/* Initializing the loop counter to N/2 */
|
||||
i = (uint32_t) S->Nby2;
|
||||
|
||||
do
|
||||
{
|
||||
/* Re-ordering of even and odd elements */
|
||||
/* pState[i] = pInlineBuffer[2*i] */
|
||||
*pS1++ = *pbuff++;
|
||||
/* pState[N-i-1] = pInlineBuffer[2*i+1] */
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
/* pbuff initialized to input buffer */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* Initializing the loop counter */
|
||||
i = (uint32_t) S->N;
|
||||
|
||||
do
|
||||
{
|
||||
/* Writing the re-ordered output back to inplace input buffer */
|
||||
*pbuff++ = *pS1++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
* Step2: Calculate RFFT for N-point input
|
||||
* ---------------------------------------------------------- */
|
||||
/* pInlineBuffer is real input of length N , pState is the complex output of length 2N */
|
||||
arm_rfft_q15(S->pRfft, pInlineBuffer, pState);
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Step3: Multiply the FFT output with the weights.
|
||||
*----------------------------------------------------------------------*/
|
||||
arm_cmplx_mult_cmplx_q15(pState, weights, pState, S->N);
|
||||
|
||||
/* The output of complex multiplication is in 3.13 format.
|
||||
* Hence changing the format of N (i.e. 2*N elements) complex numbers to 1.15 format by shifting left by 2 bits. */
|
||||
arm_shift_q15(pState, 2, pState, S->N * 2);
|
||||
|
||||
/* ----------- Post-processing ---------- */
|
||||
/* DCT-IV can be obtained from DCT-II by the equation,
|
||||
* Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
|
||||
* Hence, Y4(0) = Y2(0)/2 */
|
||||
/* Getting only real part from the output and Converting to DCT-IV */
|
||||
|
||||
/* Initializing the loop counter */
|
||||
i = ((uint32_t) S->N - 1u);
|
||||
|
||||
/* pbuff initialized to input buffer. */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* Calculating Y4(0) from Y2(0) using Y4(0) = Y2(0)/2 */
|
||||
in = *pS1++ >> 1u;
|
||||
/* input buffer acts as inplace, so output values are stored in the input itself. */
|
||||
*pbuff++ = in;
|
||||
|
||||
/* pState pointer is incremented twice as the real values are located alternatively in the array */
|
||||
pS1++;
|
||||
|
||||
do
|
||||
{
|
||||
/* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
|
||||
/* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
/* points to the next real value */
|
||||
pS1++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
/*------------ Normalizing the output by multiplying with the normalizing factor ----------*/
|
||||
|
||||
/* Initializing the loop counter */
|
||||
i = (uint32_t) S->N;
|
||||
|
||||
/* pbuff initialized to the pInlineBuffer(now contains the output values) */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
do
|
||||
{
|
||||
/* Multiplying pInlineBuffer with the normalizing factor sqrt(2/N) */
|
||||
in = *pbuff;
|
||||
*pbuff++ = ((q15_t) (((q31_t) in * S->normalize) >> 15));
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
#endif /* #ifndef ARM_MATH_CM0 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of DCT4_IDCT4 group
|
||||
*/
|
||||
@@ -0,0 +1,387 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_dct4_q31.c
|
||||
*
|
||||
* Description: Processing function of DCT4 & IDCT4 Q31.
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 1.0.10 2011/7/15
|
||||
* Big Endian support added and Merged M0 and M3/M4 Source code.
|
||||
*
|
||||
* Version 1.0.3 2010/11/29
|
||||
* Re-organized the CMSIS folders and updated documentation.
|
||||
*
|
||||
* Version 1.0.2 2010/11/11
|
||||
* Documentation updated.
|
||||
*
|
||||
* Version 1.0.1 2010/10/05
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 1.0.0 2010/09/20
|
||||
* Production release and review comments incorporated.
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
|
||||
/**
|
||||
* @addtogroup DCT4_IDCT4
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Processing function for the Q31 DCT4/IDCT4.
|
||||
* @param[in] *S points to an instance of the Q31 DCT4 structure.
|
||||
* @param[in] *pState points to state buffer.
|
||||
* @param[in,out] *pInlineBuffer points to the in-place input and output buffer.
|
||||
* @return none.
|
||||
* \par Input an output formats:
|
||||
* Input samples need to be downscaled by 1 bit to avoid saturations in the Q31 DCT process,
|
||||
* as the conversion from DCT2 to DCT4 involves one subtraction.
|
||||
* Internally inputs are downscaled in the RFFT process function to avoid overflows.
|
||||
* Number of bits downscaled, depends on the size of the transform.
|
||||
* The input and output formats for different DCT sizes and number of bits to upscale are mentioned in the table below:
|
||||
*
|
||||
* \image html dct4FormatsQ31Table.gif
|
||||
*/
|
||||
|
||||
void arm_dct4_q31(
|
||||
const arm_dct4_instance_q31 * S,
|
||||
q31_t * pState,
|
||||
q31_t * pInlineBuffer)
|
||||
{
|
||||
uint16_t i; /* Loop counter */
|
||||
q31_t *weights = S->pTwiddle; /* Pointer to the Weights table */
|
||||
q31_t *cosFact = S->pCosFactor; /* Pointer to the cos factors table */
|
||||
q31_t *pS1, *pS2, *pbuff; /* Temporary pointers for input buffer and pState buffer */
|
||||
q31_t in; /* Temporary variable */
|
||||
|
||||
|
||||
/* DCT4 computation involves DCT2 (which is calculated using RFFT)
|
||||
* along with some pre-processing and post-processing.
|
||||
* Computational procedure is explained as follows:
|
||||
* (a) Pre-processing involves multiplying input with cos factor,
|
||||
* r(n) = 2 * u(n) * cos(pi*(2*n+1)/(4*n))
|
||||
* where,
|
||||
* r(n) -- output of preprocessing
|
||||
* u(n) -- input to preprocessing(actual Source buffer)
|
||||
* (b) Calculation of DCT2 using FFT is divided into three steps:
|
||||
* Step1: Re-ordering of even and odd elements of input.
|
||||
* Step2: Calculating FFT of the re-ordered input.
|
||||
* Step3: Taking the real part of the product of FFT output and weights.
|
||||
* (c) Post-processing - DCT4 can be obtained from DCT2 output using the following equation:
|
||||
* Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
|
||||
* where,
|
||||
* Y4 -- DCT4 output, Y2 -- DCT2 output
|
||||
* (d) Multiplying the output with the normalizing factor sqrt(2/N).
|
||||
*/
|
||||
|
||||
/*-------- Pre-processing ------------*/
|
||||
/* Multiplying input with cos factor i.e. r(n) = 2 * x(n) * cos(pi*(2*n+1)/(4*n)) */
|
||||
arm_mult_q31(pInlineBuffer, cosFact, pInlineBuffer, S->N);
|
||||
arm_shift_q31(pInlineBuffer, 1, pInlineBuffer, S->N);
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Step1: Re-ordering of even and odd elements as
|
||||
* pState[i] = pInlineBuffer[2*i] and
|
||||
* pState[N-i-1] = pInlineBuffer[2*i+1] where i = 0 to N/2
|
||||
---------------------------------------------------------------------*/
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* pS2 initialized to pState+N-1, so that it points to the end of the state buffer */
|
||||
pS2 = pState + (S->N - 1u);
|
||||
|
||||
/* pbuff initialized to input buffer */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
#ifndef ARM_MATH_CM0
|
||||
|
||||
/* Run the below code for Cortex-M4 and Cortex-M3 */
|
||||
|
||||
/* Initializing the loop counter to N/2 >> 2 for loop unrolling by 4 */
|
||||
i = S->Nby2 >> 2u;
|
||||
|
||||
/* First part of the processing with loop unrolling. Compute 4 outputs at a time.
|
||||
** a second loop below computes the remaining 1 to 3 samples. */
|
||||
do
|
||||
{
|
||||
/* Re-ordering of even and odd elements */
|
||||
/* pState[i] = pInlineBuffer[2*i] */
|
||||
*pS1++ = *pbuff++;
|
||||
/* pState[N-i-1] = pInlineBuffer[2*i+1] */
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
*pS1++ = *pbuff++;
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
*pS1++ = *pbuff++;
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
*pS1++ = *pbuff++;
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
/* pbuff initialized to input buffer */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* Initializing the loop counter to N/4 instead of N for loop unrolling */
|
||||
i = S->N >> 2u;
|
||||
|
||||
/* Processing with loop unrolling 4 times as N is always multiple of 4.
|
||||
* Compute 4 outputs at a time */
|
||||
do
|
||||
{
|
||||
/* Writing the re-ordered output back to inplace input buffer */
|
||||
*pbuff++ = *pS1++;
|
||||
*pbuff++ = *pS1++;
|
||||
*pbuff++ = *pS1++;
|
||||
*pbuff++ = *pS1++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
* Step2: Calculate RFFT for N-point input
|
||||
* ---------------------------------------------------------- */
|
||||
/* pInlineBuffer is real input of length N , pState is the complex output of length 2N */
|
||||
arm_rfft_q31(S->pRfft, pInlineBuffer, pState);
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Step3: Multiply the FFT output with the weights.
|
||||
*----------------------------------------------------------------------*/
|
||||
arm_cmplx_mult_cmplx_q31(pState, weights, pState, S->N);
|
||||
|
||||
/* The output of complex multiplication is in 3.29 format.
|
||||
* Hence changing the format of N (i.e. 2*N elements) complex numbers to 1.31 format by shifting left by 2 bits. */
|
||||
arm_shift_q31(pState, 2, pState, S->N * 2);
|
||||
|
||||
/* ----------- Post-processing ---------- */
|
||||
/* DCT-IV can be obtained from DCT-II by the equation,
|
||||
* Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
|
||||
* Hence, Y4(0) = Y2(0)/2 */
|
||||
/* Getting only real part from the output and Converting to DCT-IV */
|
||||
|
||||
/* Initializing the loop counter to N >> 2 for loop unrolling by 4 */
|
||||
i = (S->N - 1u) >> 2u;
|
||||
|
||||
/* pbuff initialized to input buffer. */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* Calculating Y4(0) from Y2(0) using Y4(0) = Y2(0)/2 */
|
||||
in = *pS1++ >> 1u;
|
||||
/* input buffer acts as inplace, so output values are stored in the input itself. */
|
||||
*pbuff++ = in;
|
||||
|
||||
/* pState pointer is incremented twice as the real values are located alternatively in the array */
|
||||
pS1++;
|
||||
|
||||
/* First part of the processing with loop unrolling. Compute 4 outputs at a time.
|
||||
** a second loop below computes the remaining 1 to 3 samples. */
|
||||
do
|
||||
{
|
||||
/* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
|
||||
/* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
/* points to the next real value */
|
||||
pS1++;
|
||||
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
pS1++;
|
||||
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
pS1++;
|
||||
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
pS1++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
/* If the blockSize is not a multiple of 4, compute any remaining output samples here.
|
||||
** No loop unrolling is used. */
|
||||
i = (S->N - 1u) % 0x4u;
|
||||
|
||||
while(i > 0u)
|
||||
{
|
||||
/* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
|
||||
/* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
/* points to the next real value */
|
||||
pS1++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
}
|
||||
|
||||
|
||||
/*------------ Normalizing the output by multiplying with the normalizing factor ----------*/
|
||||
|
||||
/* Initializing the loop counter to N/4 instead of N for loop unrolling */
|
||||
i = S->N >> 2u;
|
||||
|
||||
/* pbuff initialized to the pInlineBuffer(now contains the output values) */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* Processing with loop unrolling 4 times as N is always multiple of 4. Compute 4 outputs at a time */
|
||||
do
|
||||
{
|
||||
/* Multiplying pInlineBuffer with the normalizing factor sqrt(2/N) */
|
||||
in = *pbuff;
|
||||
*pbuff++ = ((q31_t) (((q63_t) in * S->normalize) >> 31));
|
||||
|
||||
in = *pbuff;
|
||||
*pbuff++ = ((q31_t) (((q63_t) in * S->normalize) >> 31));
|
||||
|
||||
in = *pbuff;
|
||||
*pbuff++ = ((q31_t) (((q63_t) in * S->normalize) >> 31));
|
||||
|
||||
in = *pbuff;
|
||||
*pbuff++ = ((q31_t) (((q63_t) in * S->normalize) >> 31));
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* Run the below code for Cortex-M0 */
|
||||
|
||||
/* Initializing the loop counter to N/2 */
|
||||
i = S->Nby2;
|
||||
|
||||
do
|
||||
{
|
||||
/* Re-ordering of even and odd elements */
|
||||
/* pState[i] = pInlineBuffer[2*i] */
|
||||
*pS1++ = *pbuff++;
|
||||
/* pState[N-i-1] = pInlineBuffer[2*i+1] */
|
||||
*pS2-- = *pbuff++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
/* pbuff initialized to input buffer */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* Initializing the loop counter */
|
||||
i = S->N;
|
||||
|
||||
do
|
||||
{
|
||||
/* Writing the re-ordered output back to inplace input buffer */
|
||||
*pbuff++ = *pS1++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
* Step2: Calculate RFFT for N-point input
|
||||
* ---------------------------------------------------------- */
|
||||
/* pInlineBuffer is real input of length N , pState is the complex output of length 2N */
|
||||
arm_rfft_q31(S->pRfft, pInlineBuffer, pState);
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Step3: Multiply the FFT output with the weights.
|
||||
*----------------------------------------------------------------------*/
|
||||
arm_cmplx_mult_cmplx_q31(pState, weights, pState, S->N);
|
||||
|
||||
/* The output of complex multiplication is in 3.29 format.
|
||||
* Hence changing the format of N (i.e. 2*N elements) complex numbers to 1.31 format by shifting left by 2 bits. */
|
||||
arm_shift_q31(pState, 2, pState, S->N * 2);
|
||||
|
||||
/* ----------- Post-processing ---------- */
|
||||
/* DCT-IV can be obtained from DCT-II by the equation,
|
||||
* Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
|
||||
* Hence, Y4(0) = Y2(0)/2 */
|
||||
/* Getting only real part from the output and Converting to DCT-IV */
|
||||
|
||||
/* pbuff initialized to input buffer. */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
/* pS1 initialized to pState */
|
||||
pS1 = pState;
|
||||
|
||||
/* Calculating Y4(0) from Y2(0) using Y4(0) = Y2(0)/2 */
|
||||
in = *pS1++ >> 1u;
|
||||
/* input buffer acts as inplace, so output values are stored in the input itself. */
|
||||
*pbuff++ = in;
|
||||
|
||||
/* pState pointer is incremented twice as the real values are located alternatively in the array */
|
||||
pS1++;
|
||||
|
||||
/* Initializing the loop counter */
|
||||
i = (S->N - 1u);
|
||||
|
||||
while(i > 0u)
|
||||
{
|
||||
/* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
|
||||
/* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
|
||||
in = *pS1++ - in;
|
||||
*pbuff++ = in;
|
||||
/* points to the next real value */
|
||||
pS1++;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
}
|
||||
|
||||
|
||||
/*------------ Normalizing the output by multiplying with the normalizing factor ----------*/
|
||||
|
||||
/* Initializing the loop counter */
|
||||
i = S->N;
|
||||
|
||||
/* pbuff initialized to the pInlineBuffer(now contains the output values) */
|
||||
pbuff = pInlineBuffer;
|
||||
|
||||
do
|
||||
{
|
||||
/* Multiplying pInlineBuffer with the normalizing factor sqrt(2/N) */
|
||||
in = *pbuff;
|
||||
*pbuff++ = ((q31_t) (((q63_t) in * S->normalize) >> 31));
|
||||
|
||||
/* Decrement the loop counter */
|
||||
i--;
|
||||
} while(i > 0u);
|
||||
|
||||
#endif /* #ifndef ARM_MATH_CM0 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of DCT4_IDCT4 group
|
||||
*/
|
||||
@@ -0,0 +1,382 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_rfft_f32.c
|
||||
*
|
||||
* Description: RFFT & RIFFT Floating point process function
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 1.0.10 2011/7/15
|
||||
* Big Endian support added and Merged M0 and M3/M4 Source code.
|
||||
*
|
||||
* Version 1.0.3 2010/11/29
|
||||
* Re-organized the CMSIS folders and updated documentation.
|
||||
*
|
||||
* Version 1.0.2 2010/11/11
|
||||
* Documentation updated.
|
||||
*
|
||||
* Version 1.0.1 2010/10/05
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 1.0.0 2010/09/20
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 0.0.7 2010/06/10
|
||||
* Misra-C changes done
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupTransforms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup RFFT_RIFFT Real FFT Functions
|
||||
*
|
||||
* \par
|
||||
* Complex FFT/IFFT typically assumes complex input and output. However many applications use real valued data in time domain.
|
||||
* Real FFT/IFFT efficiently process real valued sequences with the advantage of requirement of low memory and with less complexity.
|
||||
*
|
||||
* \par
|
||||
* This set of functions implements Real Fast Fourier Transforms(RFFT) and Real Inverse Fast Fourier Transform(RIFFT)
|
||||
* for Q15, Q31, and floating-point data types.
|
||||
*
|
||||
*
|
||||
* \par Algorithm:
|
||||
*
|
||||
* <b>Real Fast Fourier Transform:</b>
|
||||
* \par
|
||||
* Real FFT of N-point is calculated using CFFT of N/2-point and Split RFFT process as shown below figure.
|
||||
* \par
|
||||
* \image html RFFT.gif "Real Fast Fourier Transform"
|
||||
* \par
|
||||
* The RFFT functions operate on blocks of input and output data and each call to the function processes
|
||||
* <code>fftLenR</code> samples through the transform. <code>pSrc</code> points to input array containing <code>fftLenR</code> values.
|
||||
* <code>pDst</code> points to output array containing <code>2*fftLenR</code> values. \n
|
||||
* Input for real FFT is in the order of
|
||||
* <pre>{real[0], real[1], real[2], real[3], ..}</pre>
|
||||
* Output for real FFT is complex and are in the order of
|
||||
* <pre>{real(0), imag(0), real(1), imag(1), ...}</pre>
|
||||
*
|
||||
* <b>Real Inverse Fast Fourier Transform:</b>
|
||||
* \par
|
||||
* Real IFFT of N-point is calculated using Split RIFFT process and CFFT of N/2-point as shown below figure.
|
||||
* \par
|
||||
* \image html RIFFT.gif "Real Inverse Fast Fourier Transform"
|
||||
* \par
|
||||
* The RIFFT functions operate on blocks of input and output data and each call to the function processes
|
||||
* <code>2*fftLenR</code> samples through the transform. <code>pSrc</code> points to input array containing <code>2*fftLenR</code> values.
|
||||
* <code>pDst</code> points to output array containing <code>fftLenR</code> values. \n
|
||||
* Input for real IFFT is complex and are in the order of
|
||||
* <pre>{real(0), imag(0), real(1), imag(1), ...}</pre>
|
||||
* Output for real IFFT is real and in the order of
|
||||
* <pre>{real[0], real[1], real[2], real[3], ..}</pre>
|
||||
*
|
||||
* \par Lengths supported by the transform:
|
||||
* \par
|
||||
* Real FFT/IFFT supports the lengths [128, 512, 2048], as it internally uses CFFT/CIFFT.
|
||||
*
|
||||
* \par Instance Structure
|
||||
* A separate instance structure must be defined for each Instance but the twiddle factors can be reused.
|
||||
* There are separate instance structure declarations for each of the 3 supported data types.
|
||||
*
|
||||
* \par Initialization Functions
|
||||
* There is also an associated initialization function for each data type.
|
||||
* The initialization function performs the following operations:
|
||||
* - Sets the values of the internal structure fields.
|
||||
* - Initializes twiddle factor tables.
|
||||
* - Initializes CFFT data structure fields.
|
||||
* \par
|
||||
* Use of the initialization function is optional.
|
||||
* However, if the initialization function is used, then the instance structure cannot be placed into a const data section.
|
||||
* To place an instance structure into a const data section, the instance structure must be manually initialized.
|
||||
* Manually initialize the instance structure as follows:
|
||||
* <pre>
|
||||
*arm_rfft_instance_f32 S = {fftLenReal, fftLenBy2, ifftFlagR, bitReverseFlagR, twidCoefRModifier, pTwiddleAReal, pTwiddleBReal, pCfft};
|
||||
*arm_rfft_instance_q31 S = {fftLenReal, fftLenBy2, ifftFlagR, bitReverseFlagR, twidCoefRModifier, pTwiddleAReal, pTwiddleBReal, pCfft};
|
||||
*arm_rfft_instance_q15 S = {fftLenReal, fftLenBy2, ifftFlagR, bitReverseFlagR, twidCoefRModifier, pTwiddleAReal, pTwiddleBReal, pCfft};
|
||||
* </pre>
|
||||
* where <code>fftLenReal</code> length of RFFT/RIFFT; <code>fftLenBy2</code> length of CFFT/CIFFT.
|
||||
* <code>ifftFlagR</code> Flag for selection of RFFT or RIFFT(Set ifftFlagR to calculate RIFFT otherwise calculates RFFT);
|
||||
* <code>bitReverseFlagR</code> Flag for selection of output order(Set bitReverseFlagR to output in normal order otherwise output in bit reversed order);
|
||||
* <code>twidCoefRModifier</code> modifier for twiddle factor table which supports 128, 512, 2048 RFFT lengths with same table;
|
||||
* <code>pTwiddleAReal</code>points to A array of twiddle coefficients; <code>pTwiddleBReal</code>points to B array of twiddle coefficients;
|
||||
* <code>pCfft</code> points to the CFFT Instance structure. The CFFT structure also needs to be initialized, refer to arm_cfft_radix4_f32() for details regarding
|
||||
* static initialization of cfft structure.
|
||||
*
|
||||
* \par Fixed-Point Behavior
|
||||
* Care must be taken when using the fixed-point versions of the RFFT/RIFFT function.
|
||||
* Refer to the function specific documentation below for usage guidelines.
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Internal functions prototypes
|
||||
*--------------------------------------------------------------------*/
|
||||
|
||||
void arm_split_rfft_f32(
|
||||
float32_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
float32_t * pATable,
|
||||
float32_t * pBTable,
|
||||
float32_t * pDst,
|
||||
uint32_t modifier);
|
||||
void arm_split_rifft_f32(
|
||||
float32_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
float32_t * pATable,
|
||||
float32_t * pBTable,
|
||||
float32_t * pDst,
|
||||
uint32_t modifier);
|
||||
|
||||
/**
|
||||
* @addtogroup RFFT_RIFFT
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Processing function for the floating-point RFFT/RIFFT.
|
||||
* @param[in] *S points to an instance of the floating-point RFFT/RIFFT structure.
|
||||
* @param[in] *pSrc points to the input buffer.
|
||||
* @param[out] *pDst points to the output buffer.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_rfft_f32(
|
||||
const arm_rfft_instance_f32 * S,
|
||||
float32_t * pSrc,
|
||||
float32_t * pDst)
|
||||
{
|
||||
const arm_cfft_radix4_instance_f32 *S_CFFT = S->pCfft;
|
||||
|
||||
|
||||
/* Calculation of Real IFFT of input */
|
||||
if(S->ifftFlagR == 1u)
|
||||
{
|
||||
/* Real IFFT core process */
|
||||
arm_split_rifft_f32(pSrc, S->fftLenBy2, S->pTwiddleAReal,
|
||||
S->pTwiddleBReal, pDst, S->twidCoefRModifier);
|
||||
|
||||
|
||||
/* Complex radix-4 IFFT process */
|
||||
arm_radix4_butterfly_inverse_f32(pDst, S_CFFT->fftLen,
|
||||
S_CFFT->pTwiddle,
|
||||
S_CFFT->twidCoefModifier,
|
||||
S_CFFT->onebyfftLen);
|
||||
|
||||
/* Bit reversal process */
|
||||
if(S->bitReverseFlagR == 1u)
|
||||
{
|
||||
arm_bitreversal_f32(pDst, S_CFFT->fftLen,
|
||||
S_CFFT->bitRevFactor, S_CFFT->pBitRevTable);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Calculation of RFFT of input */
|
||||
|
||||
/* Complex radix-4 FFT process */
|
||||
arm_radix4_butterfly_f32(pSrc, S_CFFT->fftLen,
|
||||
S_CFFT->pTwiddle, S_CFFT->twidCoefModifier);
|
||||
|
||||
/* Bit reversal process */
|
||||
if(S->bitReverseFlagR == 1u)
|
||||
{
|
||||
arm_bitreversal_f32(pSrc, S_CFFT->fftLen,
|
||||
S_CFFT->bitRevFactor, S_CFFT->pBitRevTable);
|
||||
}
|
||||
|
||||
|
||||
/* Real FFT core process */
|
||||
arm_split_rfft_f32(pSrc, S->fftLenBy2, S->pTwiddleAReal,
|
||||
S->pTwiddleBReal, pDst, S->twidCoefRModifier);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of RFFT_RIFFT group
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Core Real FFT process
|
||||
* @param[in] *pSrc points to the input buffer.
|
||||
* @param[in] fftLen length of FFT.
|
||||
* @param[in] *pATable points to the twiddle Coef A buffer.
|
||||
* @param[in] *pBTable points to the twiddle Coef B buffer.
|
||||
* @param[out] *pDst points to the output buffer.
|
||||
* @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_split_rfft_f32(
|
||||
float32_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
float32_t * pATable,
|
||||
float32_t * pBTable,
|
||||
float32_t * pDst,
|
||||
uint32_t modifier)
|
||||
{
|
||||
uint32_t i; /* Loop Counter */
|
||||
float32_t outR, outI; /* Temporary variables for output */
|
||||
float32_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */
|
||||
float32_t CoefA1, CoefA2, CoefB1; /* Temporary variables for twiddle coefficients */
|
||||
float32_t *pDst1 = &pDst[2], *pDst2 = &pDst[(4u * fftLen) - 1u]; /* temp pointers for output buffer */
|
||||
float32_t *pSrc1 = &pSrc[2], *pSrc2 = &pSrc[(2u * fftLen) - 1u]; /* temp pointers for input buffer */
|
||||
|
||||
/* Init coefficient pointers */
|
||||
pCoefA = &pATable[modifier * 2u];
|
||||
pCoefB = &pBTable[modifier * 2u];
|
||||
|
||||
i = fftLen - 1u;
|
||||
|
||||
while(i > 0u)
|
||||
{
|
||||
/*
|
||||
outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]
|
||||
+ pSrc[2 * n - 2 * i] * pBTable[2 * i] +
|
||||
pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
|
||||
*/
|
||||
|
||||
/* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +
|
||||
pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); */
|
||||
|
||||
/* read pATable[2 * i] */
|
||||
CoefA1 = *pCoefA++;
|
||||
/* pATable[2 * i + 1] */
|
||||
CoefA2 = *pCoefA;
|
||||
|
||||
/* pSrc[2 * i] * pATable[2 * i] */
|
||||
outR = *pSrc1 * CoefA1;
|
||||
/* pSrc[2 * i] * CoefA2 */
|
||||
outI = *pSrc1++ * CoefA2;
|
||||
|
||||
/* (pSrc[2 * i + 1] + pSrc[2 * fftLen - 2 * i + 1]) * CoefA2 */
|
||||
outR -= (*pSrc1 + *pSrc2) * CoefA2;
|
||||
/* pSrc[2 * i + 1] * CoefA1 */
|
||||
outI += *pSrc1++ * CoefA1;
|
||||
|
||||
CoefB1 = *pCoefB;
|
||||
|
||||
/* pSrc[2 * fftLen - 2 * i + 1] * CoefB1 */
|
||||
outI -= *pSrc2-- * CoefB1;
|
||||
/* pSrc[2 * fftLen - 2 * i] * CoefA2 */
|
||||
outI -= *pSrc2 * CoefA2;
|
||||
|
||||
/* pSrc[2 * fftLen - 2 * i] * CoefB1 */
|
||||
outR += *pSrc2-- * CoefB1;
|
||||
|
||||
/* write output */
|
||||
*pDst1++ = outR;
|
||||
*pDst1++ = outI;
|
||||
|
||||
/* write complex conjugate output */
|
||||
*pDst2-- = -outI;
|
||||
*pDst2-- = outR;
|
||||
|
||||
/* update coefficient pointer */
|
||||
pCoefB = pCoefB + (modifier * 2u);
|
||||
pCoefA = pCoefA + ((modifier * 2u) - 1u);
|
||||
|
||||
i--;
|
||||
|
||||
}
|
||||
|
||||
pDst[2u * fftLen] = pSrc[0] - pSrc[1];
|
||||
pDst[(2u * fftLen) + 1u] = 0.0f;
|
||||
|
||||
pDst[0] = pSrc[0] + pSrc[1];
|
||||
pDst[1] = 0.0f;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Core Real IFFT process
|
||||
* @param[in] *pSrc points to the input buffer.
|
||||
* @param[in] fftLen length of FFT.
|
||||
* @param[in] *pATable points to the twiddle Coef A buffer.
|
||||
* @param[in] *pBTable points to the twiddle Coef B buffer.
|
||||
* @param[out] *pDst points to the output buffer.
|
||||
* @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_split_rifft_f32(
|
||||
float32_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
float32_t * pATable,
|
||||
float32_t * pBTable,
|
||||
float32_t * pDst,
|
||||
uint32_t modifier)
|
||||
{
|
||||
float32_t outR, outI; /* Temporary variables for output */
|
||||
float32_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */
|
||||
float32_t CoefA1, CoefA2, CoefB1; /* Temporary variables for twiddle coefficients */
|
||||
float32_t *pSrc1 = &pSrc[0], *pSrc2 = &pSrc[(2u * fftLen) + 1u];
|
||||
|
||||
pCoefA = &pATable[0];
|
||||
pCoefB = &pBTable[0];
|
||||
|
||||
while(fftLen > 0u)
|
||||
{
|
||||
/*
|
||||
outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +
|
||||
pIn[2 * n - 2 * i] * pBTable[2 * i] -
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
|
||||
|
||||
outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -
|
||||
pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);
|
||||
|
||||
*/
|
||||
|
||||
CoefA1 = *pCoefA++;
|
||||
CoefA2 = *pCoefA;
|
||||
|
||||
/* outR = (pSrc[2 * i] * CoefA1 */
|
||||
outR = *pSrc1 * CoefA1;
|
||||
|
||||
/* - pSrc[2 * i] * CoefA2 */
|
||||
outI = -(*pSrc1++) * CoefA2;
|
||||
|
||||
/* (pSrc[2 * i + 1] + pSrc[2 * fftLen - 2 * i + 1]) * CoefA2 */
|
||||
outR += (*pSrc1 + *pSrc2) * CoefA2;
|
||||
|
||||
/* pSrc[2 * i + 1] * CoefA1 */
|
||||
outI += (*pSrc1++) * CoefA1;
|
||||
|
||||
CoefB1 = *pCoefB;
|
||||
|
||||
/* - pSrc[2 * fftLen - 2 * i + 1] * CoefB1 */
|
||||
outI -= *pSrc2-- * CoefB1;
|
||||
|
||||
/* pSrc[2 * fftLen - 2 * i] * CoefB1 */
|
||||
outR += *pSrc2 * CoefB1;
|
||||
|
||||
/* pSrc[2 * fftLen - 2 * i] * CoefA2 */
|
||||
outI += *pSrc2-- * CoefA2;
|
||||
|
||||
/* write output */
|
||||
*pDst++ = outR;
|
||||
*pDst++ = outI;
|
||||
|
||||
/* update coefficient pointer */
|
||||
pCoefB = pCoefB + (modifier * 2u);
|
||||
pCoefA = pCoefA + ((modifier * 2u) - 1u);
|
||||
|
||||
/* Decrement loop count */
|
||||
fftLen--;
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,460 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_rfft_q15.c
|
||||
*
|
||||
* Description: RFFT & RIFFT Q15 process function
|
||||
*
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 1.0.10 2011/7/15
|
||||
* Big Endian support added and Merged M0 and M3/M4 Source code.
|
||||
*
|
||||
* Version 1.0.3 2010/11/29
|
||||
* Re-organized the CMSIS folders and updated documentation.
|
||||
*
|
||||
* Version 1.0.2 2010/11/11
|
||||
* Documentation updated.
|
||||
*
|
||||
* Version 1.0.1 2010/10/05
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 1.0.0 2010/09/20
|
||||
* Production release and review comments incorporated
|
||||
*
|
||||
* Version 0.0.7 2010/06/10
|
||||
* Misra-C changes done
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "arm_math.h"
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Internal functions prototypes
|
||||
--------------------------------------------------------------------*/
|
||||
|
||||
void arm_split_rfft_q15(
|
||||
q15_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
q15_t * pATable,
|
||||
q15_t * pBTable,
|
||||
q15_t * pDst,
|
||||
uint32_t modifier);
|
||||
|
||||
void arm_split_rifft_q15(
|
||||
q15_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
q15_t * pATable,
|
||||
q15_t * pBTable,
|
||||
q15_t * pDst,
|
||||
uint32_t modifier);
|
||||
|
||||
/**
|
||||
* @addtogroup RFFT_RIFFT
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Processing function for the Q15 RFFT/RIFFT.
|
||||
* @param[in] *S points to an instance of the Q15 RFFT/RIFFT structure.
|
||||
* @param[in] *pSrc points to the input buffer.
|
||||
* @param[out] *pDst points to the output buffer.
|
||||
* @return none.
|
||||
*
|
||||
* \par Input an output formats:
|
||||
* \par
|
||||
* Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process.
|
||||
* Hence the output format is different for different RFFT sizes.
|
||||
* 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:
|
||||
* \par
|
||||
* \image html RFFTQ15.gif "Input and Output Formats for Q15 RFFT"
|
||||
* \par
|
||||
* \image html RIFFTQ15.gif "Input and Output Formats for Q15 RIFFT"
|
||||
*/
|
||||
|
||||
void arm_rfft_q15(
|
||||
const arm_rfft_instance_q15 * S,
|
||||
q15_t * pSrc,
|
||||
q15_t * pDst)
|
||||
{
|
||||
const arm_cfft_radix4_instance_q15 *S_CFFT = S->pCfft;
|
||||
|
||||
/* Calculation of RIFFT of input */
|
||||
if(S->ifftFlagR == 1u)
|
||||
{
|
||||
/* Real IFFT core process */
|
||||
arm_split_rifft_q15(pSrc, S->fftLenBy2, S->pTwiddleAReal,
|
||||
S->pTwiddleBReal, pDst, S->twidCoefRModifier);
|
||||
|
||||
/* Complex readix-4 IFFT process */
|
||||
arm_radix4_butterfly_inverse_q15(pDst, S_CFFT->fftLen,
|
||||
S_CFFT->pTwiddle,
|
||||
S_CFFT->twidCoefModifier);
|
||||
|
||||
/* Bit reversal process */
|
||||
if(S->bitReverseFlagR == 1u)
|
||||
{
|
||||
arm_bitreversal_q15(pDst, S_CFFT->fftLen,
|
||||
S_CFFT->bitRevFactor, S_CFFT->pBitRevTable);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Calculation of RFFT of input */
|
||||
|
||||
/* Complex readix-4 FFT process */
|
||||
arm_radix4_butterfly_q15(pSrc, S_CFFT->fftLen,
|
||||
S_CFFT->pTwiddle, S_CFFT->twidCoefModifier);
|
||||
|
||||
/* Bit reversal process */
|
||||
if(S->bitReverseFlagR == 1u)
|
||||
{
|
||||
arm_bitreversal_q15(pSrc, S_CFFT->fftLen,
|
||||
S_CFFT->bitRevFactor, S_CFFT->pBitRevTable);
|
||||
}
|
||||
|
||||
arm_split_rfft_q15(pSrc, S->fftLenBy2, S->pTwiddleAReal,
|
||||
S->pTwiddleBReal, pDst, S->twidCoefRModifier);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of RFFT_RIFFT group
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Core Real FFT process
|
||||
* @param *pSrc points to the input buffer.
|
||||
* @param fftLen length of FFT.
|
||||
* @param *pATable points to the A twiddle Coef buffer.
|
||||
* @param *pBTable points to the B twiddle Coef buffer.
|
||||
* @param *pDst points to the output buffer.
|
||||
* @param modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
|
||||
* @return none.
|
||||
* The function implements a Real FFT
|
||||
*/
|
||||
|
||||
void arm_split_rfft_q15(
|
||||
q15_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
q15_t * pATable,
|
||||
q15_t * pBTable,
|
||||
q15_t * pDst,
|
||||
uint32_t modifier)
|
||||
{
|
||||
uint32_t i; /* Loop Counter */
|
||||
q31_t outR, outI; /* Temporary variables for output */
|
||||
q15_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */
|
||||
q15_t *pSrc1, *pSrc2;
|
||||
|
||||
|
||||
// pSrc[2u * fftLen] = pSrc[0];
|
||||
// pSrc[(2u * fftLen) + 1u] = pSrc[1];
|
||||
|
||||
pCoefA = &pATable[modifier * 2u];
|
||||
pCoefB = &pBTable[modifier * 2u];
|
||||
|
||||
pSrc1 = &pSrc[2];
|
||||
pSrc2 = &pSrc[(2u * fftLen) - 2u];
|
||||
|
||||
#ifndef ARM_MATH_CM0
|
||||
|
||||
/* Run the below code for Cortex-M4 and Cortex-M3 */
|
||||
|
||||
i = 1u;
|
||||
|
||||
while(i < fftLen)
|
||||
{
|
||||
/*
|
||||
outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]
|
||||
+ pSrc[2 * n - 2 * i] * pBTable[2 * i] +
|
||||
pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
|
||||
*/
|
||||
|
||||
/* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +
|
||||
pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); */
|
||||
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
/* pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1] */
|
||||
outR = __SMUSD(*__SIMD32(pSrc1), *__SIMD32(pCoefA));
|
||||
|
||||
#else
|
||||
|
||||
/* -(pSrc[2 * i + 1] * pATable[2 * i + 1] - pSrc[2 * i] * pATable[2 * i]) */
|
||||
outR = -(__SMUSD(*__SIMD32(pSrc1), *__SIMD32(pCoefA)));
|
||||
|
||||
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
||||
|
||||
/* pSrc[2 * n - 2 * i] * pBTable[2 * i] +
|
||||
pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]) */
|
||||
outR = __SMLAD(*__SIMD32(pSrc2), *__SIMD32(pCoefB), outR) >> 15u;
|
||||
|
||||
/* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
outI = __SMUSDX(*__SIMD32(pSrc2)--, *__SIMD32(pCoefB));
|
||||
|
||||
#else
|
||||
|
||||
outI = __SMUSDX(*__SIMD32(pCoefB), *__SIMD32(pSrc2)--);
|
||||
|
||||
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
||||
|
||||
/* (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] */
|
||||
outI = __SMLADX(*__SIMD32(pSrc1)++, *__SIMD32(pCoefA), outI);
|
||||
|
||||
/* write output */
|
||||
pDst[2u * i] = (q15_t) outR;
|
||||
pDst[(2u * i) + 1u] = outI >> 15u;
|
||||
|
||||
/* write complex conjugate output */
|
||||
pDst[(4u * fftLen) - (2u * i)] = (q15_t) outR;
|
||||
pDst[((4u * fftLen) - (2u * i)) + 1u] = -(outI >> 15u);
|
||||
|
||||
/* update coefficient pointer */
|
||||
pCoefB = pCoefB + (2u * modifier);
|
||||
pCoefA = pCoefA + (2u * modifier);
|
||||
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
pDst[2u * fftLen] = pSrc[0] - pSrc[1];
|
||||
pDst[(2u * fftLen) + 1u] = 0;
|
||||
|
||||
pDst[0] = pSrc[0] + pSrc[1];
|
||||
pDst[1] = 0;
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* Run the below code for Cortex-M0 */
|
||||
|
||||
i = 1u;
|
||||
|
||||
while(i < fftLen)
|
||||
{
|
||||
/*
|
||||
outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]
|
||||
+ pSrc[2 * n - 2 * i] * pBTable[2 * i] +
|
||||
pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
|
||||
*/
|
||||
|
||||
outR = *pSrc1 * *pCoefA;
|
||||
outR = outR - (*(pSrc1 + 1) * *(pCoefA + 1));
|
||||
outR = outR + (*pSrc2 * *pCoefB);
|
||||
outR = (outR + (*(pSrc2 + 1) * *(pCoefB + 1))) >> 15;
|
||||
|
||||
|
||||
/* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +
|
||||
pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);
|
||||
*/
|
||||
|
||||
outI = *pSrc2 * *(pCoefB + 1);
|
||||
outI = outI - (*(pSrc2 + 1) * *pCoefB);
|
||||
outI = outI + (*(pSrc1 + 1) * *pCoefA);
|
||||
outI = outI + (*pSrc1 * *(pCoefA + 1));
|
||||
|
||||
/* update input pointers */
|
||||
pSrc1 += 2u;
|
||||
pSrc2 -= 2u;
|
||||
|
||||
/* write output */
|
||||
pDst[2u * i] = (q15_t) outR;
|
||||
pDst[(2u * i) + 1u] = outI >> 15u;
|
||||
|
||||
/* write complex conjugate output */
|
||||
pDst[(4u * fftLen) - (2u * i)] = (q15_t) outR;
|
||||
pDst[((4u * fftLen) - (2u * i)) + 1u] = -(outI >> 15u);
|
||||
|
||||
/* update coefficient pointer */
|
||||
pCoefB = pCoefB + (2u * modifier);
|
||||
pCoefA = pCoefA + (2u * modifier);
|
||||
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
pDst[2u * fftLen] = pSrc[0] - pSrc[1];
|
||||
pDst[(2u * fftLen) + 1u] = 0;
|
||||
|
||||
pDst[0] = pSrc[0] + pSrc[1];
|
||||
pDst[1] = 0;
|
||||
|
||||
#endif /* #ifndef ARM_MATH_CM0 */
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Core Real IFFT process
|
||||
* @param[in] *pSrc points to the input buffer.
|
||||
* @param[in] fftLen length of FFT.
|
||||
* @param[in] *pATable points to the twiddle Coef A buffer.
|
||||
* @param[in] *pBTable points to the twiddle Coef B buffer.
|
||||
* @param[out] *pDst points to the output buffer.
|
||||
* @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
|
||||
* @return none.
|
||||
* The function implements a Real IFFT
|
||||
*/
|
||||
void arm_split_rifft_q15(
|
||||
q15_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
q15_t * pATable,
|
||||
q15_t * pBTable,
|
||||
q15_t * pDst,
|
||||
uint32_t modifier)
|
||||
{
|
||||
uint32_t i; /* Loop Counter */
|
||||
q31_t outR, outI; /* Temporary variables for output */
|
||||
q15_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */
|
||||
q15_t *pSrc1, *pSrc2;
|
||||
q15_t *pDst1 = &pDst[0];
|
||||
|
||||
pCoefA = &pATable[0];
|
||||
pCoefB = &pBTable[0];
|
||||
|
||||
pSrc1 = &pSrc[0];
|
||||
pSrc2 = &pSrc[2u * fftLen];
|
||||
|
||||
#ifndef ARM_MATH_CM0
|
||||
|
||||
/* Run the below code for Cortex-M4 and Cortex-M3 */
|
||||
|
||||
i = fftLen;
|
||||
|
||||
while(i > 0u)
|
||||
{
|
||||
|
||||
/*
|
||||
outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +
|
||||
pIn[2 * n - 2 * i] * pBTable[2 * i] -
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
|
||||
|
||||
outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -
|
||||
pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
/* pIn[2 * n - 2 * i] * pBTable[2 * i] -
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]) */
|
||||
outR = __SMUSD(*__SIMD32(pSrc2), *__SIMD32(pCoefB));
|
||||
|
||||
#else
|
||||
|
||||
/* -(-pIn[2 * n - 2 * i] * pBTable[2 * i] +
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1])) */
|
||||
outR = -(__SMUSD(*__SIMD32(pSrc2), *__SIMD32(pCoefB)));
|
||||
|
||||
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
||||
|
||||
/* pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +
|
||||
pIn[2 * n - 2 * i] * pBTable[2 * i] */
|
||||
outR = __SMLAD(*__SIMD32(pSrc1), *__SIMD32(pCoefA), outR) >> 15u;
|
||||
|
||||
/*
|
||||
-pIn[2 * n - 2 * i] * pBTable[2 * i + 1] +
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
|
||||
outI = __SMUADX(*__SIMD32(pSrc2)--, *__SIMD32(pCoefB));
|
||||
|
||||
/* pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] */
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
outI = __SMLSDX(*__SIMD32(pCoefA), *__SIMD32(pSrc1)++, -outI);
|
||||
|
||||
#else
|
||||
|
||||
outI = __SMLSDX(*__SIMD32(pSrc1)++, *__SIMD32(pCoefA), -outI);
|
||||
|
||||
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
||||
/* write output */
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
*__SIMD32(pDst1)++ = __PKHBT(outR, (outI >> 15u), 16);
|
||||
|
||||
#else
|
||||
|
||||
*__SIMD32(pDst1)++ = __PKHBT((outI >> 15u), outR, 16);
|
||||
|
||||
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
||||
|
||||
/* update coefficient pointer */
|
||||
pCoefB = pCoefB + (2u * modifier);
|
||||
pCoefA = pCoefA + (2u * modifier);
|
||||
|
||||
i--;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* Run the below code for Cortex-M0 */
|
||||
|
||||
i = fftLen;
|
||||
|
||||
while(i > 0u)
|
||||
{
|
||||
|
||||
/*
|
||||
outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +
|
||||
pIn[2 * n - 2 * i] * pBTable[2 * i] -
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
|
||||
*/
|
||||
|
||||
outR = *pSrc2 * *pCoefB;
|
||||
outR = outR - (*(pSrc2 + 1) * *(pCoefB + 1));
|
||||
outR = outR + (*pSrc1 * *pCoefA);
|
||||
outR = (outR + (*(pSrc1 + 1) * *(pCoefA + 1))) >> 15;
|
||||
|
||||
/*
|
||||
outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -
|
||||
pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);
|
||||
*/
|
||||
|
||||
outI = *(pSrc1 + 1) * *pCoefA;
|
||||
outI = outI - (*pSrc1 * *(pCoefA + 1));
|
||||
outI = outI - (*pSrc2 * *(pCoefB + 1));
|
||||
outI = outI - (*(pSrc2 + 1) * *(pCoefB));
|
||||
|
||||
/* update input pointers */
|
||||
pSrc1 += 2u;
|
||||
pSrc2 -= 2u;
|
||||
|
||||
/* write output */
|
||||
*pDst1++ = (q15_t) outR;
|
||||
*pDst1++ = (q15_t) (outI >> 15);
|
||||
|
||||
/* update coefficient pointer */
|
||||
pCoefB = pCoefB + (2u * modifier);
|
||||
pCoefA = pCoefA + (2u * modifier);
|
||||
|
||||
i--;
|
||||
|
||||
}
|
||||
|
||||
#endif /* #ifndef ARM_MATH_CM0 */
|
||||
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 15. February 2012
|
||||
* $Revision: V1.1.0
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_rfft_q31.c
|
||||
*
|
||||
* Description: RFFT & RIFFT Q31 process function
|
||||
*
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Version 1.1.0 2012/02/15
|
||||
* Updated with more optimizations, bug fixes and minor API changes.
|
||||
*
|
||||
* Version 1.0.10 2011/7/15
|
||||
* Big Endian support added and Merged M0 and M3/M4 Source code.
|
||||
*
|
||||
* Version 1.0.3 2010/11/29
|
||||
* Re-organized the CMSIS folders and updated documentation.
|
||||
*
|
||||
* Version 1.0.2 2010/11/11
|
||||
* Documentation updated.
|
||||
*
|
||||
* Version 1.0.1 2010/10/05
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 1.0.0 2010/09/20
|
||||
* Production release and review comments incorporated.
|
||||
*
|
||||
* Version 0.0.7 2010/06/10
|
||||
* Misra-C changes done
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Internal functions prototypes
|
||||
--------------------------------------------------------------------*/
|
||||
|
||||
void arm_split_rfft_q31(
|
||||
q31_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
q31_t * pATable,
|
||||
q31_t * pBTable,
|
||||
q31_t * pDst,
|
||||
uint32_t modifier);
|
||||
|
||||
void arm_split_rifft_q31(
|
||||
q31_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
q31_t * pATable,
|
||||
q31_t * pBTable,
|
||||
q31_t * pDst,
|
||||
uint32_t modifier);
|
||||
|
||||
/**
|
||||
* @addtogroup RFFT_RIFFT
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Processing function for the Q31 RFFT/RIFFT.
|
||||
* @param[in] *S points to an instance of the Q31 RFFT/RIFFT structure.
|
||||
* @param[in] *pSrc points to the input buffer.
|
||||
* @param[out] *pDst points to the output buffer.
|
||||
* @return none.
|
||||
*
|
||||
* \par Input an output formats:
|
||||
* \par
|
||||
* Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process.
|
||||
* Hence the output format is different for different RFFT sizes.
|
||||
* 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:
|
||||
* \par
|
||||
* \image html RFFTQ31.gif "Input and Output Formats for Q31 RFFT"
|
||||
*
|
||||
* \par
|
||||
* \image html RIFFTQ31.gif "Input and Output Formats for Q31 RIFFT"
|
||||
*/
|
||||
|
||||
void arm_rfft_q31(
|
||||
const arm_rfft_instance_q31 * S,
|
||||
q31_t * pSrc,
|
||||
q31_t * pDst)
|
||||
{
|
||||
const arm_cfft_radix4_instance_q31 *S_CFFT = S->pCfft;
|
||||
|
||||
/* Calculation of RIFFT of input */
|
||||
if(S->ifftFlagR == 1u)
|
||||
{
|
||||
/* Real IFFT core process */
|
||||
arm_split_rifft_q31(pSrc, S->fftLenBy2, S->pTwiddleAReal,
|
||||
S->pTwiddleBReal, pDst, S->twidCoefRModifier);
|
||||
|
||||
/* Complex readix-4 IFFT process */
|
||||
arm_radix4_butterfly_inverse_q31(pDst, S_CFFT->fftLen,
|
||||
S_CFFT->pTwiddle,
|
||||
S_CFFT->twidCoefModifier);
|
||||
/* Bit reversal process */
|
||||
if(S->bitReverseFlagR == 1u)
|
||||
{
|
||||
arm_bitreversal_q31(pDst, S_CFFT->fftLen,
|
||||
S_CFFT->bitRevFactor, S_CFFT->pBitRevTable);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Calculation of RFFT of input */
|
||||
|
||||
/* Complex readix-4 FFT process */
|
||||
arm_radix4_butterfly_q31(pSrc, S_CFFT->fftLen,
|
||||
S_CFFT->pTwiddle, S_CFFT->twidCoefModifier);
|
||||
|
||||
/* Bit reversal process */
|
||||
if(S->bitReverseFlagR == 1u)
|
||||
{
|
||||
arm_bitreversal_q31(pSrc, S_CFFT->fftLen,
|
||||
S_CFFT->bitRevFactor, S_CFFT->pBitRevTable);
|
||||
}
|
||||
|
||||
/* Real FFT core process */
|
||||
arm_split_rfft_q31(pSrc, S->fftLenBy2, S->pTwiddleAReal,
|
||||
S->pTwiddleBReal, pDst, S->twidCoefRModifier);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @} end of RFFT_RIFFT group
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Core Real FFT process
|
||||
* @param[in] *pSrc points to the input buffer.
|
||||
* @param[in] fftLen length of FFT.
|
||||
* @param[in] *pATable points to the twiddle Coef A buffer.
|
||||
* @param[in] *pBTable points to the twiddle Coef B buffer.
|
||||
* @param[out] *pDst points to the output buffer.
|
||||
* @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_split_rfft_q31(
|
||||
q31_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
q31_t * pATable,
|
||||
q31_t * pBTable,
|
||||
q31_t * pDst,
|
||||
uint32_t modifier)
|
||||
{
|
||||
uint32_t i; /* Loop Counter */
|
||||
q31_t outR, outI; /* Temporary variables for output */
|
||||
q31_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */
|
||||
q31_t CoefA1, CoefA2, CoefB1; /* Temporary variables for twiddle coefficients */
|
||||
q31_t *pOut1 = &pDst[2], *pOut2 = &pDst[(4u * fftLen) - 1u];
|
||||
q31_t *pIn1 = &pSrc[2], *pIn2 = &pSrc[(2u * fftLen) - 1u];
|
||||
|
||||
/* Init coefficient pointers */
|
||||
pCoefA = &pATable[modifier * 2u];
|
||||
pCoefB = &pBTable[modifier * 2u];
|
||||
|
||||
i = fftLen - 1u;
|
||||
|
||||
while(i > 0u)
|
||||
{
|
||||
/*
|
||||
outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]
|
||||
+ pSrc[2 * n - 2 * i] * pBTable[2 * i] +
|
||||
pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
|
||||
*/
|
||||
|
||||
/* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +
|
||||
pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); */
|
||||
|
||||
CoefA1 = *pCoefA++;
|
||||
CoefA2 = *pCoefA;
|
||||
|
||||
/* outR = (pSrc[2 * i] * pATable[2 * i] */
|
||||
outR = ((int32_t) (((q63_t) * pIn1 * CoefA1) >> 32));
|
||||
|
||||
/* outI = pIn[2 * i] * pATable[2 * i + 1] */
|
||||
outI = ((int32_t) (((q63_t) * pIn1++ * CoefA2) >> 32));
|
||||
|
||||
/* - pSrc[2 * i + 1] * pATable[2 * i + 1] */
|
||||
outR =
|
||||
(q31_t) ((((q63_t) outR << 32) + ((q63_t) * pIn1 * (-CoefA2))) >> 32);
|
||||
|
||||
/* (pIn[2 * i + 1] * pATable[2 * i] */
|
||||
outI =
|
||||
(q31_t) ((((q63_t) outI << 32) + ((q63_t) * pIn1++ * (CoefA1))) >> 32);
|
||||
|
||||
/* pSrc[2 * n - 2 * i] * pBTable[2 * i] */
|
||||
outR =
|
||||
(q31_t) ((((q63_t) outR << 32) + ((q63_t) * pIn2 * (-CoefA2))) >> 32);
|
||||
CoefB1 = *pCoefB;
|
||||
|
||||
/* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
|
||||
outI =
|
||||
(q31_t) ((((q63_t) outI << 32) + ((q63_t) * pIn2-- * (-CoefB1))) >> 32);
|
||||
|
||||
/* pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
|
||||
outR =
|
||||
(q31_t) ((((q63_t) outR << 32) + ((q63_t) * pIn2 * (CoefB1))) >> 32);
|
||||
|
||||
/* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
|
||||
outI =
|
||||
(q31_t) ((((q63_t) outI << 32) + ((q63_t) * pIn2-- * (-CoefA2))) >> 32);
|
||||
|
||||
/* write output */
|
||||
*pOut1++ = (outR << 1u);
|
||||
*pOut1++ = (outI << 1u);
|
||||
|
||||
/* write complex conjugate output */
|
||||
*pOut2-- = -(outI << 1u);
|
||||
*pOut2-- = (outR << 1u);
|
||||
|
||||
/* update coefficient pointer */
|
||||
pCoefB = pCoefB + (modifier * 2u);
|
||||
pCoefA = pCoefA + ((modifier * 2u) - 1u);
|
||||
|
||||
i--;
|
||||
|
||||
}
|
||||
|
||||
pDst[2u * fftLen] = pSrc[0] - pSrc[1];
|
||||
pDst[(2u * fftLen) + 1u] = 0;
|
||||
|
||||
pDst[0] = pSrc[0] + pSrc[1];
|
||||
pDst[1] = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Core Real IFFT process
|
||||
* @param[in] *pSrc points to the input buffer.
|
||||
* @param[in] fftLen length of FFT.
|
||||
* @param[in] *pATable points to the twiddle Coef A buffer.
|
||||
* @param[in] *pBTable points to the twiddle Coef B buffer.
|
||||
* @param[out] *pDst points to the output buffer.
|
||||
* @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_split_rifft_q31(
|
||||
q31_t * pSrc,
|
||||
uint32_t fftLen,
|
||||
q31_t * pATable,
|
||||
q31_t * pBTable,
|
||||
q31_t * pDst,
|
||||
uint32_t modifier)
|
||||
{
|
||||
q31_t outR, outI; /* Temporary variables for output */
|
||||
q31_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */
|
||||
q31_t CoefA1, CoefA2, CoefB1; /* Temporary variables for twiddle coefficients */
|
||||
q31_t *pIn1 = &pSrc[0], *pIn2 = &pSrc[(2u * fftLen) + 1u];
|
||||
|
||||
pCoefA = &pATable[0];
|
||||
pCoefB = &pBTable[0];
|
||||
|
||||
while(fftLen > 0u)
|
||||
{
|
||||
/*
|
||||
outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +
|
||||
pIn[2 * n - 2 * i] * pBTable[2 * i] -
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
|
||||
|
||||
outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -
|
||||
pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
|
||||
pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);
|
||||
|
||||
*/
|
||||
CoefA1 = *pCoefA++;
|
||||
CoefA2 = *pCoefA;
|
||||
|
||||
/* outR = (pIn[2 * i] * pATable[2 * i] */
|
||||
outR = ((int32_t) (((q63_t) * pIn1 * CoefA1) >> 32));
|
||||
|
||||
/* - pIn[2 * i] * pATable[2 * i + 1] */
|
||||
outI = -((int32_t) (((q63_t) * pIn1++ * CoefA2) >> 32));
|
||||
|
||||
/* pIn[2 * i + 1] * pATable[2 * i + 1] */
|
||||
outR =
|
||||
(q31_t) ((((q63_t) outR << 32) + ((q63_t) * pIn1 * (CoefA2))) >> 32);
|
||||
|
||||
/* pIn[2 * i + 1] * pATable[2 * i] */
|
||||
outI =
|
||||
(q31_t) ((((q63_t) outI << 32) + ((q63_t) * pIn1++ * (CoefA1))) >> 32);
|
||||
|
||||
/* pIn[2 * n - 2 * i] * pBTable[2 * i] */
|
||||
outR =
|
||||
(q31_t) ((((q63_t) outR << 32) + ((q63_t) * pIn2 * (CoefA2))) >> 32);
|
||||
|
||||
CoefB1 = *pCoefB;
|
||||
|
||||
/* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
|
||||
outI =
|
||||
(q31_t) ((((q63_t) outI << 32) - ((q63_t) * pIn2-- * (CoefB1))) >> 32);
|
||||
|
||||
/* pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
|
||||
outR =
|
||||
(q31_t) ((((q63_t) outR << 32) + ((q63_t) * pIn2 * (CoefB1))) >> 32);
|
||||
|
||||
/* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
|
||||
outI =
|
||||
(q31_t) ((((q63_t) outI << 32) + ((q63_t) * pIn2-- * (CoefA2))) >> 32);
|
||||
|
||||
/* write output */
|
||||
*pDst++ = (outR << 1u);
|
||||
*pDst++ = (outI << 1u);
|
||||
|
||||
/* update coefficient pointer */
|
||||
pCoefB = pCoefB + (modifier * 2u);
|
||||
pCoefA = pCoefA + ((modifier * 2u) - 1u);
|
||||
|
||||
/* Decrement loop count */
|
||||
fftLen--;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user