📄 fft.c
字号:
/****************************************************************************
** $TITLE: FFT.C$
** FFT.C
** ---------
** Brings data in from the codec, and runs it through an fft algorithm.
** the data can be plotted in real time at the host or be sent to
** oscilloscope through the codec.
**
****************************************************************************/
/*--------------------------------------------------------------------------
EXTERNAL DECLARATIONS
--------------------------------------------------------------------------*/
extern volatile int user_tx_buf[6];
extern volatile int user_tx_ready;
extern volatile int user_rx_buf[6];
extern volatile int user_rx_ready;
/*--------------------------------------------------------------------------
INCLUDES
--------------------------------------------------------------------------*/
#include <def21060.h>
#include <21065l.h>
#include <signal.h>
#include <macros.h>
#include <limits.h>
#include <trans.h>
#include <float.h>
#include <math.h>
#include <ezkit/1819regs.h>
/*--------------------------------------------------------------------------
CONSTANT & MACRO DEFINITIONS
--------------------------------------------------------------------------*/
#define PI 3.1425926
/* Codec tag word to send out left and right samples */
#define DOUT_TAG 0x9800
/* Codec tag word to send out address and data slots */
#define REGOUT_TAG 0xe000
/* This is the codec register setting for line input on both channels */
#define SOURCE_IS_LINE 0x0404
/* This is the codec register setting for mic input on both channels */
#define SOURCE_IS_MIC 0
/* interrupt SIG_SPT1I's service routine Address*/
#define CODEC_ISR_VECT 0X9001
/* Codec addreses */
#define SOURCE_ADDR 0x1a00
#define RECGAIN_ADDR 0x1c00
/* Number of sample points in the calculation */
#define NUM_POINTS 256
#define BETWEEN_SAMPLES 25000
/* The program can be in 1 of 3 modes. The other mode is a wait mode
and is anything greater than 2 */
#define SAMPLE_MODE 1
#define CALCULATE_MODE 2
/*--------------------------------------------------------------------------
GLOBAL DECLARATIONS
--------------------------------------------------------------------------*/
int mode; // mode 1 = collecting data points. mode 2 = calculating FFT
int data_count;//ADC sample Counter
int out_count;//DAC Output Counter
int window;//control the window type
float Windows[NUM_POINTS];//Windows
/* Use this array for calculating the FFT, then copy result into data[] */
int tempdata[NUM_POINTS];
float fdata[NUM_POINTS]; /* array to convertg int points to floats */
float Magnitude[NUM_POINTS];
/* The output data is stored here */
int OutputBuffer[NUM_POINTS];
/*--------------------------------------------------------------------------
FUNCTION PROTOTYPES
--------------------------------------------------------------------------*/
void main (void);
void sample_codec( void );
void init_codec( void );
/****************************************************************************
** Procedure: sample_codec()
**
** Arguments: None
**
** Returns: None
**
** Desc: Gets data in from the codec and sends the output buffer to the codec.
** If mode = SAMPLE_MODE, 128 consecutive samples are taken from the
** codec for calculating the FFT.
**
****************************************************************************/
void sample_codec( void )
{
// Copy output buffers to transmit data buffers.
user_tx_buf[LEFT_CHANL] = OutputBuffer[out_count];
user_tx_buf[RIGHT_CHNL] = OutputBuffer[out_count];
out_count++;
if(out_count>=NUM_POINTS) out_count=0;
user_tx_buf[TAG] = DOUT_TAG;
user_tx_ready = 1;
/* Put this sample in the array if we're in sample mode */
if( mode == SAMPLE_MODE )
{
tempdata[data_count] = user_rx_buf[LEFT_CHANL];
data_count++;
/* If we have 256 samples, stop sampling and calculate */
if( data_count >= 256 )
{
data_count = 0;
mode = CALCULATE_MODE;
}
}
}
/****************************************************************************
**
** Procedure: init_codec()
**
** Arguments: None
**
** Returns: None
**
** Desc: Turns on the codec interrupt then initializes the codec
** source and record gain.
**
****************************************************************************/
void init_codec( void )
{
asm("#include <def21065l.h>");
interrupt(SIG_SPT1I,(void (*)(int))CODEC_ISR_VECT);
asm("BIT SET IMASK SPT1I;"); /* unmasks sport interrupt */
/* Set source to LINE */
user_tx_buf[TAG] = REGOUT_TAG;
user_tx_buf[ADDR] = SOURCE_ADDR;
user_tx_buf[DATA] = SOURCE_IS_LINE;
user_tx_ready = 1;
idle(); /* Wait for codec register to get set */
idle();
/* Set record gain */
user_tx_buf[TAG] = REGOUT_TAG;
user_tx_buf[ADDR] = RECGAIN_ADDR;
user_tx_buf[DATA] = 0;
user_tx_ready = 1;
idle(); /* Wait for codec register to get set */
idle();
return;
}
/****************************************************************************
**
** Procedure: main()
**
** Arguments: None
**
** Returns: None
**
** Desc: Sets everything up and then goes into its sampling and
** processing loop.
**
****************************************************************************/
void main ( void )
{
int i; /* counter variable */
int cntr; /* counter variable */
float fmin, fmax;
float range;
float i_output[NUM_POINTS]; /* Imaginary part of FFT */
float r_output[NUM_POINTS]; /* Real part of FFT */
int *optr;
float *fptr, *rptr, *iptr;
float favg;
int offset;
float scale_value;
window = 0;
fmin = FLT_MAX; /* make sure the min is updated the first time */
fmax = FLT_MIN; /* make sure the max is updated the first time */
data_count = 0;
out_count = 0;
mode = SAMPLE_MODE; /* Start with the first 128 samples */
init_codec(); /* Set up codec for line in */
if(window) {for(i=0;i<NUM_POINTS;i++) Windows[i]=0.54-0.46*cos(2*PI*i/(NUM_POINTS-1));}
else {for(i=0;i<NUM_POINTS;i++) Windows[i]=1.0;}
for(;;) /* Start the sample/calculate/wait loop */
{
/* Just after accumulating the 128 points, calculate the FFT */
if( mode == CALCULATE_MODE )
{
for( i=0 ; i<NUM_POINTS ; i++ )
fdata[i] =(float)tempdata[i]*Windows[i];
offset = 50;
scale_value = 25.0;
/* do FFT.*/
rfft256( fdata, r_output, i_output );
/* do Magnitude*/
fptr = Magnitude;
rptr = r_output;
iptr = i_output;
for( i=0 ; i<NUM_POINTS ; i++ )
{
*fptr = *rptr * *rptr + *iptr * *iptr;
fptr++;
iptr++;
rptr++;
}
/*Scale initialize*/
fmin = FLT_MAX;
fmax = FLT_MIN;
/* log Scale*/
fptr = Magnitude;
for( i=0 ; i<NUM_POINTS ; i++ )
{
if( *fptr < 0.0 )
*fptr = -logf( -*fptr );
else
*fptr = logf( *fptr );
fptr++;
}
/* search the array's max and min to scale*/
favg = 0;
fptr = &Magnitude[0];
for( i=0 ; i<NUM_POINTS ; i++ )
{
fmax = fmax > *fptr ? fmax : *fptr;
fmin = fmin < *fptr ? fmin : *fptr;
favg += *fptr;
fptr++;
}
favg /= (NUM_POINTS - 2);
range = fmax - favg;
optr = OutputBuffer;
fptr = Magnitude;
for( i=0 ; i<NUM_POINTS ; i++ )
{
*optr++ = (offset + (int)(scale_value * ( (*fptr++ - favg) / range )))*100;
}
OutputBuffer[0]=16383;//set trigger
}
/* don't calculate the FFT every 256 samples*/
if (mode >= CALCULATE_MODE)
{
mode++;
if (mode >= BETWEEN_SAMPLES)
{
mode = SAMPLE_MODE;
}
}
user_rx_ready = 1; /* Tell codec isr we're ready for data */
while(user_rx_ready) idle(); /* Wait for codec data */
sample_codec(); /* Get data */
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -