the master code below:
#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h>
//#include “pins_arduino.h”
#define TRUE 0
#define FALSE 1
//MP3 Player Shield pin mapping. See the schematic
#define MP3_XCS 6 //Control Chip Select Pin (for accessing SPI Control/Status registers)
#define MP3_XDCS 7 //Data Chip Select / BSYNC Pin
#define MP3_DREQ 2 //Data Request Pin: Player asks for more data
#define MP3_RESET 8 //Reset is active low
//Remember you have to edit the Sd2PinMap.h of the sdfatlib library to correct control the SD card.
//VS10xx SCI Registers
#define SCI_MODE 0x00
#define SCI_STATUS 0x01
#define SCI_BASS 0x02
#define SCI_CLOCKF 0x03
#define SCI_DECODE_TIME 0x04
#define SCI_AUDATA 0x05
#define SCI_WRAM 0x06
#define SCI_WRAMADDR 0x07
#define SCI_HDAT0 0x08
#define SCI_HDAT1 0x09
#define SCI_AIADDR 0x0A
#define SCI_VOL 0x0B
#define SCI_AICTRL0 0x0C
#define SCI_AICTRL1 0x0D
#define SCI_AICTRL2 0x0E
#define SCI_AICTRL3 0x0F
#define I2S_CONFIG 0xC040
#define SDC_Content 100 //file name from aal001 to aal100
#define SN_LEN 9
char trackName = “aal001.mp3”; //number & english total length 8 of name
int trackNumber = 1;
char errorMsg[100]; //This is a generic array used for sprintf of error messages
//Create the variables to be used by SdFat Library
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile MyFile , Mp3File;
SdFat sd;
int start; // timer start time record
char NO = 1;
volatile byte Mode = 0;
int CPU_CS = 10;
boolean flag = false;
char ACR_STATE = 1; //current ACR stat
char int_data;
String allMsg;
char Stop = 0;
void Player_Initial();
void Mp3SetBass_Treble(unsigned char treble_frq,unsigned char bass_frq);
void Mp3SetSampleRate(unsigned char hi_rate,unsigned char low_rate);
void Mp3SetCLKI(unsigned char hi_byte , unsigned char low_byte);
void Mp3_Play(char *mp3file);
void Mp3_Stop();
void Mp3_Pause();
void Mp3_Pre();
void Mp3_Next();
void Time_Play();
int SD_Alive();
void SD_Size();
void _make_list(const char* sourcepath ,const char* txt , const char* targetpath);
void _make_dir(const char* dirname);
void _ChangePath(const char* pathname);
char Time();
void Function();
void _CC_SDC_MP3();
char ACR_State();
byte transferAndWait (const byte what);
void setup() {
Player_Initial();
SD_Alive();
_make_dir(“/mp3”); // make folders “mp3”.
_make_dir(“/list”); // make folders “list”.
_make_dir(“/schedule”); // make folders “schedule”.
_make_dir(“/buildin”); // make folders “buildin”.
_make_list(“/list” , “sdlist.txt” , “/mp3”); //make sdlist on the list folder , indicate record exists file name on the sd
SD_Size();
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV16); //Set SPI bus speed to 1MHz (16MHz / 16 = 1MHz)
SPI.transfer(0xFF); //Throw a dummy byte at the bus
delay(10);
digitalWrite(MP3_RESET, HIGH); //Bring up VS1053
//Mp3SetVolume(20, 20); //Set initial volume (20 = -10dB) LOUD
Mp3SetVolume(40, 40); //Set initial volume (20 = -10dB) Manageable
//Mp3SetVolume(80, 80); //Set initial volume (20 = -10dB) More quiet
Mp3SetBass_Treble(0x00,0x00); // adjustment volume and frequency of Treble and Bass ,default 0x00 trun off treble and bass function
Mp3WriteRegister(SCI_CLOCKF , 0x80 , 0x00);
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_CLOCK_DIV4);
Mp3SetSampleRate(0xBB,0x81); //set sample rate = 48kHz , stereo
ACR_STATE = 2;
Serial.println(“initial done\nIdle”);
//Serial.println(ACR_State() , DEC);
}
void loop(){
if(Mode == 1){
ACR_STATE = 3; //ACR busy
Serial.println(“start playback”);
_ChangePath(“/mp3”);
while(MyFile.openNext(sd.vwd() , O_READ)){
MyFile.getFilename(trackName);
MyFile.close();
Mp3_Play(trackName);
if(Stop == 1){
Stop = 0;
break;
}
Mode = 0;
}
}
ACR_STATE = 2; // ACR idle
// flag = false;
}
byte transferAndWait (const byte what)
{
byte a = SPI.transfer (what);
delayMicroseconds (50);
return a;
} // end of transferAndWait
void Player_Initial(){
start = micros();
Serial.begin(57600); //Use serial for debugging
pinMode(MP3_DREQ, INPUT);
pinMode(MP3_XCS, OUTPUT);
pinMode(MP3_XDCS, OUTPUT);
pinMode(MP3_RESET, OUTPUT);
digitalWrite(MP3_XCS, HIGH); //Deselect Control
digitalWrite(MP3_XDCS, HIGH); //Deselect Data
digitalWrite(MP3_RESET, LOW); //Put VS1053 into hardware reset
pinMode(CPU_CS , OUTPUT); //control slave CPU CS
digitalWrite(CPU_CS , HIGH);
//attachInterrupt(1,Function,FALLING);
SREG |= 0x80; // enable interrupt
EICRA |= 0x0C;
EIMSK |= 0x02;
allMsg = “”;
if (!card.init(SPI_FULL_SPEED))
allMsg += “SD card do not exists\n”;
if (!volume.init(&card))
allMsg += “SD card fomat error\n”;
if (!root.openRoot(&volume))
allMsg += “Opening root "/" error\n”;
if(!sd.init(SPI_FULL_SPEED))
allMsg += “SD card error\n”;
if(allMsg != “”)
Serial.println(allMsg);
}
ISR(INT1_vect){
digitalWrite(CPU_CS , LOW);
transferAndWait(0);
Mode = transferAndWait(0);
digitalWrite(CPU_CS , HIGH);
Serial.print("Mode = ");
Serial.println(Mode , DEC);
//Function();
}
void Mp3_Play(char *mp3file){
Mp3WriteRegister(SCI_MODE , 0x48, 0x00);
if (!Mp3File.open(mp3file, O_READ)) {
sprintf(errorMsg, “Failed to open %s”, mp3file);
Serial.println(errorMsg);
return;
}
uint8_t streamBuffer[32];
char lock = 1;
while(1) {
while(!digitalRead(MP3_DREQ)) { // mp3_DREQ is 0 indicate the vs1053 buffer full(2048bytes)
if(lock == 1) {
if(!Mp3File.read(streamBuffer, sizeof(streamBuffer)))
break;
lock = 0;
}
}//while(!digitalRead(MP3_DREQ)) end
if(lock == 1){
if(!Mp3File.read(streamBuffer, sizeof(streamBuffer)))
break;
lock = 0;
}
//Once DREQ is released (high) we now feed 32 bytes of data to the VS1053 from our SD read buffer
digitalWrite(MP3_XDCS, LOW); //Select Data
for(int y = 0 ; y < sizeof(streamBuffer) ; y++)
SPI.transfer(streamBuffer[y]); // Send SPI byte
digitalWrite(MP3_XDCS, HIGH); //Deselect Data
lock = 1; //We’ve just dumped 32 bytes into VS1053 so our SD read buffer is empty. Set flag so we go get more data
if(Mode == 2){ // Mp3_Stop
Mp3_Stop();
Stop = 1;
Serial.println(“Mp3 stop”);
break;
}else if(Mode == 3){ //Mp3_Pause
Serial.println(“Mp3 pause”);
Mp3_Pause();
}
else if(Mode == 4){
Mp3_Next();
Serial.println(“Next song”);
break;
}
}//while(1) end
while(!digitalRead(MP3_DREQ)) ; //Wait for DREQ to go high indicating transfer is complete
digitalWrite(MP3_XDCS, HIGH); //Deselect Data
Mp3File.close(); //Close out this track
sprintf(errorMsg, “Track %s done!”, mp3file);
Serial.println(errorMsg);
}
void Mp3_Stop(){
Mp3WriteRegister(SCI_MODE , 0x48 , 0x08); // play stop
Mp3WriteRegister(SCI_MODE , 0x24 , 0x04);
}
void Mp3_Pause(){
while(Mode == 3);
}
void Mp3_Pre(){}
void Mp3_Next(){
Mp3_Stop();
}
void Time_Play(){}
void _make_dir(const char* dirname){
if(!sd.exists(dirname)){
if(!sd.mkdir(dirname)) { //make folder dirname
sprintf(errorMsg , “make folder %s error” , dirname);
sd.errorHalt(errorMsg);
}
}
}
void _make_list(const char* sourcepath ,const char* txt , const char* targetpath){
SdFile ptr;
Serial.print("build in sdlist.txt … ");
_ChangePath(sourcepath);
if(sd.exists(txt)){
if(!sd.remove(txt)){
sprintf(errorMsg , “delete %s file error” , txt);
Serial.println(errorMsg);
}
}
if(!MyFile.open(txt , O_RDWR | O_CREAT)){
sprintf(errorMsg , “open %s error” , txt);
sd.errorHalt(errorMsg);
}
MyFile.timestamp(T_WRITE , 2012 , 12 , 15 , 16 , 10 , 00);
_ChangePath(targetpath);
while(ptr.openNext(sd.vwd(),O_READ)){
ptr.getFilename(trackName);
MyFile.println(trackName);
ptr.close();
}
MyFile.close();
Serial.println(“done”);
}
void _ChangePath(const char* pathname){
if(!sd.chdir(pathname)){
sprintf(errorMsg , “set path %s error” , pathname);
sd.errorHalt(errorMsg);
}
sd.chvol();
}
int SD_Alive(){
allMsg = “”;
sprintf(errorMsg , "%dmin. " , Time());
allMsg += errorMsg;
switch(card.type()) {
case SD_CARD_TYPE_SD1:
allMsg += “SD1”;
// Serial.println(“SD1”);
break;
case SD_CARD_TYPE_SD2:
allMsg += “SD2”;
// Serial.println(“SD2”);
break;
case SD_CARD_TYPE_SDHC:
allMsg += “SDHC”;
// Serial.println(“SDHC”);
break;
default:
allMsg += “Unknown”;
// Serial.println(“Unknown”);
return 0; //SD card do not use
}
sprintf(errorMsg , " FAT%d" , volume.fatType());
allMsg += errorMsg;
Serial.println(allMsg);
return 1;
}
char Time(){
unsigned long t;
static unsigned char s , m = 0;
t = micros(); // about 70 minutes will be overflow , millis() about 50 days will be overflow
t -= start;
s = t / 1000;
if((s / 60) != 0){
s %= 60;
m++;
}
if((m / 60) != 0)
m %= 60;
return m;
}
void SD_Size(){
uint32_t useSize = 0;
for(int i = 0; i < 4 ; i++){
switch(i){
case 0:
_ChangePath(“/buildin”);
break;
case 1:
_ChangePath(“/list”);
break;
case 2:
_ChangePath(“/mp3”);
break;
case 3:
_ChangePath(“/schedule”);
break;
}
while(MyFile.openNext(sd.vwd() , O_READ)){
useSize += MyFile.fileSize();
MyFile.close();
}
}
sprintf(errorMsg , “remain size is %luMB” ,((card.cardSize() * 512) - useSize)/1000000);
Serial.println(errorMsg);
}
void _CC_SDC_MP3(){
String content = “”;
char r_m , r_d , w_m , w_d;
int r_y , w_y;
dir_t dir;
for(int i = 0; i < 4 ; i++){
switch(i){
case 0:
_ChangePath(“/buildin”);
break;
case 1:
_ChangePath(“/list”);
break;
case 2:
_ChangePath(“/mp3”);
break;
case 3:
_ChangePath(“/schedule”);
break;
}
while(MyFile.openNext(sd.vwd() , O_READ)){
MyFile.dirEntry(dir);
MyFile.getFilename(errorMsg);
r_y = 1980 + (dir.lastAccessDate >> 9);
r_m = (dir.lastAccessDate & 0x01E0) >> 5;
r_d = (dir.lastAccessDate & 0x001F);
w_y = 1980 + (dir.lastWriteDate >> 9);
w_m = (dir.lastWriteDate & 0x01E0) >> 5;
w_d = (dir.lastWriteDate & 0x001F);
sprintf(errorMsg , “%s %d%02d%02d %d%02d%02d” , errorMsg , r_y,r_m,r_d ,w_y,w_m,w_d);
Serial.println(errorMsg);
MyFile.close();
}
}
}
char ACR_State(){
return ACR_STATE;
}
//Write to VS10xx register
//SCI: Data transfers are always 16bit. When a new SCI operation comes in
//DREQ goes low. We then have to wait for DREQ to go high again.
//XCS should be low for the full duration of operation.
void Mp3WriteRegister(unsigned char addressbyte, unsigned char highbyte, unsigned char lowbyte){
while(!digitalRead(MP3_DREQ)) ; //Wait for DREQ to go high indicating IC is available
digitalWrite(MP3_XCS, LOW); //Select control
//SCI consists of instruction byte, address byte, and 16-bit data word.
SPI.transfer(0x02); //Write instruction
SPI.transfer(addressbyte);
SPI.transfer(highbyte);
SPI.transfer(lowbyte);
while(!digitalRead(MP3_DREQ)) ; //Wait for DREQ to go high indicating command is complete
digitalWrite(MP3_XCS, HIGH); //Deselect Control
}
//Read the 16-bit value of a VS10xx register
unsigned int Mp3ReadRegister (unsigned char addressbyte){
while(!digitalRead(MP3_DREQ)) ; //Wait for DREQ to go high indicating IC is available
digitalWrite(MP3_XCS, LOW); //Select control
//SCI consists of instruction byte, address byte, and 16-bit data word.
SPI.transfer(0x03); //Read instruction
SPI.transfer(addressbyte);
char response1 = SPI.transfer(0xFF); //Read the first byte
while(!digitalRead(MP3_DREQ)) ; //Wait for DREQ to go high indicating command is complete
char response2 = SPI.transfer(0xFF); //Read the second byte
while(!digitalRead(MP3_DREQ)) ; //Wait for DREQ to go high indicating command is complete
digitalWrite(MP3_XCS, HIGH); //Deselect Control
int resultvalue = response1 << 8;
resultvalue |= response2;
return resultvalue;
}
//Set VS10xx Volume Register
void Mp3SetVolume(unsigned char leftchannel, unsigned char rightchannel){
Mp3WriteRegister(SCI_VOL, leftchannel, rightchannel);
}
void Mp3SetBass_Treble(unsigned char treble_frq,unsigned char bass_frq){
Mp3WriteRegister(SCI_BASS, treble_frq, bass_frq);
}
void Mp3SetCLKI(unsigned char hi_byte , unsigned char low_byte){
Mp3WriteRegister(SCI_CLOCKF, hi_byte , low_byte);
}
void Mp3SetSampleRate(unsigned char hi_rate,unsigned char low_rate){
Mp3WriteRegister(SCI_AUDATA , hi_rate , low_rate);
}
and slave code on below:
#include <SPI.h>
//#include “pins_arduino.h”
#define BUTTEN 6
int pin[6] = {3,4,5,6,7,8};
int interruptMsg = 9;
//int CPU_CS = 10; // SPI sl
//char Msg[100];
unsigned char data[6];
//byte command = 0;
byte SPI_value;
void setup(){
Serial.begin(57600);
for(int i = 0 ; i <BUTTEN ; i++)
pinMode(pin , INPUT);
pinMode(interruptMsg , OUTPUT);
pinMode(MISO, OUTPUT);
SPCR |= _BV(SPE); // set CPU is slave
// SPCR |= _BV(SPIE); // enable SPI interrupt
SPI.attachInterrupt(); // enable SPI interrupt
SPI.setClockDivider(SPI_CLOCK_DIV4);
SPI.setDataMode(SPI_MODE0);
Serial.println(“UI interface enable”);
}
void loop(){
digitalWrite(interruptMsg , HIGH);
for(byte i = 0 ; i< BUTTEN ; i++){
data = digitalRead(pin);
if(data == 0){
SPI_value = i+1;
Serial.println(SPI_value);
digitalWrite(interruptMsg , LOW);
delay(250);
}
}
}
ISR (SPI_STC_vect)
{
//byte c = SPDR;
SPDR = SPI_value;
/*
switch (command)
{
// no command? then this is the command
case 0:
command = c;
SPDR = 0;
break;
// add to incoming byte, return result
case ‘a’:
SPDR = SPI_value;
break;
default:
SPDR = 0xBB;
} // end of switch
*/
} // end of interrupt service routine (ISR) SPI_STC_vect
thakns