#include <Bounce.h>
#include <Audio.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioPlaySerialflashRaw playFlashRaw2; //xy=209,420
AudioPlaySerialflashRaw playFlashRaw1; //xy=211,392
AudioPlaySerialflashRaw playFlashRaw3; //xy=212,453
AudioInputI2S i2s2; //xy=217,266
AudioPlaySerialflashRaw playFlashRaw4; //xy=219,490
AudioRecordQueue queue1; //xy=357,259
AudioMixer4 mixer1; //xy=488,455
AudioOutputI2S i2s1; //xy=628,456
AudioConnection patchCord1(playFlashRaw2, 0, mixer1, 1);
AudioConnection patchCord2(playFlashRaw1, 0, mixer1, 0);
AudioConnection patchCord3(playFlashRaw3, 0, mixer1, 2);
AudioConnection patchCord4(i2s2, 0, queue1, 0);
AudioConnection patchCord5(playFlashRaw4, 0, mixer1, 3);
AudioConnection patchCord6(mixer1, 0, i2s1, 0);
AudioControlSGTL5000 sgtl5000_1; //xy=644,240
// GUItool: end automatically generated code
// Bounce objects to easily and reliably read the buttons
Bounce buttonRecord1 = Bounce(0, 8);
Bounce buttonPlay1 = Bounce(1, 8); // 8 = 8 ms debounce time
Bounce buttonRecord2 = Bounce(2, 8);
Bounce buttonPlay2 = Bounce(3, 8);
Bounce buttonRecord3 = Bounce(4, 8); // 8 = 8 ms debounce time
Bounce buttonPlay3 = Bounce(5, 8);
Bounce buttonRecord4 = Bounce(12, 8); // 8 = 8 ms debounce time
Bounce buttonPlay4 = Bounce(21, 8);
const int SDchipSelect = 10; // Audio Shield has SD card CS on pin 10
const int FlashChipSelect = 6; // digital pin for flash chip CS pin
// which input on the audio shield will be used?
const int myInput = AUDIO_INPUT_LINEIN;
// Remember which mode we're doing
int modePart1 = 0; // 0=stopped, 1=recording, 2=playing
// The file where data is recorded
File frec;
void setup() {
SPI.setSCK(14); // Audio shield has SCK on pin 14
SPI.setMOSI(7);
// Configure the pushbutton pins
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(12, INPUT_PULLUP);
pinMode(21, INPUT_PULLUP);
// Audio connections require memory, and the record queue
// uses this memory to buffer incoming audio.
AudioMemory(100);
// Enable the audio shield, select input, and enable output
sgtl5000_1.enable();
sgtl5000_1.inputSelect(myInput);
sgtl5000_1.volume(0.5);
unsigned long startMillis = millis();
while (!Serial && (millis() - startMillis < 10000)) ;
delay(100);
Serial.println("Copy all files from SD Card to SPI Flash");
if (!SD.begin(SDchipSelect)) {
error("Unable to access SD card");
}
if (!SerialFlash.begin(FlashChipSelect)) {
error("Unable to access SPI Flash chip");
}
}
void loop() {
// First, read the buttons
buttonRecord1.update();
buttonPlay1.update();
// Respond to button presses
if (buttonRecord1.fallingEdge()) {
Serial.println("Record Button Press");
if (modePart1 == 2) stopPlaying(1);
if (modePart1 == 0) startRecording(1);
modePart1=1;
}
if (buttonPlay1.fallingEdge()) {
Serial.println("Play Button Press");
if (modePart1 == 1) stopRecording(1);
if (modePart1 == 0) startPlaying(1);
}
// If we're playing or recording, carry on...
if (modePart1 == 1) {
continueRecording(1);
}
if (modePart1 == 2) {
continuePlaying(1);
}
}
void startRecording(int part) {
Serial.print("startRecording");
if (part == 1) {
Serial.println(" part 1");
if (SD.exists("RECORDPART1.RAW")) {
// The SD library writes new data to the end of the
// file, so to start a new recording, the old file
// must be deleted before new data is written.
Serial.print("removed RECORDPART1.RAW");
SD.remove("RECORDPART1.RAW");
}
frec = SD.open("RECORDPART1.RAW", FILE_WRITE);
if (frec) {
queue1.begin();
modePart1 = 1;
}
}
}
void continueRecording(int part) {
if (queue1.available() >= 2) {
if (part == 1) {
byte buffer[512];
// Fetch 2 blocks from the audio library and copy
// into a 512 byte buffer. The Arduino SD library
// is most efficient when full 512 byte sector size
// writes are used.
memcpy(buffer, queue1.readBuffer(), 256);
queue1.freeBuffer();
memcpy(buffer + 256, queue1.readBuffer(), 256);
queue1.freeBuffer();
// write all 512 bytes to the SD card
elapsedMicros usec = 0;
frec.write(buffer, 512);
// Uncomment these lines to see how long SD writes
// are taking. A pair of audio blocks arrives every
// 5802 microseconds, so hopefully most of the writes
// take well under 5802 us. Some will take more, as
// the SD library also must write to the FAT tables
// and the SD card controller manages media erase and
// wear leveling. The queue1 object can buffer
// approximately 301700 us of audio, to allow time
// for occasional high SD card latency, as long as
// the average write time is under 5802 us.
//Serial.print("SD write, us=");
//Serial.println(usec);
}
}
}
void stopRecording(int part) {
if (part == 1) {
Serial.println("stopRecording part 1");
queue1.end();
if (modePart1 == 1) {
while (queue1.available() > 0) {
frec.write((byte*)queue1.readBuffer(), 256);
queue1.freeBuffer();
}
frec.close();
}
sdToFlash(); // as soon as file has been recorded to SD, copy over to flash chip
modePart1 = 0;
}
}
void startPlaying(int part) {
if (part == 1) {
Serial.println("startPlaying part 1");
playFlashRaw1.play("RECORDPART1.RAW");
// changed from 2 to 0 in order to allow retriggering of start of sample
modePart1 = 0;
}
}
void continuePlaying(int part) {
if (part == 1) {
if (!playFlashRaw1.isPlaying()) {
playFlashRaw1.stop();
modePart1 = 0;
}
}
}
void stopPlaying(int part) {
if(part ==1){
Serial.println("stopPlaying");
if (modePart1 == 2) playFlashRaw1.stop();
modePart1 = 0;
}
}
void sdToFlash() {
File rootdir = SD.open("/");
while (1) {
// open a file from the SD card
Serial.println();
File f = rootdir.openNextFile();
if (!f) break;
const char *filename = f.name();
Serial.print(filename);
Serial.print(" ");
unsigned long length = f.size();
Serial.println(length);
// check if this file is already on the Flash chip
if (SerialFlash.exists(filename)) {
Serial.println(" already exists on the Flash chip");
SerialFlashFile ff = SerialFlash.open(filename);
if (ff && ff.size() == f.size()) {
Serial.println(" size is the same, comparing data...");
if (compareFiles(f, ff) == true) {
Serial.println(" files are identical :)");
f.close();
ff.close();
continue; // advance to next file
} else {
Serial.println(" files are different");
}
} else {
Serial.print(" size is different, ");
Serial.print(ff.size());
Serial.println(" bytes");
}
// delete the copy on the Flash chip, if different
Serial.println(" delete file from Flash chip");
SerialFlash.remove(filename);
}
// create the file on the Flash chip and copy data
if (SerialFlash.create(filename, length)) {
SerialFlashFile ff = SerialFlash.open(filename);
if (ff) {
Serial.print(" copying");
// copy data loop
unsigned long count = 0;
unsigned char dotcount = 9;
while (count < length) {
char buf[256];
unsigned int n;
n = f.read(buf, 256);
ff.write(buf, n);
count = count + n;
Serial.print(".");
if (++dotcount > 100) {
Serial.println();
dotcount = 0;
}
}
ff.close();
if (dotcount > 0) Serial.println();
} else {
Serial.println(" error opening freshly created file!");
}
} else {
Serial.println(" unable to create file");
}
f.close();
}
rootdir.close();
delay(10);
Serial.println("Finished All Files");
}
// copy sd to flash
bool compareFiles(File &file, SerialFlashFile &ffile) {
file.seek(0);
ffile.seek(0);
unsigned long count = file.size();
while (count > 0) {
char buf1[128], buf2[128];
unsigned long n = count;
if (n > 128) n = 128;
file.read(buf1, n);
ffile.read(buf2, n);
if (memcmp(buf1, buf2, n) != 0) return false; // differ
count = count - n;
}
return true; // all data identical
}
void error(const char *message) {
while (1) {
Serial.println(message);
delay(2500);
}
}