Adding I2C as a Slave Kills my program?

Okay, so I am trying to build an i2C controlled MP3 Player with SD card. I have the MP3s playing 32 bytes at a time from the SD card and so I’m ready to move on to adding i2C to the program. Here is where I get into trouble… When I add the line Wire.begin(20); to the program, it will freeze and restart when I go to read from the SD card. If I make it a master, no problem. I have tried with an without request and receive event functions and no change. Below is my code (btw, if anyone wants to build an audio player using the VLSI VS1053, this would be a very good start for you. Message me and I’ll send you the entire code).

#include <SdFat.h>
#include <SPI.h>
#include <Wire.h>
SdFat sd;
SdFile myFile;
byte buf[32];
//int chipSelect = SS_PIN;
//PROGMEM byte sdMP3[2048];
unsigned long filePos = 0;
unsigned long fileSize = 0;
//char* files[]={"01.MP3", "01.WMA", "02.WMA"};
volatile int iTrack = 0;
int iLastTrack = 0;
volatile bool bPlaying = false;
volatile bool changeTrack = false;
int iPlayingError = 0;
byte iVolume = 20;
char serialIn = '0';
char* TrackName = "TRACK0";
//#define i2C_EEPROM_ADDRESS 100 //EEPROM Address for the i2C Address
int i2CAddress = 20; //Default Address used for this i2C device
/** Control Chip Select Pin (for accessing SPI Control/Status registers) */
#define MP3_XCS 8
/** Data Chip Select / BSYNC Pin */
#define MP3_XDCS 9
#define SD_CS 10
#define ERROR_LED 6

//** Data Request Pin: Player asks for more data */
#define MP3_DREQ 14
#define SD_POWER 16
#define MP3_HARDRESET 17

//Set SD Select Pin
void SelectSD(){
  DeSelectAll();
  //digitalWrite(MP3_XCS, HIGH);
  //digitalWrite(MP3_XDCS, HIGH);
  PORTB &= B11111011; //turns off D10
  //digitalWrite(SD_CS, LOW);
}

//Deselect all SPI Select pins
void DeSelectAll()
{
  PORTB |= B00000111;
  //digitalWrite(SD_CS, HIGH);
  //digitalWrite(MP3_XDCS, HIGH);
  //digitalWrite(MP3_XCS, HIGH);
}

void SPIWait(){
  while (!(PINC & _BV(0)));  //Checks for DREQ to go high
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent()
{

}

// function that executes when data is passed to this slave from the master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{

}

void setup() {
  Serial.begin(9600);
  Serial.println("Starting Up... ");
  pinMode(MP3_HARDRESET,OUTPUT);
  pinMode(ERROR_LED, OUTPUT);
  digitalWrite(ERROR_LED, LOW);
  pinMode(SD_POWER, OUTPUT);
  digitalWrite(SD_POWER, LOW);  //CYCLE SD POWER
  pinMode(MP3_DREQ, INPUT);
  pinMode(SD_CS, OUTPUT);
  pinMode(MP3_XCS, OUTPUT);
  pinMode(MP3_XDCS, OUTPUT);
  digitalWrite(MP3_HARDRESET, HIGH);  //ACTIVE LOW HARD RESET
  delay(500);
  digitalWrite(SD_POWER, HIGH);
  SPI.begin();
  DeSelectAll();
  AudioSoftReset();  //Setup VS1053 
  
  //i2C setup
  digitalWrite(A4,HIGH); //Enable Pull-up resistor
  digitalWrite(A5,HIGH); //Enable Pull-up resistor
  Serial.print("Starting up i2C on Address ");
  Serial.print(i2CAddress);
  Serial.print("... ");
  //Wire.begin();
  Wire.begin(i2CAddress);       // join i2c bus with programmed address
  //Wire.onRequest(requestEvent); // register event
  //Wire.onReceive(receiveEvent); // register event
  Serial.println("Done");
  Serial.println(" ");

  // Initialize SdFat or print a detailed error message and halt
  // Use half speed like the native library.
  // change to SPI_FULL_SPEED for more performance.
  if (!sd.init(SPI_FULL_SPEED, SD_CS))
  {
    Serial.println("Error Starting SD");
    digitalWrite(ERROR_LED, HIGH);
  }
  else
  {
    Serial.println("Success!");
    digitalWrite(ERROR_LED, LOW);
  }
}

void loop() {
  AudioSoftReset();
  while(!bPlaying)
  {
    Serial.print("MENU (Last Track: ");
    Serial.print(iLastTrack);
    Serial.println(")");

    Serial.println("  n: Next track");
    Serial.println("  p: Previous Track");
    Serial.println("  r: Print all vs1053 registers");
    Serial.println("  s: Soft reset vs1053");
    Serial.flush();
    while(!Serial.available() && !bPlaying);
    serialIn = Serial.read();
    if(serialIn == 'R' || serialIn == 'r')
      PrintAllRegisters();
    else if(serialIn == 'S' || serialIn == 's')
      AudioSoftReset();
    if(serialIn == 'N' || serialIn == 'n')
    {
      Serial.println("blah1");
      iTrack = iLastTrack+1;
      if(iTrack > 999)
        iTrack = 1;
      bPlaying = true;
    }
    if(serialIn == 'P' || serialIn == 'p')
    {
      iTrack = iLastTrack-1;
      if(iTrack < 0)
        iTrack = 999;
      bPlaying = true;
    }
    if(serialIn >= '0' && serialIn <= '9')
    {
      iTrack = serialIn-48;
      bPlaying = true;
    }
  }
        Serial.println("blah2");
  AudioSoftReset();
        Serial.println("blah3");
  char name[8] = "track";
  char num[3];
  strcpy(name, "TRACK");
  itoa(iTrack,num,DEC);
  if(iTrack < 100)
    strcat(name,"0");
  if(iTrack < 10)
    strcat(name,"0");
  strcat(name, num);
  strcat(name, ".MP3");
  Serial.println("blah4");
  SelectSD();
  Serial.println("blah5");
  if (!myFile.open(name, O_READ)) {
    //sd.errorHalt("opening test.txt for read failed");
    Serial.print("opening ");
    Serial.print(name);
    Serial.println(" for read failed");
    bPlaying = false;
    digitalWrite(ERROR_LED, HIGH);
  }
  else
  {
    Serial.print("opening ");
    Serial.print(name);
    Serial.println(" for read successful");
    Serial.print("filesize= ");
    Serial.println(myFile.fileSize());
    digitalWrite(ERROR_LED, LOW);
  }
  int n=0;
  SelectSD();
  while ((n = myFile.read(buf, sizeof(buf))) > 0)
  {
    TransferAudioData();
    SelectSD();
  }
  SelectSD();
  // close the file:
  myFile.close();
  TransferEndOfFile();
  DeSelectAll();
  iLastTrack = iTrack;
  bPlaying = false;
}

In my loop function you will see Serial.println(“blah#”); When I execute my program I get blah 1-5 to print then the arduino resets. The problem seems to lie with myFile.open(name, O_READ) but I can’t figure out how. I’m using the newest version of SDFatlib from http://code.google.com/p/sdfatlib/downloads/detail?name=sdfatlib20110702.zip&can=2&q=. I had to cut out a lot of the audio functions, but this should give you the gist.

Any help or advice would be greatly appreciated.
-Jeremy

Initializing name

  char name[8] = "track";

…is pointless because you overwrite the value at the very next executable line…

  strcpy(name, "TRACK");
  if(iTrack < 100)
    strcat(name,"0");

…seven bytes stored in name.

  if(iTrack < 10)
    strcat(name,"0");

…eight bytes stored in name (it is now full).

  strcat(name, num);

…nine bytes stored in name (the stack is now corrupt).

  strcat(name, ".MP3");

…insult added to injury.

Allocate more space for name.

Coding Badly,

Thanks for finding this.

Jeremyvnc sent me a bug report on this for SdFat. I did a quick test of the I2C stuff and it was OK. I felt a bit guilty that I didn't spend more time looking at his code.

I just don't have the time any more to find user bugs. I get so much mail about SdFat since it was used as the base for SD.h.

Over 90% of the time this type of bug is a corrupt stack that kills SdFat.

You are welcome. And, I feel your pain. In a previous life I did technical support and spent large quantities of time fixing the same small set of problems.