#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