I'm thinking about how to make a 16-bit mono sound sampling system, with playback of the samples sound, and storage to SD card if playback is okay.
Wil then take the SD card & put in a PC for some post capture manipulation.
My planned architecture - AD7680 16 bit ADC for audio capture, Atmega1284 for control, a bank of 8 23LC1024 128Kx8 SRAMs for intermediate, and for playback a AD5662 16 bit DAC. And SD card for "longterm" storage.
I have this code done up for capture & playback. Any chance of it working fast enough to sample at 44,100? If not, what can be improved?
Datasheets & .ino file attached.
/* Crossroads, 26 July 2013
test for reading from 16 bit ADC
AD7680, needs 24 bit read, max SPI speed 2.5MHz
write read data to bank of 23LC1024 SRAM, eight 128K x 8 SRAM
((128 * 1024)bytes/bank * 8 banks)/88200 bytes/sec = 11.88S
Need two bytes/sample for 16-bit sampling
Needs to be realtime
playback, read SRAM, write to AD5662B (A?) DAC, write as 24 bit sample
Needs to be realtime
Storage - store on SD card once decide sample is good, move to PC for cleanup, trimming, etc. Doesn't need to be realtime.
*/
// pins 0,1 used for Serial
#include <SPI.h>
// pins 11,12,13 used for SPO
#include (SDfat.h>
byte csSD = 10; // SD card chip select
byte csADC = 7; // ADC chip select
byte csDAC = 6 ; // DAC chip select
byte csSRAM[] = {22,23,24,25,26,27,28,29}; // SRAM chip selects
byte recordButton = 14;
byte endButton = 15;
byte playbackButton = 16;
byte storeSDButton = 17; // need autonamimg somehow
byte tbd18Button = 18;
byte tbd19Button = 19;
byte tbd20Button = 20;
byte activeLed = 21; // light up to show recording, playback, storage
byte free[] = {4,5,8,9,30,31,};
// ATMEL ATMEGA1284P on Bobuino & Project usage
//
// +---\/---+
// free (D 4) PB0 1 | | 40 PA0 (D 21) AI 7 activeLED
// free (D 5) PB1 2 | | 39 PA1 (D 20) AI 6 tbd20
// csDAC (D 6) PB2 3 |INT2 | 38 PA2 (D 19) AI 5 tbd19
// csADC (D 7) PB3 4 |PWM | 37 PA3 (D 18) AI 4 tbd18
// csSD (D 10) PB4 5 |PWM | 36 PA4 (D 17) AI 3 storeSD
// MOSI (D 11) PB5 6 | | 35 PA5 (D 16) AI 2 playback
// MISO (D 12) PB6 7 |PWM | 34 PA6 (D 15) AI 1 end
// SCK (D 13) PB7 8 |PWM | 33 PA7 (D 14) AI 0 record
// RST 9 | | 32 AREF
// VCC 10 | | 31 GND
// GND 11 | | 30 AVCC
// XTAL2 12 | | 29 PC7 (D 29) SRAM7
// XTAL1 13 | | 28 PC6 (D 28) SRAM6
// RX0 (D 0) PD0 14 | TDI| 27 PC5 (D 27) SRAM5
// TX0 (D 1) PD1 15 | TDO| 26 PC4 (D 26) SRAM4
// RX1 (D 2) PD2 16 |INT0 TMS| 25 PC3 (D 25) SRAM3
// TX1 (D 3) PD3 17 |INT1 TCK| 24 PC2 (D 24) SRAM2
// free(D 30) PD4 18 |PWM SDA| 23 PC1 (D 23) SRAM1
// free (D 8) PD5 19 |PWM SCL| 22 PC0 (D 22) SRAM0
// free (D 9) PD6 20 |PWM PWM| 21 PD7 (D 31) free
// +--------+
//
byte x;
unsigned long currentTime;
unsigned long duration;
unsigned long memFree = 524288;
byte recording;
byte playing;
byte storing;
byte buttons;
byte adc0;
byte adc1;
byte adc2;
byte SRAMbank = B11111110; // first bank
byte SRAMaddress0; // LSB
byte SRAMaddress1; // middle
byte SRAMaddress2; // MSB
/*********************************************/
void setup(){
//Serial.begin (115200); // for debug testing
pinMode (csSD, OUTPUT);
pinMide (csADC, OUTPUT);
pinMode (csDAC, OUTPUT);
for (x=0; x<8; x=x+1){
pinMode (csSRAM[x], OUTPUT);
}
for (x=0; x<6; x=x+1){
pinMode (free[x], INPUT_PULLUP);
}
pinMode (recordButton, INPUT_PULLUP);
pinMode (endButton, INPUT_PULLUP);
pinMode (playbackButton, INPUT_PULLUP);
pinMode (storeSDButton, INPUT_PULLUP);
pinMode (activeLed, OUTPUT);
SPI.begin();
set SPI Speed to 2 MHz (divide by 4)
} // end setup
/*******************************************/
void loop(){
buttons = PINA; // read buttons port & split out the bits
startStatus = buttons & B10000000;
endStatus = buttons & B01000000;
playStatus = buttons & B0010000;
storeStatus = buttons & B00010000;
// start recording, or keep recording
// 44,100 rate = sample every 362 clocks, 22.6uS
if ( (((startStatus == 0) && (endStatus != 0) && (playStatus != 0) && (storeStatus != 0) ) && (recording == 0)) ){
recording = 1; // turn on recording flag
SRAMaddress0 = 0; // set SRAM start address
SRAMaddress1 = 0; // set SRAM start address
SRAMaddress2 = 0; // set SRAM start address
SRAMbank = B11111110; // start at first chip
PORTA = PORTA | B00000001; // turn on status LED
}
while (recording == 1){ // stay here until memory is full, or end is pressed
currentTime = micros();
if ( currentTime - previousTime) <=22){
previousTime = previousTime + 22;
// access ADC
PORTB = PORTB & B11110111; // clear csADC
adc2 = SPI.transfer(0); // MSB 0000 xxxx
adc1 = SPI.transfer(0); // xxxx xxxx
adc0 = SPI.transfer(0); // xxxx 0000 LSB
PORTB = PORTB | B00001000; // set csADC
// clean up into 2 bytes
upperADC = (adc2 <<4) + (adc1 >> 4);
lowerADC = (adc1 <<4) + (adc0 >> 4);
// write to SRAM
PORTC = SRAMbank; // clear SRAM chip select 0 to 7
SPI.transfer (SRAMaddress2);
SPI.transfer (SRAMaddress1);
SPI.transfer (SRAMaddress0);
SPI.transfer (upperADC);
SPI.transfer (lowerADC);
PORTC = 0xFF; // set SRAM chip select 0 to 7
// update for next address and/or bank
SRAMaddress0 = SRAMaddress0+1;
if (SRAMaddress0 == 0){
// lower address rolled over, increment middle address
SRAMaddress1 = SRAMaddress1 +1; //
if (SRAMaddress1 == 0){
// middle address rolled over, increment upper address
SRAMaddress2 = SRAMaddress2 + 1; //
if (SRAMaddress2 == 2){ //gone thru all addresses,rollover to next bank
SRAMaddress2 = 0; // clear upper bit, shift the 0 for next cs bit
SRAMbank = SRAMbank <<1 + 0x01; // B11111110 -> B11111101, etc.
if (SRAMbank == 0xFF){ // shifted a 0 across all outputs
recording = 0; // Done!
PORTA = PORTA & B11111110; // turn off status LED
} // SRAM bank rollover
} // upper address rollover
} // middle address rollover
} // lower address rollover
// check endButton, stop if pressed
if ((PINA & B01000000) == 0){
recording = 0;
}
} // time check
} // while record/store loop
AD7680 16bit ADC SPI.pdf (295 KB)
23LC1024 128Kx8 SRAM.pdf (481 KB)
AD5662 DAC 16 bit.pdf (578 KB)
sample_playback_store.ino (8.6 KB)