So I'm trying to make an i2C controlled MP3 player by using the VS1053, SD card and an arduino. I have successfully tied the three devices into one another on the SPI bus and can get the sample "Hello" from VLSI to play just fine (woohoo!) and if I load another sketch that uses SD (or even SDFat) then I can pull data from SD cards (alright!). However, if I try to put the two together, neither works and neither does serial communication at all. I'm thinking there is some sort of interfering code between the standard SPI library and the SDFat library (SD is a wrapper of SDFat). From trial and error of commenting/uncommenting & downloading I have come to the conclusion that the SDCard class isn't doing it, but when I make an instance of the SDFile class, my "Hello" becomes a blip, I can't read from the sd card, and my serial (9600) drops out. My latest idea was to use the software SPI and isolate the two buses, but that hasn't fixed anything either.
FYI, I'm using an arduino pro mini 3.3V @ 8MHz.
Here is my code:
//RA: Hello, World code for VS1053 and ATMega328 microcontroller on an arduino board
//Uses a sparkfun mp3 shield for arduino available at www.sparkfun.com
#include <SPI.h>
#include <SdFat.h>
#include <HelloMP3.h>
//#include <SdFatUtil.h>
Sd2Card card;
SdVolume volume;
//SdFile root;
SdFile file; //comment this out for MP3 and serial to work again
//// store error strings in flash to save RAM
//#define error(s) error_P(PSTR(s))
//#include <SD.h>
//File myFile;
/** Control Chip Select Pin (for accessing SPI Control/Status registers) */
#define MP3_XCS 8
/** Data Chip Select / BSYNC Pin */
#define MP3_XDCS 9
//** Data Request Pin: Player asks for more data */
#define MP3_DREQ 14
/** VS10xx SCI Registers */
#define SPI_MODE 0x0 /**< VS10xx register */
#define SPI_STATUS 0x1 /**< VS10xx register */
#define SPI_BASS 0x2 /**< VS10xx register */
#define SPI_CLOCKF 0x3 /**< VS10xx register */
#define SPI_DECODE_TIME 0x4 /**< VS10xx register */
#define SPI_AUDATA 0x5 /**< VS10xx register */
#define SPI_WRAM 0x6 /**< VS10xx register */
#define SPI_WRAMADDR 0x7 /**< VS10xx register */
#define SPI_HDAT0 0x8 /**< VS10xx register */
#define SPI_HDAT1 0x9 /**< VS10xx register */
#define SPI_AIADDR 0xa /**< VS10xx register */
#define SPI_VOL 0xb /**< VS10xx register */
#define SPI_AICTRL0 0xc /**< VS10xx register */
#define SPI_AICTRL1 0xd /**< VS10xx register */
#define SPI_AICTRL2 0xe /**< VS10xx register */
#define SPI_AICTRL3 0xf /**< VS10xx register */
unsigned char SPIGetChar(){
unsigned char returned = SPI.transfer(0xFF);
return returned; /* Return the received byte */
}
/** Pull the VS10xx Control Chip Select line Low */
void Mp3SelectControl(){
digitalWrite(MP3_XCS, LOW);
}
/** Pull the VS10xx Control Chip Select line High */
void Mp3DeselectControl(){
digitalWrite(MP3_XCS, HIGH);
}
/** Pull the VS10xx Data Chip Select line Low */
void Mp3SelectData(){
digitalWrite(MP3_XDCS, LOW);
}
/** Pull the VS10xx Data Chip Select line High */
void Mp3DeselectData(){
digitalWrite(MP3_XDCS, HIGH);
}
void SPIWait(){
while (!digitalRead(MP3_DREQ)){};
}
/** Write VS10xx register */
void Mp3WriteRegister(unsigned char addressbyte, unsigned char highbyte, unsigned char lowbyte){
Mp3DeselectData();
Mp3SelectControl();
delay(1);
SPI.transfer(0x02); //write command
SPI.transfer(addressbyte);
SPI.transfer(highbyte);
SPI.transfer(lowbyte);
SPIWait();
Mp3DeselectControl();
}
/** Read the 16-bit value of a VS10xx register */
unsigned int Mp3ReadRegister (unsigned char addressbyte){
unsigned int resultvalue = 0;
unsigned int aux = 0;
Mp3DeselectData();
Mp3SelectControl();
SPI.transfer(0x03); //read command
SPI.transfer(addressbyte);
aux = SPI.transfer(0xff);
SPIWait();
resultvalue = aux << 8;
SPI.transfer(0xff);
SPIWait();
resultvalue |= aux;
Mp3DeselectControl();
return resultvalue;
}
/** Set VS10xx Volume Register */
void Mp3SetVolume(unsigned char leftchannel, unsigned char rightchannel){
Mp3WriteRegister(SPI_VOL,leftchannel,rightchannel);
}
/** Soft Reset of VS10xx (Between songs) */
void Mp3SoftReset(){
Mp3WriteRegister (SPI_MODE, 0x08, 0x04); /* Newmode, Reset, No L1-2 */
delay(1); /* One millisecond delay */
while (!digitalRead(MP3_DREQ)) /* wait for startup */
;
/* Set clock register, doubler etc. */
Mp3WriteRegister(SPI_CLOCKF, 0xb3, 0xfe);
delay(1); /* One millisecond delay */
/* Wait for DREQ */
while (!digitalRead(MP3_DREQ))
;
/***********************************ADDED AS TESTS*/
Mp3DeselectControl();
Mp3DeselectData();
Mp3SetVolume(0xff,0xff); //Declick: Immediately switch analog off
/* Declick: Slow sample rate for slow analog part startup */
Mp3WriteRegister(SPI_AUDATA, 0, 10); /* 10 Hz */
delay(100);
/* Switch on the analog parts */
Mp3SetVolume(0xfe,0xfe);
Mp3WriteRegister (SPI_AUDATA, 31, 64); /* 8kHz */
Mp3SetVolume(20,20); // Set initial volume (20 = -10dB)
/*******************************END ADDED AS TESTS*/
}
void setup() {
uint32_t iByteCount = 0;
int16_t n;
uint8_t buf[7];// nothing special about 7, just a lucky number.
Serial.begin(9600);
Serial.println();
Serial.println("type any character to start");
while (!Serial.available());
Serial.println();
pinMode(17,OUTPUT);
digitalWrite(17, LOW);
delay(1000);
digitalWrite(17, HIGH);
delay(1000);
pinMode(MP3_DREQ, INPUT);
pinMode(MP3_XCS, OUTPUT);
pinMode(MP3_XDCS, OUTPUT);
//Note that even if you're not using the SS pin, it must remain set as an output;
//otherwise, the SPI interface can be put into slave mode, rendering the library inoperative.
//pinMode(10, OUTPUT);//the SS of the SPI interface on the arduino board
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
//max SDI clock freq = CLKI/7 and (datasheet) CLKI = 36.864, hence max clock = 5MHz
//SPI clock arduino = 16MHz. 16/ 4 = 4MHz -- ok!
//Serial.begin(9600);
//Serial.print("Initializing SD card...");
// if (!SD.begin()) {
// //Serial.println("initialization failed!");
// return;
// }
//Serial.println("initialization done.");
//initialize chip
Mp3DeselectControl();
Mp3DeselectData();
if (!card.init(SPI_HALF_SPEED))
{
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
delay(500);
digitalWrite(13,HIGH);
Serial.println("card.init failed");
}
else
{
Serial.println("card.init successful");
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
delay(500);
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
delay(500);
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
}
Serial.flush();
while (!Serial.available());
Mp3SetVolume(0xff,0xff); //Declick: Immediately switch analog off
/* Declick: Slow sample rate for slow analog part startup */
Mp3WriteRegister(SPI_AUDATA, 0, 10); /* 10 Hz */
delay(100);
/* Switch on the analog parts */
Mp3SetVolume(0xfe,0xfe);
Mp3WriteRegister (SPI_AUDATA, 31, 64); /* 8kHz */
Mp3SetVolume(20,20); // Set initial volume (20 = -10dB)
Mp3SoftReset();
}
void InitMicrocontroller(){
SPI.setClockDivider(SPI_CLOCK_DIV64);//slow SPI bus speed
SPI.transfer(0xFF);
}
void SPIInit(){
SPI.setClockDivider(SPI_CLOCK_DIV4); //basically just set fast SPI bus speed
}
void loop(){
unsigned char *p;
unsigned int i;
InitMicrocontroller();
SPIInit();
p = &HelloMP3[0]; // Point "p" to the beginning of array
while (p <= &HelloMP3[sizeof(HelloMP3)-1]) {
while (!digitalRead(MP3_DREQ)) {
// MP3 buffer is full, time to do something else...
SPIWait(); // Wait until SPI transfer is completed
Mp3DeselectData(); // Release the SDI bus
// You can do something else here, the bus is free...
// Maybe set the volume or whatever...
}
Mp3SelectData(); // Pull XDCS low
SPI.transfer(*p++); // Send SPI byte
// You can actually send 32 bytes here before checking for DREQ again
}
// End of file - send 2048 zeros before next file
Mp3SelectData();
for (i=0; i<2048; i++) {
while (!digitalRead(MP3_DREQ)); // wait here until DREQ is high again
SPI.transfer(0);
}
SPIWait(); // Wait until SPI transfer is completed
Mp3DeselectData();
//Mp3SoftReset();
delay(10000);
}
Pleease help me and thanks in advance!
-Jeremy