#include <SdFat.h>
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) // simplifying syntax of AVR methods.
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
SdFat sd;
SdFile rec;
const int chipSelect = 53; // CS pin of microsd module.
unsigned long recByteCount = 0L; // total count of bytes saved to buffer
unsigned long recByteSaved = 0L; //total count of bytes saved to sdcard
const int btnStart = 6; // start button pin
const int btnStop = 5; // stop button pin
const int ledStart = 3; // start button LED (green)
const int ledStop = 2; // stop button LED (red)
int recPressed = 0; // flag to check start is pressed or not
int stopPressed = 0; // flag to check stop is pressed or not
byte buf00[510]; // buffer array 1 for time
byte buf01[510]; // buffer array 2 for time
//byte buf02[1020]; // buffer array 2 to 15 for samples
//byte buf03[1020];
unsigned int bufByteCount=1; // array index variable for buffers mentioned above
byte bufWrite,diff; // flag to state which buffer to write (will have only two values 0 or 1 since we are having only two buffers)
long t1,t0;
char name1[]= "audio_1.xls";
void setup() { // THIS RUNS ONCE
Setup_timer2(); // timer config
Setup_ADC(); // skipped to check timer function
pinMode(10, OUTPUT);
pinMode(ledStart, OUTPUT);
pinMode(ledStop, OUTPUT);
pinMode(btnStop, INPUT_PULLUP);
pinMode(btnStart, INPUT_PULLUP);
if (sd.begin(chipSelect, SPI_FULL_SPEED)) { // initialise card on SPI to 8MHz SPI bus speed
for (int dloop = 0; dloop < 4; dloop++) {
digitalWrite(ledStart,!digitalRead(ledStart));
delay(50);
}
} else { // if error, flash LED twice per second, until reset
while(1) {
digitalWrite(ledStart,!digitalRead(ledStart));
delay(50);
}
}
for(int i=2;i<=510;i+=2)
{
if(i%10==0){buf00[i]='\n';buf01[i]='\n';}
else{buf00[i]='\t'; buf01[i]='\t';}
}
}
void loop() { // THIS RUNS CONTI.
if (digitalRead(btnStart) == LOW && recPressed == 0)
{
StartRec(); // launch StartRec method
}
if (digitalRead(btnStop) == LOW)
{
cbi (TIMSK2, OCIE2A);
rec.close();
recPressed = 0;
digitalWrite(ledStart,LOW); // turn off recording LED
digitalWrite(ledStop,HIGH); // light stop LED
}
if (recByteCount % 1020 == 510 && recPressed == 1)
{
rec.write(buf00,510);
recByteSaved+= 510;
} // save buf00 to card
if (recByteCount % 1020 == 0 && recPressed == 1)
{
rec.write(buf01,510);
recByteSaved+= 510;
} // save buf01 to card
}
void StartRec() { // begin recording process
digitalWrite(ledStart,HIGH);
digitalWrite(ledStop,LOW);
recByteCount = 0;
recByteSaved = 0;
recPressed = 1; // recording button has been pressed
stopPressed = 0;
rec.open(name1, O_CREAT | O_TRUNC | O_RDWR);
sbi (TIMSK2, OCIE2A); // enable timer interrupt, start grabbing samples (here, time )
}
void Setup_timer2() {
TCCR2B = _BV(CS21); // Timer2 Clock Prescaler to : 8
TCCR2A = _BV(WGM21); // Interupt frequency = 16MHz / (8 x 90 + 1) = 22191Hz
OCR2A = 221; // Compare Match register set to 221. to match 111uS requirement (i.e. 9.009kHz)
}
void Setup_ADC() {
// set ADC to read pin A5, ADLAR to 1 (left adjust)
cbi(ADCSRA,ADPS2); // set prescaler to 8 / ADC clock = 2MHz
sbi(ADCSRA,ADPS1);
cbi(ADCSRA,ADPS0);
}
ISR(TIMER2_COMPA_vect) { // timer interrupt function will be called automatically.
t1=micros(); //catch the time when sample taken
ADMUX = 0x65; // set ADMUX to read analog channel 5.
sbi(ADCSRA, ADSC); // start ADC sample
while(bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready
diff=t1-t0;
t0=t1;
if (bufByteCount == 510 && bufWrite == 0) {
bufByteCount = 0;
bufWrite = 1;
} else if (bufByteCount == 510 && bufWrite == 1) {
bufByteCount = 0;
bufWrite = 0;
}
if (bufWrite == 0) { buf00[bufByteCount] = diff; buf00[bufByteCount+2] = ADCH;} // we will read analog sensors here.
if (bufWrite == 1) { buf01[bufByteCount] = diff; buf01[bufByteCount+2] = ADCH;} //here, difference between two sampled time is taken for timing purpose.
delayMicroseconds(10);
ADMUX = 0x66; // set ADMUX to read analog channel 6.
sbi(ADCSRA, ADSC); // start ADC sample
while(bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready
if (bufWrite == 0) { buf00[bufByteCount+4] = ADCH;}
if (bufWrite == 1) { buf01[bufByteCount+4] = ADCH;}
delayMicroseconds(10);
ADMUX = 0x67; // set ADMUX to read analog channel 7.
sbi(ADCSRA, ADSC); // start ADC sample
while(bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready
if (bufWrite == 0) { buf00[bufByteCount+6] = ADCH;}
if (bufWrite == 1) { buf01[bufByteCount+6] = ADCH;}
delayMicroseconds(10);
ADMUX = 0x68; // set ADMUX to read analog channel 7.
sbi(ADCSRA, ADSC); // start ADC sample
while(bit_is_set(ADCSRA, ADSC));
if (bufWrite == 0) { buf00[bufByteCount+8] = ADCH;}
if (bufWrite == 1) { buf01[bufByteCount+8] = ADCH;}
recByteCount+=10; // increment sample counter
bufByteCount+=10;
delayMicroseconds(10);
}