//#include <SPI.h>
#include <Adafruit_GFX.h> // graphics library for display
#include <Adafruit_SSD1306.h> // SSD1306 OLED display library
#include <SD.h> // SD card library
#include "fix_fft.h" // fixed point Fast Fourier Transform library
//#include "TMRpcm.h" // For reading WAV audio files
#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else // __ARM__
extern char *__brkval;
#endif // __arm__
#define OLED_RESET -1 // OLED library likes to see this but it isn't used here with I2C
#define OLED_ADDR 0x3C // OLED I2C address
#define audioIn A0 // audio input port
#define CS_PIN 10 // sd card setup
File root;
Adafruit_SSD1306 display(OLED_RESET); // create instance of OLED display
//TMRpcm audio;
void setup() {
// or 3.3 volts (on 3.3V Arduino boards)
Serial.begin(9600);
Serial.print("Initializing SD card... ");
if (!SD.begin(CS_PIN)) {
Serial.println("Card initialization failed!");
while (true);
}
Serial.println("INIT DONE");
/*
Serial.println("Files in the card:");
root = SD.open("/");
printDirectory(root, 0);
Serial.println("FINISHED SETUP");*/
printfreeMem(0);
/*
// Example of reading file from the card:
File textFile = SD.open("README.txt");
if (textFile) {
Serial.print("README.txt: ");
while (textFile.available()) {
Serial.write(textFile.read());
}
textFile.close();
} else {
Serial.println("error opening README.txt!");
}*/
// use the default analog reference of 5 volts (on 5V Arduino boards)
printfreeMem(1);
// initialize OLED display with address 0x3C for 128x64
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial.println(F("SSD1306 allocation failed"));
while (true);
}
delay(2000); // wait for initializing
display.clearDisplay(); // blank the display
display.setTextSize(1); // configure text properties
display.setTextColor(WHITE);
analogReference(DEFAULT);
//audio.speakerPin = 0; // set speaker output to pin 9
//audio.setVolume(5); // 0 to 7. Set volume level
//audio.quality(1); // Set 1 for 2x oversampling Set 0 for normal
}
//MEMORY LIMITATIONS???
//https://forum.arduino.cc/t/arduino-uno-ssd1306-allocation-failed-need-help-downsizing/604698/5
//https://cdn-learn.adafruit.com/downloads/pdf/memories-of-an-arduino.pdf
// https://www.instructables.com/Playing-Wave-file-using-arduino/
// https://simple-circuit.com/arduino-wave-audio-player-sd-card/
void loop() {
// The FFT real/imaginary data are stored in a char data type as a signed -128 to 127 number
// This allows a waveform to swing centered around a 0 reference data point
// The ADC returns data between 0-1023 so it is scaled to fit within a char by dividing by 4 and subtracting 128.
// eg (0 / 4) - 128 = -128 and (1023 / 4) - 128 = 127
char re[16], im[16]; // real and imaginary FFT result arrays
byte ylim = 60;
printfreeMem(3);
/*if ( !audio.isPlaying() ) {
File entry = SD.open("msg.wav");
audio.play( entry.name() ); // play the audio file
Serial.print("Playing file: ");
Serial.println( entry.name() );
}*/
/*
for (byte i = 0; i < 16; i++) { // read 128 analog input samples from ADC
int sample = analogRead(audioIn);
re[i] = sample / 4 - 128; // scale the samples to fit within a char variable
im[i] = 0; // there are no imaginary samples associated with the time domain so set to 0
};
printfreeMem(4);
//fix_fft(re, im, 7, 0); // send the samples for FFT conversion, returning the real/imaginary results in the same arrays
printfreeMem(5);
display.clearDisplay(); // clear display
display.setCursor(0, 0); // set cursor to top left corner of the display
display.print("Audio Spectrum by Shreya"); // print a header on the top row of the display
delay(2000); // wait for initializing
// The data array will contain frequency bin data in locations 0..127 for samples up to the sampling frequency of approx. 9 KHz
// Each frequency bin will represent a center frequency of approximately (9 KHz / 128 samples) = 70 Hz
// Due to Nyquist sampling requirements, we can only consider sampled frequency data up to (sampling rate / 2) or (9 KHz / 2) = 4.5 KHz
// Therefore we only acknowledge the first 64 frequency bins [0..63] = [0..4.5KHz]
for (byte i = 0; i < 64; i++) {
int dat = sqrt(re[i] * re[i] + im[i] * im[i]); // frequency magnitude is the square root of the sum of the squares of the real and imaginary parts of a vector
display.drawLine(i * 2, ylim, i * 2, ylim - dat, WHITE); // draw bars for each frequency bin from 0 Hz to 4.5 KHz
};
display.display(); // update the display
*/
/*
display.clearDisplay(); // clear display
display.setCursor(0, 0); // set cursor to top left corner of the display
display.print("Audio Spectrum"); // print a header on the top row of the display
display.display(); // update the display
*/
};
/*
void printDirectory(File dir, int numTabs) {
while (true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
break;
}
for (uint8_t i = 0; i < numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs + 1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
};*/
void printfreeMem(int index) {
Serial.print("Freemem ");
Serial.print(index);
Serial.print(": ");
Serial.println(freeMemory());
}
int freeMemory() {
char top;
#ifdef __arm__
return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
return &top - __brkval;
#else // __arm__
return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif // __arm__
}