Advertisement
Guest User

Mp3Player for multishield with Wifly

a guest
Apr 20th, 2013
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.79 KB | None | 0 0
  1. /*
  2.  4-28-2011
  3.  Spark Fun Electronics 2011
  4.  Nathan Seidle
  5.  
  6.  This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).
  7.  
  8.  This example code plays a MP3 from the SD card called 'track001.mp3'. The theory is that you can load a
  9.  microSD card up with a bunch of MP3s and then play a given 'track' depending on some sort of input such
  10.  as which pin is pulled low.
  11.  
  12.  It relies on the sdfatlib from Bill Greiman:
  13.  http://code.google.com/p/sdfatlib/
  14.  You will need to download and install his library. To compile, you MUST change Sd2PinMap.h of the SDfatlib!
  15.  The default SS_PIN = 10;. You must change this line under the ATmega328/Arduino area of code to
  16.  uint8_t const SS_PIN = 9;. This will cause the sdfatlib to use pin 9 as the 'chip select' for the
  17.  microSD card on pin 9 of the Arduino so that the layout of the shield works.
  18.  
  19.  Attach the shield to an Arduino. Load code (after editing Sd2PinMap.h) then open the terminal at 57600bps. This
  20.  example shows that it takes ~30ms to load up the VS1053 buffer. We can then do whatever we want for ~100ms
  21.  before we need to return to filling the buffer (for another 30ms).
  22.  
  23.  This code is heavily based on the example code I wrote to control the MP3 shield found here:
  24.  http://www.sparkfun.com/products/9736
  25.  This example code extends the previous example by reading the MP3 from an SD card and file rather than from internal
  26.  memory of the ATmega. Because the current MP3 shield does not have a microSD socket, you will need to add the microSD
  27.  shield to your Arduino stack.
  28.  
  29.  The main gotcha from all of this is that you have to make sure your CS pins for each device on an SPI bus is carefully
  30.  declared. For the SS pin (aka CS) on the SD FAT libaray, you need to correctly set it within Sd2PinMap.h. The default
  31.  pin in Sd2PinMap.h is 10. If you're using the SparkFun microSD shield with the SparkFun MP3 shield, the SD CS pin
  32.  is pin 9.
  33.  
  34.  Four pins are needed to control the VS1503:
  35.  DREQ
  36.  CS
  37.  DCS
  38.  Reset (optional but good to have access to)
  39.  Plus the SPI bus
  40.  
  41.  Only the SPI bus pins and another CS pin are needed to control the microSD card.
  42.  
  43.  What surprised me is the fact that with a normal MP3 we can do other things for up to 100ms while the MP3 IC crunches
  44.  through it's fairly large buffer of 2048 bytes. As long as you keep your sensor checks or serial reporting to under
  45.  100ms and leave ~30ms to then replenish the MP3 buffer, you can do quite a lot while the MP3 is playing glitch free.
  46.  
  47.  */
  48.  
  49. #include <SPI.h>
  50.  
  51. //Add the SdFat Libraries
  52. #include <SdFat.h>
  53. #include <SdFatUtil.h>
  54.  
  55. //Create the variables to be used by SdFat Library
  56. Sd2Card card;
  57. SdVolume volume;
  58. SdFile root;
  59. SdFile track;
  60.  
  61. //This is the name of the file on the microSD card you would like to play
  62. //Stick with normal 8.3 nomeclature. All lower-case works well.
  63. //Note: you must name the tracks on the SD card with 001, 002, 003, etc.
  64. //For example, the code is expecting to play 'track002.mp3', not track2.mp3.
  65. char trackName[] = "track001.mp3";
  66. int trackNumber = 1;
  67.  
  68. char errorMsg[100]; //This is a generic array used for sprintf of error messages
  69.  
  70. #define TRUE  0
  71. #define FALSE  1
  72.  
  73. //MP3 Player Shield pin mapping. See the schematic
  74. #define MP3_XCS 6 //Control Chip Select Pin (for accessing SPI Control/Status registers)
  75. #define MP3_XDCS 14 //Data Chip Select / BSYNC Pin
  76. #define MP3_DREQ 2 //Data Request Pin: Player asks for more data
  77. #define MP3_RESET 8 //Reset is active low
  78. //Remember you have to edit the Sd2PinMap.h of the sdfatlib library to correct control the SD card.
  79.  
  80. //VS10xx SCI Registers
  81. #define SCI_MODE 0x00
  82. #define SCI_STATUS 0x01
  83. #define SCI_BASS 0x02
  84. #define SCI_CLOCKF 0x03
  85. #define SCI_DECODE_TIME 0x04
  86. #define SCI_AUDATA 0x05
  87. #define SCI_WRAM 0x06
  88. #define SCI_WRAMADDR 0x07
  89. #define SCI_HDAT0 0x08
  90. #define SCI_HDAT1 0x09
  91. #define SCI_AIADDR 0x0A
  92. #define SCI_VOL 0x0B
  93. #define SCI_AICTRL0 0x0C
  94. #define SCI_AICTRL1 0x0D
  95. #define SCI_AICTRL2 0x0E
  96. #define SCI_AICTRL3 0x0F
  97.  
  98. void setup() {
  99.   pinMode(MP3_DREQ, INPUT);
  100.   pinMode(MP3_XCS, OUTPUT);
  101.   pinMode(MP3_XDCS, OUTPUT);
  102.   pinMode(MP3_RESET, OUTPUT);
  103.  
  104.   digitalWrite(MP3_XCS, HIGH); //Deselect Control
  105.   digitalWrite(MP3_XDCS, HIGH); //Deselect Data
  106.   digitalWrite(MP3_RESET, LOW); //Put VS1053 into hardware reset
  107.  
  108.   Serial.begin(57600); //Use serial for debugging
  109.   Serial.println("MP3 Testing");
  110.  
  111.   //Setup SD card interface
  112.   pinMode(10, OUTPUT);       //Pin 10 must be set as an output for the SD communication to work.
  113.   if (!card.init(SPI_FULL_SPEED,9))  Serial.println("Error: Card init"); //Initialize the SD card and configure the I/O pins.
  114.   if (!volume.init(&card)) Serial.println("Error: Volume ini"); //Initialize a volume on the SD card.
  115.   if (!root.openRoot(&volume)) Serial.println("Error: Opening root"); //Open the root directory in the volume.
  116.  
  117.   //We have no need to setup SPI for VS1053 because this has already been done by the SDfatlib
  118.  
  119.   //From page 12 of datasheet, max SCI reads are CLKI/7. Input clock is 12.288MHz.
  120.   //Internal clock multiplier is 1.0x after power up.
  121.   //Therefore, max SPI speed is 1.75MHz. We will use 1MHz to be safe.
  122.   SPI.setClockDivider(SPI_CLOCK_DIV16); //Set SPI bus speed to 1MHz (16MHz / 16 = 1MHz)
  123.   SPI.transfer(0xFF); //Throw a dummy byte at the bus
  124.   //Initialize VS1053 chip
  125.   delay(10);
  126.   digitalWrite(MP3_RESET, HIGH); //Bring up VS1053
  127.   //delay(10); //We don't need this delay because any register changes will check for a high DREQ
  128.  
  129.   //Mp3SetVolume(20, 20); //Set initial volume (20 = -10dB) LOUD
  130.   Mp3SetVolume(40, 40); //Set initial volume (20 = -10dB) Manageable
  131.   //Mp3SetVolume(80, 80); //Set initial volume (20 = -10dB) More quiet
  132.  
  133.   //Let's check the status of the VS1053
  134.   int MP3Mode = Mp3ReadRegister(SCI_MODE);
  135.   int MP3Status = Mp3ReadRegister(SCI_STATUS);
  136.   int MP3Clock = Mp3ReadRegister(SCI_CLOCKF);
  137.  
  138.   Serial.print("SCI_Mode (0x4800) = 0x");
  139.   Serial.println(MP3Mode, HEX);
  140.  
  141.   Serial.print("SCI_Status (0x48) = 0x");
  142.   Serial.println(MP3Status, HEX);
  143.  
  144.   int vsVersion = (MP3Status >> 4) & 0x000F; //Mask out only the four version bits
  145.   Serial.print("VS Version (VS1053 is 4) = ");
  146.   Serial.println(vsVersion, DEC); //The 1053B should respond with 4. VS1001 = 0, VS1011 = 1, VS1002 = 2, VS1003 = 3
  147.  
  148.   Serial.print("SCI_ClockF = 0x");
  149.   Serial.println(MP3Clock, HEX);
  150.  
  151.   //Now that we have the VS1053 up and running, increase the internal clock multiplier and up our SPI rate
  152.   Mp3WriteRegister(SCI_CLOCKF, 0x60, 0x00); //Set multiplier to 3.0x
  153.  
  154.   //From page 12 of datasheet, max SCI reads are CLKI/7. Input clock is 12.288MHz.
  155.   //Internal clock multiplier is now 3x.
  156.   //Therefore, max SPI speed is 5MHz. 4MHz will be safe.
  157.   SPI.setClockDivider(SPI_CLOCK_DIV4); //Set SPI bus speed to 4MHz (16MHz / 4 = 4MHz)
  158.  
  159.   MP3Clock = Mp3ReadRegister(SCI_CLOCKF);
  160.   Serial.print("SCI_ClockF = 0x");
  161.   Serial.println(MP3Clock, HEX);
  162.  
  163.   //MP3 IC setup complete
  164. }
  165.  
  166. void loop(){
  167.  
  168.   //Let's play a track of a given number
  169.   sprintf(trackName, "track%03d.mp3", trackNumber); //Splice the new file number into this file name
  170.   playMP3(trackName); //Go play trackXXX.mp3
  171.  
  172.   //Once we are done playing or have exited the playback for some reason, decide what track to play next
  173.   trackNumber++; //When we loop, advance to next track!
  174.  
  175.   if(trackNumber > 100) {
  176.     Serial.println("Whoa there cowboy!"); //Soft limit. We shouldn't be trying to open past track 100.
  177.     while(1);
  178.   }
  179. }
  180.  
  181. //PlayMP3 pulls 32 byte chunks from the SD card and throws them at the VS1053
  182. //We monitor the DREQ (data request pin). If it goes low then we determine if
  183. //we need new data or not. If yes, pull new from SD card. Then throw the data
  184. //at the VS1053 until it is full.
  185. void playMP3(char* fileName) {
  186.  
  187.   if (!track.open(&root, fileName, O_READ)) { //Open the file in read mode.
  188.     sprintf(errorMsg, "Failed to open %s", fileName);
  189.     Serial.println(errorMsg);
  190.     return;
  191.   }
  192.  
  193.   Serial.println("Track open");
  194.  
  195.   uint8_t mp3DataBuffer[32]; //Buffer of 32 bytes. VS1053 can take 32 bytes at a go.
  196.   //track.read(mp3DataBuffer, sizeof(mp3DataBuffer)); //Read the first 32 bytes of the song
  197.   int need_data = TRUE;
  198.   long replenish_time = millis();
  199.  
  200.   Serial.println("Start MP3 decoding");
  201.  
  202.   while(1) {
  203.     while(!digitalRead(MP3_DREQ)) {
  204.       //DREQ is low while the receive buffer is full
  205.       //You can do something else here, the buffer of the MP3 is full and happy.
  206.       //Maybe set the volume or test to see how much we can delay before we hear audible glitches
  207.  
  208.       //If the MP3 IC is happy, but we need to read new data from the SD, now is a great time to do so
  209.       if(need_data == TRUE) {
  210.         if(!track.read(mp3DataBuffer, sizeof(mp3DataBuffer))) { //Try reading 32 new bytes of the song
  211.           //Oh no! There is no data left to read!
  212.           //Time to exit
  213.           break;
  214.         }
  215.         need_data = FALSE;
  216.       }
  217.  
  218.       //Serial.println("."); //Print a character to show we are doing nothing
  219.  
  220.       //This is here to show how much time is spent transferring new bytes to the VS1053 buffer. Relies on replenish_time below.
  221.       Serial.print("Time to replenish buffer: ");
  222.       Serial.print(millis() - replenish_time, DEC);
  223.       Serial.print("ms");
  224.  
  225.       //Test to see just how much we can do before the audio starts to glitch
  226.       long start_time = millis();
  227.       //delay(150); //Do NOTHING - audible glitches
  228.       //delay(135); //Do NOTHING - audible glitches
  229.       //delay(120); //Do NOTHING - barely audible glitches
  230.       delay(100); //Do NOTHING - sounds fine
  231.       Serial.print(" Idle time: ");
  232.       Serial.print(millis() - start_time, DEC);
  233.       Serial.println("ms");
  234.       //Look at that! We can actually do quite a lot without the audio glitching
  235.  
  236.       //Now that we've completely emptied the VS1053 buffer (2048 bytes) let's see how much
  237.       //time the VS1053 keeps the DREQ line high, indicating it needs to be fed
  238.       replenish_time = millis();
  239.     }
  240.  
  241.  
  242.     if(need_data == TRUE){ //This is here in case we haven't had any free time to load new data
  243.       if(!track.read(mp3DataBuffer, sizeof(mp3DataBuffer))) { //Go out to SD card and try reading 32 new bytes of the song
  244.         //Oh no! There is no data left to read!
  245.         //Time to exit
  246.         break;
  247.       }
  248.       need_data = FALSE;
  249.     }
  250.  
  251.     //Once DREQ is released (high) we now feed 32 bytes of data to the VS1053 from our SD read buffer
  252.     digitalWrite(MP3_XDCS, LOW); //Select Data
  253.     for(int y = 0 ; y < sizeof(mp3DataBuffer) ; y++) {
  254.       SPI.transfer(mp3DataBuffer[y]); // Send SPI byte
  255.     }
  256.  
  257.     digitalWrite(MP3_XDCS, HIGH); //Deselect Data
  258.     need_data = TRUE; //We've just dumped 32 bytes into VS1053 so our SD read buffer is empty. Set flag so we go get more data
  259.   }
  260.  
  261.   while(!digitalRead(MP3_DREQ)) ; //Wait for DREQ to go high indicating transfer is complete
  262.   digitalWrite(MP3_XDCS, HIGH); //Deselect Data
  263.  
  264.   track.close(); //Close out this track
  265.  
  266.   sprintf(errorMsg, "Track %s done!", fileName);
  267.   Serial.println(errorMsg);
  268. }
  269.  
  270. //Write to VS10xx register
  271. //SCI: Data transfers are always 16bit. When a new SCI operation comes in
  272. //DREQ goes low. We then have to wait for DREQ to go high again.
  273. //XCS should be low for the full duration of operation.
  274. void Mp3WriteRegister(unsigned char addressbyte, unsigned char highbyte, unsigned char lowbyte){
  275.   while(!digitalRead(MP3_DREQ)) ; //Wait for DREQ to go high indicating IC is available
  276.   digitalWrite(MP3_XCS, LOW); //Select control
  277.  
  278.   //SCI consists of instruction byte, address byte, and 16-bit data word.
  279.   SPI.transfer(0x02); //Write instruction
  280.   SPI.transfer(addressbyte);
  281.   SPI.transfer(highbyte);
  282.   SPI.transfer(lowbyte);
  283.   while(!digitalRead(MP3_DREQ)) ; //Wait for DREQ to go high indicating command is complete
  284.   digitalWrite(MP3_XCS, HIGH); //Deselect Control
  285. }
  286.  
  287. //Read the 16-bit value of a VS10xx register
  288. unsigned int Mp3ReadRegister (unsigned char addressbyte){
  289.   while(!digitalRead(MP3_DREQ)) ; //Wait for DREQ to go high indicating IC is available
  290.   digitalWrite(MP3_XCS, LOW); //Select control
  291.  
  292.   //SCI consists of instruction byte, address byte, and 16-bit data word.
  293.   SPI.transfer(0x03);  //Read instruction
  294.   SPI.transfer(addressbyte);
  295.  
  296.   char response1 = SPI.transfer(0xFF); //Read the first byte
  297.   while(!digitalRead(MP3_DREQ)) ; //Wait for DREQ to go high indicating command is complete
  298.   char response2 = SPI.transfer(0xFF); //Read the second byte
  299.   while(!digitalRead(MP3_DREQ)) ; //Wait for DREQ to go high indicating command is complete
  300.  
  301.   digitalWrite(MP3_XCS, HIGH); //Deselect Control
  302.  
  303.   int resultvalue = response1 << 8;
  304.   resultvalue |= response2;
  305.   return resultvalue;
  306. }
  307.  
  308. //Set VS10xx Volume Register
  309. void Mp3SetVolume(unsigned char leftchannel, unsigned char rightchannel){
  310.   Mp3WriteRegister(SCI_VOL, leftchannel, rightchannel);
  311. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement