#include #include #include #include SdFat sd; SdFile file; SFEMP3Shield MP3player; #define ASCIIdigit(byte1) (byte1 - '0') #define ASCIIhex(byte1, byte2) (((byte1 < 'A') ? byte1 - '0' : byte1 - 'A' + 10) << 4) + \ ((byte2 < 'A') ? byte2 - '0' : byte2 - 'A' + 10) #define AMP_SHDN 4 #define STATUS_LED 3 #define GPIO 5 #define MP3_CS 6 #define MP3_DCS 7 #define MP3_RESET 8 #define SD_CS 9 #define SERIAL_BUF_SIZE 64 char serial_buf[SERIAL_BUF_SIZE]; int serial_buf_pos=0; #define PLAYLIST_MAX 10 unsigned char playlist[PLAYLIST_MAX]; unsigned char playlistSize, playlistPos; unsigned char activeFlag=0; unsigned char startupSuccess=0; unsigned char currentTrack; unsigned char gpio_flag; // printf macro void p(char *fmt, ... ) { char tmp[128]; // resulting string limited to 128 chars va_list args; va_start (args, fmt ); vsnprintf(tmp, 128, fmt, args); va_end (args); Serial.print(tmp); } void setup() { unsigned char temp; pinMode(STATUS_LED, OUTPUT); pinMode(AMP_SHDN, OUTPUT); pinMode(MP3_CS, OUTPUT); pinMode(MP3_DCS, OUTPUT); pinMode(GPIO, OUTPUT); Serial.begin(9600); digitalWrite(MP3_CS, 1); // disable VS1003 SPI while we init the SD card digitalWrite(MP3_DCS, 1); digitalWrite(AMP_SHDN, 0); // turn off amp for startup // initialize the SD card if(!sd.begin(SD_SEL, SPI_FULL_SPEED)) goto fail; //sd.initErrorHalt(); // newly required in 1.01.00 and higher temp = MP3player.begin(); if(temp == 0) // initialize the VS1003 { //delay(2000); MP3player.setVolume(0); // start at max volume startupSuccess=1; } else { fail: startupSuccess=0; while (1) { digitalWrite(STATUS_LED, 1); delay(1000); digitalWrite(STATUS_LED, 0); delay(1000); } } } //do something else now void loop() { unsigned char num; //Serial.println("I'm bored!"); //delay(2000); while (Serial.available() > 0) // if data in serial RX buffer { serial_buf[serial_buf_pos++] = Serial.read(); // add byte to our own buffer if (serial_buf[serial_buf_pos-1] == '\r' || serial_buf_pos >= SERIAL_BUF_SIZE) { switch (serial_buf[0]) { case 'E': // enqueue track if (serial_buf_pos != 4) goto finish_serial; if (!activeFlag) goto case_p; // we aren't currently playing anything, so we can just play it now num = ASCIIhex(serial_buf[1], serial_buf[2]); if (playlistSize+1 < PLAYLIST_MAX) { playlist[playlistSize++] = num; p("-Enqueuing %d\r", num); } else { Serial.println("-Playlist full.\r'"); } break; case 'L': // loop track if (serial_buf_pos != 4) goto finish_serial; num = ASCIIhex(serial_buf[1], serial_buf[2]); playTrack(num,1); p("-Looping %d\r", num); break; case 'P': // play numeric track (hex) if (serial_buf_pos != 4) goto finish_serial; case_p: num = ASCIIhex(serial_buf[1], serial_buf[2]); if (playTrack(num,0)) { p("-Playing %d\r", num); } else { p("E03\r"); // report error to sensor node } break; case 'p': // play numeric track (decimal) if (serial_buf_pos != 5) goto finish_serial; num = (ASCIIdigit(serial_buf[1]) * 100) + (ASCIIdigit(serial_buf[2]) * 10) + ASCIIdigit(serial_buf[3]); if (playTrack(num,0)) { p("-Playing %d\r", num); } else { p("E03\r"); // report error to sensor node } break; case 'S': // stop MP3player.stopTrack(); playlistPos = playlistSize = 0; break; case 'V': // volume if (serial_buf_pos != 4) goto finish_serial; //num = (serial_buf[1] - '0') * 100 + (serial_buf[2] - '0') * 10 + (serial_buf[3] - '0'); num = ASCIIhex(serial_buf[1], serial_buf[2]); MP3player.setVolume(num, num); p("-Volume %d\r", num); break; case 'I': // info //MP3player.getAudioInfo(); break; case 'A': digitalWrite(AMP_SHDN, 1); break; case 'a': digitalWrite(AMP_SHDN, 0); break; default: break; } finish_serial: serial_buf_pos = 0; } } if (activeFlag && !MP3player.isPlaying()) // check if we're done after playing a file { play_finished(); } } void play_finished() { //playback is complete if (playlistSize && (playlistPos < playlistSize)) // do we have more tracks in the playlist? { playTrack(playlist[playlistPos++], 0); // play next track return; } else { playlistPos = playlistSize = 0; } //digitalWrite(AMP_SHDN, 0); digitalWrite(STATUS_LED, 0); activeFlag = 0; } unsigned char playTrack(unsigned char track, unsigned char loopTrack) { // play a track based on first 3 characters of file name (only files in root directory) // for example, track 15 should be named "015XXXXXXX.mp3", where X is any character // only the first 3 digits matter. the rest of the file name can be anything // if there are multiple files with the same first 3 digits, the first file will play char desiredTrack[] = "000"; char currentFile[13]; unsigned char ret; sprintf(desiredTrack, "%03d", track); // convert track into 3 character string if (MP3player.isPlaying()) // if we are currently playing something, we have to stop (can't read the SD card, SPI is occupied) { MP3player.stopTrack(); } sd.chdir("/",true); // open root directory of SD card while (file.openNext(sd.vwd(), O_READ)) { // loop through all files file.getFilename(currentFile); // get current file's file name file.close(); if (strncmp(desiredTrack, currentFile, 3) == 0) // compare first 3 characters of file name { digitalWrite(STATUS_LED, 1); digitalWrite(AMP_SHDN, 1); if (loopTrack) { MP3player.loopMP3(currentFile); // loop the file! } else { ret = MP3player.playMP3(currentFile); // play the file! } if (MP3player.isPlaying()) // check if it's playing { currentTrack = track; activeFlag = 1; return 1; // playback success } else { digitalWrite(STATUS_LED, 0); //digitalWrite(AMP_SHDN, 0); return 0; // playback failed } } } return 0; // couldn't find the file }