// Prototyping sketch for quadrature spectrum analyzer using complex "grabber"
// Creates a pair of quadrature sinusoids, grabs complex blocks of 256 samples, windows and uses
// arm_math fft, reorders the data, computes the log_2 of magsq, smooths the results with first-order IIR filter,
// and displays spectrum -22.05kHz to +22.05kHz on graphics board.
// Derek Rowell July 2016
//
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include "grabber_complex_256.h"
#include "sdrMath.h"
const int myInput = AUDIO_INPUT_LINEIN;
//
AudioInputI2S audioInput;
AudioSynthWaveformSine I_input1; // quadrature sinusoid 1
AudioSynthWaveformSine Q_input1;
AudioSynthWaveformSine I_input2; // quadrature sinusoid 2
AudioSynthWaveformSine Q_input2;
AudioMixer4 mixer1;
AudioMixer4 mixer2;
AudioGrabberComplex256 myData;
//
AudioConnection c1(I_input1, 0, mixer1, 0);
AudioConnection c2(I_input2, 0, mixer1, 1);
AudioConnection c3(Q_input1, 0, mixer2, 0);
AudioConnection c4(Q_input2, 0, mixer2, 1);
AudioConnection c5(mixer1, 0, myData, 0);
AudioConnection c6(mixer2, 0, myData, 1);
AudioControlSGTL5000 audioShield;
//
arm_cfft_radix2_instance_q15 myFFT;
int16_t FFTbuffer[512];
int16_t log2Mag[256];
//----------------------------------------------------------------------------
void setup() {
Serial.begin(57600);
delay(2000);
audioShield.enable();
AudioMemory(12);
audioShield.volume(0.5);
audioShield.inputSelect(myInput);
//
uint16_t Frequency1 = 19000; float Amplitude1 = 0.6;
uint16_t Frequency2 = 18000; float Amplitude2 = 0.6/8.0; // log difference should be 3
AudioNoInterrupts(); // Set up a pair of quadrature sinusoids
mixer1.gain(0, 1.0); mixer1.gain(1, 1.0);
mixer2.gain(0, 1.0); mixer2.gain(1, 1.0);
I_input1.frequency(Frequency1); I_input1.amplitude(Amplitude1); I_input1.phase(45);
Q_input1.frequency(Frequency1); Q_input1.amplitude(Amplitude1); Q_input1.phase(315);
I_input2.frequency(Frequency2); I_input2.amplitude(Amplitude2); I_input2.phase(0);
Q_input2.frequency(Frequency2); Q_input2.amplitude(Amplitude2); Q_input2.phase(90);
AudioInterrupts();
//
arm_cfft_radix2_init_q15(&myFFT, 256, 0, 1); // Initialize the complex FFT function
windowComplex256_16(FFTbuffer, HAMMING); // Create a Hamming data window
}
//----------------------------------------------------------------------------------
void loop() {
myData.grab(FFTbuffer); // "grab" a 256 complex sample buffer
windowComplex256_16(FFTbuffer, APPLY); // apply a Hamming window function
arm_cfft_radix2_q15(&myFFT, FFTbuffer); // Use arm_math complex FFT
for (int i=0; i<256; i++) {
int16_t Re = FFTbuffer[2*i];
int16_t Im = FFTbuffer[2*i+1];
uint32_t magsq = (Re*Re + Im*Im)>>12;
log2Mag[i] = fastLog2_32(magsq)>>1; // log(x^2) = 2log(x)
}
FFTshift_16(log2Mag, 256); // Reorder the +ve and -ve frequencies
smoothVector(log2Mag, 256, (uint16_t)(0.8*16384));
displaySpectrum(log2Mag, 256);
delay(10);
}