#ifndef _FPU_RFFT_H_
#define _FPU_RFFT_H_
//#############################################################################
//! \file include/fpu_rfft.h
//!
//! \brief Prototypes and Definitions for the C28x FPU Library
//! \author Vishal Coelho
//! \date n/a
//
// HISTORY
//+--------+--------+---------------------------------------------------------+
//|DATE | AUTHOR | CHANGE |
//+--------+--------+---------------------------------------------------------+
//|04/06/17|V.C. | Added RFFT_adc_f32_win |
//+-----+--------+------------------------------------------------------------+
//
// Group: C2000
// Target Family: F2837x
//
//#############################################################################
//
//
// $Copyright: Copyright (C) 2022 Texas Instruments Incorporated -
// http://www.ti.com/ ALL RIGHTS RESERVED $
//#############################################################################
//*****************************************************************************
// includes
//*****************************************************************************
#include "fpu_types.h"
//!
//! \defgroup DSP_RFFT_F32 Real Fast Fourier Transforms
//!
//! \ingroup DSP_RFFT_F32
// @{
#ifdef __cplusplus
extern "C" {
#endif
//*****************************************************************************
// typedefs
//*****************************************************************************
//! \brief Structure for the Real FFT
//!
typedef struct {
float *InBuf; //!< Pointer to the input buffer
float *OutBuf; //!< Pointer to the output buffer
float *CosSinBuf; //!< Pointer to the twiddle factors
float *MagBuf; //!< Pointer to the magnitude buffer
float *PhaseBuf; //!< Pointer to the phase buffer
uint16_t FFTSize; //!< Size of the FFT (number of real data points)
uint16_t FFTStages; //!< Number of FFT stages
} RFFT_F32_STRUCT;
//! \brief Handle to the Real FFT object
//!
typedef RFFT_F32_STRUCT* RFFT_F32_STRUCT_Handle;
//! \brief Structure for the Real FFT with ADC input
//!
typedef struct {
uint16_t *InBuf; //!< Pointer to the input buffer
void *Tail; //!< Null pointer to the OutBuf of RFFT_F32_STRUCT
} RFFT_ADC_F32_STRUCT;
//! \brief Handle to the Real FFT (with ADC input) structure
//!
typedef RFFT_ADC_F32_STRUCT* RFFT_ADC_F32_STRUCT_Handle;
//*****************************************************************************
// globals
//*****************************************************************************
//
//! \brief Twiddle Factor Table for a 2048-pt (max) Real FFT
//!
//! Note:
//! 1. RFFT_f32_twiddleFactors name is deprecated and only supported for
//! legacy reasons. Users are encouraged to use FPU32RFFTtwiddleFactors
//! as the table symbol.
//! 2. The RFFT_f32_twiddleFactors is an alias for the new table. It is not
//! a separate table.
//
//*****************************************************************************
extern float RFFT_f32_twiddleFactors[1020];
extern float FPU32RFFTtwiddleFactors[1020];
//*****************************************************************************
// 'inline' function
//*****************************************************************************
//! \brief Set the input buffer pointer
//! \param[in] fh handle to the 'RFFT_F32_STRUCT' object
//! \param[in] pi pointer to the input buffer
//!
static inline void RFFT_f32_setInputPtr(RFFT_F32_STRUCT_Handle fh,
const float *pi)
{
fh->InBuf = (float *)pi;
}
//! \brief Get the input buffer pointer
//! \param[in] fh handle to the 'RFFT_F32_STRUCT' object
//! \return pi pointer to the input buffer
//!
static inline float * RFFT_f32_getInputPtr(RFFT_F32_STRUCT_Handle fh)
{
return(fh->InBuf);
}
//! \brief Set the output buffer pointer
//! \param[in] fh handle to the 'RFFT_F32_STRUCT' object
//! \param[in] po pointer to the output buffer
//!
static inline void RFFT_f32_setOutputPtr(RFFT_F32_STRUCT_Handle fh,
const float *po)
{
fh->OutBuf= (float *)po;
}
//! \brief Get the output buffer pointer
//! \param[in] fh handle to the 'RFFT_F32_STRUCT' object
//! \return po pointer to the output buffer
//!
static inline float * RFFT_f32_getOutputPtr(RFFT_F32_STRUCT_Handle fh)
{
return(fh->OutBuf);
}
//! \brief Set the twiddles pointer
//! \param[in] fh handle to the 'RFFT_F32_STRUCT' object
//! \param[in] pt pointer to the twiddles
//!
static inline void RFFT_f32_setTwiddlesPtr(RFFT_F32_STRUCT_Handle fh,
const float *pc)
{
fh->CosSinBuf = (float *)pc;
}
//! \brief Get the twiddles pointer
//! \param[in] fh handle to the 'RFFT_F32_STRUCT' object
//! \return pt pointer to the twiddles
//!
static inline float * RFFT_f32_getTwiddlesPtr(RFFT_F32_STRUCT_Handle fh)
{
return(fh->CosSinBuf);
}
//! \brief Set the magnitude buffer pointer
//! \param[in] fh handle to the 'RFFT_F32_STRUCT' object
//! \param[in] pm pointer to the magnitude buffer
//!
static inline void RFFT_f32_setMagnitudePtr(RFFT_F32_STRUCT_Handle fh,
const float *pm)
{
fh->MagBuf = (float *)pm;
}
//! \brief Get the magnitude buffer pointer
//! \param[in] fh handle to the 'RFFT_F32_STRUCT' object
//! \return pm pointer to the magnitude buffer
//!
static inline float * RFFT_f32_getMagnitudePtr(RFFT_F32_STRUCT_Handle fh)
{
return(fh->MagBuf);
}
//! \brief Set the phase buffer pointer
//! \param[in] fh handle to the 'RFFT_F32_STRUCT' object
//! \param[in] pp pointer to the phase buffer
//!
static inline void RFFT_f32_setPhasePtr(RFFT_F32_STRUCT_Handle fh,
const float *pp)
{
fh->PhaseBuf = (float *)pp;
}
//! \brief Get the phase buffer pointer
//! \param[in] fh handle to the 'RFFT_F32_STRUCT' object
//! \return pp pointer to the phase buffer
//!
static inline float * RFFT_f32_getPhasePtr(RFFT_F32_STRUCT_Handle fh)
{
return(fh->PhaseBuf);
}
//! \brief Set the number of FFT stages
//! \param[in] fh handle to the 'RFFT_F32_STRUCT' object
//! \param[in] st number of FFT stages
//!
static inline void RFFT_f32_setStages(RFFT_F32_STRUCT_Handle fh,
const uint16_t st)
{
fh->FFTStages = st;
}
//! \brief Get the size of the FFT
//! \param[in] fh handle to the 'RFFT_F32_STRUCT' object
//! \return st number of FFT stages
//!
static inline uint16_t RFFT_f32_getStages(RFFT_F32_STRUCT_Handle fh)
{
return(fh->FFTStages);
}
//! \brief Set the number of FFT stages
//! \param[in] fh handle to the 'RFFT_F32_STRUCT' object
//! \param[in] sz size of the FFT
//!
static inline void RFFT_f32_setFFTSize(RFFT_F32_STRUCT_Handle fh,
const uint16_t sz)
{
fh->FFTSize = sz;
}
//! \brief Get the size of the FFT
//! \param[in] fh handle to the 'RFFT_F32_STRUCT' object
//! \return sz size of the FFT
//!
static inline uint16_t RFFT_f32_getFFTSize(RFFT_F32_STRUCT_Handle fh)
{
return(fh->FFTSize);
}
//! \brief Set the input buffer pointer
//! \param[in] fh handle to the 'RFFT_ADC_F32_STRUCT' object
//! \param[in] pi pointer to the input buffer
//!
static inline void RFFT_ADC_f32_setInBufPtr(RFFT_ADC_F32_STRUCT_Handle fh,
const uint16_t * pi)
{
fh->InBuf = (uint16_t *)pi;
}
//! \brief get the input buffer pointer
//! \param[in] fh handle to the 'RFFT_ADC_F32_STRUCT' object
//! \return pi pointer to the input buffer
//!
static inline uint16_t *RFFT_ADC_f32_getInBufPtr(RFFT_ADC_F32_STRUCT_Handle fh)
{
return(fh->InBuf);
}
//! \brief Set the tail pointer
//! \param[in] fh handle to the 'RFFT_ADC_F32_STRUCT' object
//! \param[in] pt pointer to the tail
//!
static inline void RFFT_ADC_f32_setTailPtr(RFFT_ADC_F32_STRUCT_Handle fh,
const void * pt)
{
fh->Tail = (void *)pt;
}
//! \brief Get the tail pointer
//! \param[in] fh handle to the 'RFFT_ADC_F32_STRUCT' object
//! \return pt pointer to the tail
//!
static inline void *RFFT_ADC_f32_getTailPtr(RFFT_ADC_F32_STRUCT_Handle fh)
{
return(fh->Tail);
}
//*****************************************************************************
// function prototypes
//*****************************************************************************
//! \brief Real Fast Fourier Transform (RFFT).
//!
//! This routine computes the 32-bit floating-point FFT for an N-pt
//! (\f$ N = 2^{n}, n = 5 : 10\f$)
//! This routine computes the 32-bit single precision FFT for an N-pt
//! (\f$ N = 2^{n}, n = 5 : 10\f$) real input. This function reorders
//! the input in bit-reversed format as part of the stage 1,2 and 3
//! computations. The routine uses two buffers in ping-pong fashion i.e. after
//! each FFT stage the output and input buffers become the input and output
//! buffers respectively for the next stage.
//! This algorithm only allocates memory, and performs computation, for the
//! non-zero elements of the input (the real part). The complex conjugate
//! nature of the spectrum (for real only data) affords savings in space
//! and computaion, therefore the algorithm only calculates the spectrum from
//! the 0th bin to the nyquist bin (included).
//!
//! Another approach to calculate the real FFT would be to treat the real
//! N-point data as N/2 complex, run the forward complex N/2 point FFT
//! followed by an "unpack" function
//!
//! \param hndRFFT_F32 Pointer to the RFFT_F32 object
//! \attention
//! -# The routine requires the use of two buffers, each of size N (32-bit
//! float), for computation; the input buffer must be aligned to a memory
//! address of 2N words (16-bit). Refer to the RFFT linker command file to see
//! an example of this.
//! -# If alignment is not possible the user can use the alternative, albeit
//! slower, function RFFT_f32u
//! \sa \ref SSEC_RFFT_F32_USING_CFFT_F32
//!
//!
//! Performance Data
//! Samples | Cycles
//! |
---|
64 | 1281
//! |
128 | 2779
//! |
256 | 6149
//! |
512 | 13674
//! |
1024 | 30356
//! |
//
extern void RFFT_f32(RFFT_F32_STRUCT_Handle hndRFFT_F32);
//! \brief Real FFT (Unaligned).
//!
//! This routine computes the 32-bit single precision FFT for an N-pt
//! (\f$ N = 2^{n}, n = 5 : 10\f$) real input. This function reorders
//! the input in bit-reversed format as part of the stage 1,2 and 3
//! computations. The routine uses two buffers in ping-pong fashion i.e. after
//! each FFT stage the output and input buffers become the input and output
//! buffers respectively for the next stage.
//! This algorithm only allocates memory, and performs computation, for the
//! non-zero elements of the input (the real part). The complex conjugate
//! nature of the spectrum (for real only data) affords savings in space
//! and computaion, therefore the algorithm only calculates the spectrum from
//! the 0th bin to the nyquist bin (included).
//!
//! Another approach to calculate the real FFT would be to treat the real
//! N-point data as N/2 complex, run the forward complex N/2 point FFT
//! followed by an "unpack" function
//!
//! \param hndRFFT_F32 Pointer to the RFFT_F32 object
//! \attention
//! -# The routine requires the use of two buffers, each of size N (32-bit
//! float), for computation; the input buffer need not be aligned to a boundary
//! -# If alignment is possible it is recommended to use the faster routine,
//! RFFT_f32
//! \sa \ref SSEC_RFFT_F32_USING_CFFT_F32
//!
//!
//! Performance Data
//! Samples | Cycles
//! |
---|
64 | 1393
//! |
128 | 3003
//! |
256 | 6597
//! |
512 | 14570
//! |
1024 | 32148
//! |
//
extern void RFFT_f32u(RFFT_F32_STRUCT_Handle hndRFFT_F32);
//! \brief Real FFT with ADC Input.
//!
//! This routine computes the 32-bit single precision FFT for an N-pt
//! (\f$ N = 2^{n}, n = 5 : 10\f$) real 12-bit ADC input. This function
//! reorders the input in bit-reversed format as part of the stage 1,2 and 3
//! computations. The routine uses two buffers in ping-pong fashion i.e. after
//! each FFT stage the output and input buffers become the input and output
//! buffers respectively for the next stage.
//! This algorithm only allocates memory, and performs computation, for the
//! non-zero elements of the input (the real part). The complex conjugate
//! nature of the spectrum (for real only data) affords savings in space
//! and computaion, therefore the algorithm only calculates the spectrum from
//! the 0th bin to the nyquist bin (included).
//!
//! Another approach to calculate the real FFT would be to treat the real
//! N-point data as N/2 complex, run the forward complex N/2 point FFT
//! followed by an "unpack" function
//!
//! \param hndRFFT_ADC_F32 Pointer to the RFFT_ADC F32 object
//! \attention
//! -# The routine requires the use of two buffers, the input of size 2N
//! and type uint16_t, the output of size N and type float, for
//! computation; the input buffer must be aligned to a memory
//! address of N words (16-bit). Refer to the RFFT linker command file to
//! see an example of this.
//! -# If alignment is not possible the user can use the alternative, albeit
//! slower, function RFFT_adc_f32u
//!
//!
//! Performance Data
//! Samples | Cycles
//! |
---|
64 | 1295
//! |
128 | 2769
//! |
256 | 6059
//! |
512 | 13360
//! |
1024 | 29466
//! |
//
extern void RFFT_adc_f32(RFFT_ADC_F32_STRUCT_Handle hndRFFT_ADC_F32);
//! \brief Real FFT with ADC Input (Unaligned).
//!
//! This routine computes the 64-bit double precision FFT for an N-pt
//! (\f$ N = 2^{n}, n = 5 : 10\f$) real 12-bit ADC input. This function
//! reorders the input in bit-reversed format as part of the stage 1,2 and 3
//! computations. The routine uses two buffers in ping-pong fashion i.e. after
//! each FFT stage the output and input buffers become the input and output
//! buffers respectively for the next stage.
//! This algorithm only allocates memory, and performs computation, for the
//! non-zero elements of the input (the real part). The complex conjugate
//! nature of the spectrum (for real only data) affords savings in space
//! and computaion, therefore the algorithm only calculates the spectrum from
//! the 0th bin to the nyquist bin (included).
//!
//! Another approach to calculate the real FFT would be to treat the real
//! N-point data as N/2 complex, run the forward complex N/2 point FFT
//! followed by an "unpack" function
//!
//! \param hndRFFT_ADC_F32 Pointer to the RFFT_ADC F32 object
//! \attention
//! -# The routine requires the use of two buffers, the input of size 2N
//! and type uint16_t, the output of size N and type float, for
//! computation; the input buffer need not be aligned to any boundary.
//! -# If alignment is possible it is recommended to use the faster function
//! RFFT_adc_f32
//!
//!
//! Performance Data
//! Samples | Cycles
//! |
---|
64 | 1415
//! |
128 | 3009
//! |
256 | 6539
//! |
512 | 14320
//! |
1024 | 31386
//! |
//
extern void RFFT_adc_f32u(RFFT_ADC_F32_STRUCT_Handle hndRFFT_ADC_F32);
//! \brief Windowing function for the 32-bit real FFT
//! \param pBuffer pointer to the buffer that needs to be windowed
//! \param pWindow pointer to the windowing table
//! \param size size of the buffer
//! This function applies the window to a 2N point real data buffer that
//! has not been reordered in the bit-reversed format
//!
//!
//! Performance Data
//! Samples | Cycles
//! |
---|
64 | 308
//! |
128 | 596
//! |
256 | 1172
//! |
512 | 2324
//! |
1024 | 4628
//! |
//
extern void RFFT_f32_win(float *pBuffer, const float *pWindow,
const uint16_t size);
//! \brief Windowing function for the 32-bit real FFT with ADC Input
//! \param pBuffer pointer to the uint16_t buffer that needs to be windowed
//! \param pWindow pointer to the float windowing table
//! \param size size of the buffer
//! This function applies the window to a 2N point real data buffer that
//! has not been reordered in the bit-reversed format
//! \attention
//! -# The routine requires the window to be unsigned int (16-bit). The
//! user must take the desired floating point window from the header files
//! (e.g. HANN1024 from fpu32/fpu_fft_hann.h)and convert it to Q16 by
//! multiplying by 2^16 and then flooring the value before converting it to
//! uint16_t
//!
//!
//! Performance Data
//! Samples | Cycles
//! |
---|
64 | 346
//! |
128 | 666
//! |
256 | 1306
//! |
512 | 2586
//! |
1024 | 5146
//! |
//
extern void RFFT_adc_f32_win(uint16_t *pBuffer, const uint16_t *pWindow,
const uint16_t size);
//! \brief Real FFT Magnitude.
//!
//! This module computes the real FFT magnitude. The output from RFFT_f32_mag
//! matches the magnitude output from the FFT found in common mathematics
//! software and Code Composer Studio FFT graphs.
//! If instead a normalized magnitude like that performed by the fixed-point
//! TMS320C28x IQmath FFT library is required, then the RFFT_f32s_mag
//! function can be used. In fixed-point algorithms scaling is performed to
//! avoid overflowing data. Floating-point calculations do not need this
//! scaling to avoid overflow and therefore the RFFT_f32_mag function can be
//! used instead.
//! \param hndRFFT_F32 Pointer to the RFFT_F32 object
//! \attention
//! -# The Magnitude buffer does not require memory alignment to a boundary
//! -# For C28x devices that have the TMU0 (or higher) module, use
//! RFFT_f32_mag_TMU0() instead for better performance.
//!
//!
//! Performance Data
//! Samples | Cycles
//! |
---|
64 | 635
//! |
128 | 1243
//! |
256 | 2459
//! |
512 | 4888
//! |
1024 | 9752
//! |
//
extern void RFFT_f32_mag(RFFT_F32_STRUCT_Handle hndRFFT_F32);
//! \brief Real FFT Magnitude (Scaled).
//!
//! This module computes the scaled real FFT magnitude. The scaling is
//! \f$\frac{1}{[2^{FFT\_STAGES-1}]}\f$, and is done to match the
//! normalization performed by the fixed-point TMS320C28x IQmath FFT library
//! for overflow avoidance. Floating-point calculations do not need this
//! scaling to avoid overflow and therefore the RFFT_f32_mag function can be
//! used instead. The output from RFFT_f32s_mag matches the magnitude
//! output from the FFT found in common mathematics software and Code Composer
//! Studio FFT graphs.
//! \param hndRFFT_F32 Pointer to the RFFT_F32 object
//! \attention
//! -# The Magnitude buffer does not require memory alignment to a boundary
//! -# For C28x devices that have the TMU0 (or higher) module, use
//! RFFT_f32s_mag_TMU0() instead for better performance.
//!
//!
//! Performance Data
//! Samples | Cycles
//! |
---|
64 | 723
//! |
128 | 1336
//! |
256 | 2557
//! |
512 | 4990
//! |
1024 | 9859
//! |
//
extern void RFFT_f32s_mag(RFFT_F32_STRUCT_Handle hndRFFT_F32);
//! \brief Real FFT Phase.
//!
//! \param hndRFFT_F32 Pointer to the RFFT_F32 object
//! \attention
//! -# The Phase buffer does not require memory alignment to a boundary
//! -# For C28x devices that have the TMU0 (or higher) module, use
//! RFFT_f32_phase_TMU0() instead for better performance.
//!
//!
//! Performance Data
//! Samples | Cycles
//! |
---|
64 | 1949
//! |
128 | 3933
//! |
256 | 7901
//! |
512 | 16835
//! |
1024 | 31707
//! |
//
extern void RFFT_f32_phase(RFFT_F32_STRUCT_Handle hndRFFT_F32);
#if defined(__TMS320C28XX_TMU__)
//! \brief Real FFT Magnitude using the TMU0 module.
//!
//! This module computes the real FFT magnitude. The output from RFFT_f32_mag
//! matches the magnitude output from the FFT found in common mathematics
//! software and Code Composer Studio FFT graphs.
//! If instead a normalized magnitude like that performed by the fixed-point
//! TMS320C28x IQmath FFT library is required, then the RFFT_f32s_mag
//! function can be used. In fixed-point algorithms scaling is performed to
//! avoid overflowing data. Floating-point calculations do not need this
//! scaling to avoid overflow and therefore the RFFT_f32_mag function can be
//! used instead.
//! \param hndRFFT_F32 Pointer to the RFFT_F32 object
//! \attention
//! -# The Magnitude buffer does not require memory alignment to a boundary
//! -# This function requires a C28x device with TMU0 or higher module.
//! For devices without the TMU, use RFFT_f32_mag() instead.
//!
//!
//! Performance Data
//! Samples | Cycles
//! |
---|
64 | 161
//! |
128 | 289
//! |
256 | 545
//! |
512 | 1055
//! |
1024 | 2079
//! |
//
extern void RFFT_f32_mag_TMU0(RFFT_F32_STRUCT_Handle hndRFFT_F32);
//! \brief Real FFT Magnitude using the TMU0 module (Scaled).
//!
//! This module computes the scaled real FFT magnitude. The scaling is
//! \f$\frac{1}{[2^{FFT\_STAGES-1}]}\f$, and is done to match the
//! normalization performed by the fixed-point TMS320C28x IQmath FFT library
//! for overflow avoidance. Floating-point calculations do not need this
//! scaling to avoid overflow and therefore the RFFT_f32_mag function can be
//! used instead. The output from RFFT_f32s_mag matches the magnitude
//! output from the FFT found in common mathematics software and Code Composer
//! Studio FFT graphs.
//! \param hndRFFT_F32 Pointer to the RFFT_F32 object
//! \attention
//! -# The Magnitude buffer does not require memory alignment to a boundary
//! -# This function requires a C28x device with TMU0 or higher module.
//! For devices without the TMU, use RFFT_f32s_mag() instead.
//!
//!
//! Performance Data
//! Samples | Cycles
//! |
---|
64 | 268
//! |
128 | 466
//! |
256 | 856
//! |
512 | 1375
//! |
1024 | 2661
//! |
//
extern void RFFT_f32s_mag_TMU0(RFFT_F32_STRUCT_Handle hndRFFT_F32);
//! \brief Real FFT Phase using TMU0 module.
//!
//! \param hndRFFT_F32 Pointer to the RFFT_F32 object
//! \attention
//! -# The Phase buffer does not require memory alignment to a boundary
//! -# This function requires a C28x device with TMU0 or higher module.
//! For devices without the TMU, use RFFT_f32_phase() instead.
//!
//!
//! Performance Data
//! Samples | Cycles
//! |
---|
64 | 279
//! |
128 | 535
//! |
256 | 1047
//! |
512 | 2068
//! |
1024 | 4116
//! |
//
extern void RFFT_f32_phase_TMU0(RFFT_F32_STRUCT_Handle hndRFFT_F32);
#endif //__TMS320C28XX_TMU__
//! \brief Generate twiddle factors for the Real FFT.
//!
//! \param hndRFFT_F32 Pointer to the RFFT_F32 object
//! \attention This function is written in C and compiled without optimization
//! turned on.
//
extern void RFFT_f32_sincostable(RFFT_F32_STRUCT_Handle hndRFFT_F32);
// @} //addtogroup
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif // - end of _FPU_RFFT_H_
// End of File