#include <arm_math.h>
#include <arm_const_structs.h>
arm_cfft_radix4_instance_f32 fft_inst; // instantiate (deprecated but works)
// define buffer size
#define datalen (1024 * 4) // expression needs to be in parentheses!
#define FFT_SIZE datalen
#define NUMBITS 16
#define Vref 2.5000
#define vbit Vref/powf(2.000f, NUMBITS)
volatile uint32_t data[datalen]; // set up a buffer for our ADC
volatile uint32_t datapointer = 0; // pointer into data[]
float fftbuf[2*FFT_SIZE];
float outbuf[FFT_SIZE]; // where the fft in dBs ends up
float weight[FFT_SIZE]; // holder for the window coefficients
float twoPi = 6.28318531f;
float fourPi =12.56637061f;
float sixPi = 18.84955592f;
void calcBlackmanHarrisWindow(uint16_t fftsize) {
float volatile ratio;
float a0, a1, a2, a3, f1;
a0 = 0.35875f; a1 = 0.48829f; a2 = 0.14128f; a3 = 0.01168f;
f1 = ((float) fftsize);
for (int i=0; i<fftsize; i++) {
ratio = ((float)i)/f1; // from Wikipedia Windows
weight[i] = a0 -a1*cosf(twoPi*ratio) +a2*cosf(fourPi*ratio) -a3*cosf(sixPi*ratio); }
}
// Instantiate an arm fft instance - fwd, with no bit reversal 0,1
arm_cfft_radix4_init_f32( &fft_inst, FFT_SIZE, 0, 1);
memset(fftbuf, 0, sizeof(fftbuf)); // clear fft buffer memory
calcBlackmanHarrisWindow(FFT_SIZE); // window function returns values in variable "weight"
// collect ADC samples into data[], compute float average, when complete, then
Serial.println("Start of FFT processing");
Serial.printf("FFT_SIZE = %i\r\n", datalen);
// Do an FFT here
// fftbuf is 2x bigger than datalen, due to imaginary part
// data is stored as re[0], im[0], re[1], im[1], ... re[N-1], im[N-1]
// First convert data to float subtract the mean and put in the even mem locations
for (int i = 0; i<datalen; i++) {
fftbuf[2*i] = ((float) data[i] * vbit) - average; // convert counts in data to volts and remove mean
fftbuf[2*i+1] = 0.0f; // imaginary part is zero
fftbuf[2*i] *= weight[i];
}
Serial.println("Finished putting into fftbuf");
arm_cfft_radix4_f32( &fft_inst, fftbuf ); // do the fft in place
Serial.println("Finished FFT");
arm_cmplx_mag_squared_f32( fftbuf, outbuf, FFT_SIZE/2 ); // mag squared
Serial.println("Finished mag squared");
for( int i = 0; i < FFT_SIZE/2; i++) {
outbuf[i] = 10.0f*log10f(outbuf[i]); // use 10 log, since mag sq is power
}
Serial.println("Computed dBs");
int k = 8; // print 8 samples per line
for( int i=0; i<FFT_SIZE/2/k; i++) {
for( int j=0; j<k; j++) {
Serial.print( outbuf[i+j]), Serial.print(", ");
}
Serial.println(); // every 8 samples a carriage return, we get 1 extra comma, but that's easy to edit out!
}