Go Down

Topic: SDfat and SPI library (Read 1 time) previous topic - next topic


I'm trying to use the sdfat library with the arduino spi library. I'm using the arduino uno and trying to use both as slaves. They both work seperatley, but when i try to combine them it doesn't work. Neither one of the spi slaves interacts and the whole thing just goes wrong, it doesn't even write anything to the slave.

heres the code:

Code: [Select]

#include <SPI.h>
#include <SdFat.h>

int CS_pin = 8;
int DCS_pin = 9;
int DREQ_pin = 7;
int XRST_pin = 6;
int MP3_CS_pin = 10;

SdFat sd;
SdFile myFile;
byte dat[10000];
int index = 0;

void setup()
  pinMode(MP3_CS_pin, OUTPUT);
  pinMode(CS_pin, OUTPUT);
  pinMode(DREQ_pin, INPUT);
  pinMode(DCS_pin, OUTPUT);
  pinMode(XRST_pin, OUTPUT);


void playSong(){
  for(int i = 0; i < index; i++){

void loop()
  digitalWrite(MP3_CS_pin, HIGH);
  digitalWrite(CS_pin, HIGH);
  digitalWrite(DCS_pin, HIGH);
  if (!sd.init(SPI_HALF_SPEED, MP3_CS_pin)) sd.initErrorHalt();
  // re-open the file for reading:
  if (!myFile.open("song1.mp3", O_READ)) {
    sd.errorHalt("error opening song1.mp3 for read");
  int data;
  while ((data = myFile.read()) >= 0){
    dat[index++] = data;
  digitalWrite(MP3_CS_pin, HIGH);

//max SDI clock freq = CLKI/7 and (datasheet) CLKI = 36.864, hence max clock = 5MHz
//SPI clock arduino = 16MHz. 16/ 4 = 4MHz -- ok!

digitalWrite(XRST_pin, LOW);

digitalWrite(CS_pin, HIGH);
digitalWrite(DCS_pin, HIGH);
digitalWrite(XRST_pin, HIGH);

// CHIP Write
// sets sci_mode register, SM_SDINEW, SM_TESTS, SM_STREAM.  pg 25, 26
byte aux;
digitalWrite(CS_pin, LOW);
SPI.transfer(0x02);  //write command
SPI.transfer(0x00); //SDI_MODE register
//extract and send higher byte of data
aux = 0x08A0 >> 8;
//extract and send lower byte of data
aux = 0x08A0 & 0b11111111;
//wait for the chip to finish executing command
while (!DREQ_pin){};
digitalWrite(CS_pin, HIGH);

// Start SINE test
digitalWrite(CS_pin, HIGH);
digitalWrite(DCS_pin, LOW);


digitalWrite(DCS_pin, HIGH);

i've been at this for like 2 weeks now and im super frustrated >.<
please help.


Code: [Select]
byte dat[10000];
Out of the 2K of SRAM that you have available, you'd like to use 10K for this one array? I don't think so.


well i did it because i don't know how long the song would be and it's just a test run... i just want the song to play and i couldn't think of a better way to have the data stored without still having access to the sd card via spi. unless the file class doesn't keep the spi port open. but i wasn't to sure on it.


dude relax, that's way overkill, did you think about your song's bit rate, and the speed at which you can access the data on your card? you should start by performing these kind of estimating calculations before allocating memory like that.

another point, SD cards can only be accessed block-by-block, and this is usually a 512 byte block, I bet you that the library already caches this block for you, and the card won't be accessed as long as you are using data from the same block

third point, I think I have already pointed you towards my tutorial on almost the exact thing you are making, I'm not sure if you've bothered with it, but if you take a look at step 14, http://www.instructables.com/id/Music-Playing-Alarm-Clock/step14/ , I have a logic analyzer session that shows you exactly how the data is sent between the SD card, the AVR, and the MP3 decoder. If you take a look in detail, you'll know exactly how long it takes for the 512-byte data block to be transfered from the SD card, and how frequently the MP3 decoder requests the data.

oh and "the whole thing just goes wrong" is not descriptive enough, you are not telling us how you know "it doesn't even write anything to the slave"

Also, you are not checking DREQ when sending the data... unless you are matching the MP3 file's bitrate exactly, you should check DREQ. Also did you ever read the VS1003 datasheet? I'm pretty sure it explicitly said that DREQ high means it can accept at least 32 bytes (meaning DREQ's falling edge means it can probably take 0 to 32 more bytes but you MUST try to stop immediantly)

I also suggest you pass the byte from myFile.read() directly into the SDI interface immediantly instead of buffering it first, since the SD card library probably already cached the data already (meaning it doesn't need to re-access the card)

about "unless the file class doesn't keep the spi port open", I hope you understand that the SPI module will always be active, with a SPI port, the CS line to a slave device is what determines whether or not a port to that slave device is "open", technically, the slave is "selected", hence the CS or SS (chip select, slave select). As a rule, a slave is always deselected when you finish talking to it, I don't think you can design the SD library without doing that or else it makes the SPI bus useless since the SPI bus is designed to support multiple slaves

There might be a music shield or something out there that uses the same decoder, and there's probably a library for that shield should it exist. If you are having this much trouble, you might consider using that instead.
Freelance engineer, consultant, contractor. Graduated from UW in 2013.

Go Up