Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * example sketch to play audio file(s) in a directory, using the mp3 library
- * for playback and the arduino sd library to read files from a microsd card.
- * pins are setup to work well for teensy 2.0. double-check if using arduino.
- *
- * originally based on frank zhao's player: http://frank.circleofcurrent.com/
- * utilities adapted from previous versions of the functions by matthew seal.
- *
- * (c) 2011 david sirkin [email protected]
- * akil srinivasan [email protected]
- */
- // first step is to include (arduino) sd, eeprom, and (our own) mp3 and lcd libraries.
- #include <SD.h>
- #include <EEPROM.h>
- #include <mp3.h>
- #include <mp3conf.h>
- #include <nokia_5110_lcd.h>
- /*IF we are not using the Graphics or Bitmap capabilities
- of the LCD, save code space with these #defines*/
- #define NO_GRAPHICS
- #define NO_BITMAP
- // setup microsd, decoder, and lcd chip pins
- #define sd_cs 12 // 'chip select' for microsd card
- #define mp3_cs 21 // 'command chip select' to cs pin
- #define dcs 20 // 'data chip select' to bsync pin
- #define rst 18 // 'reset' to decoder's reset pin
- #define dreq 19 // 'data request line' to dreq pin
- //LCD PINS
- #define LCD_PWR 10
- #define LCD_SCE 9
- #define LCD_RESET 8
- #define LCD_DC 4
- // read_buffer is the amount of data read from microsd, then sent to decoder.
- #define read_buffer 512 // size of the microsd read buffer
- #define mp3_vol 175 // default volume: 0=min, 254=max
- // file names are 13 bytes max (8 + '.' + 3 + '\0'), and the file list should
- // fit into the eeprom. for example, 13 * 40 = 520 bytes of eeprom are needed
- // to store a list of 40 songs. if you use shorter file names, or if your mcu
- // has more eeprom, you can change these.
- #define max_name_len 13
- #define max_num_songs 40
- // next steps, declare the variables used later to represent microsd objects.
- Sd2Card card; // top-level represenation of card
- SdVolume volume; // sd partition, not audio volume
- SdFile sd_root, sd_file; // sd_file is the child of sd_root
- // declare lcd object as well
- Nokia_5110_lcd lcd(LCD_PWR, LCD_DC, LCD_SCE, LCD_RESET);
- // store the number of songs in this directory, and the current song to play.
- unsigned char num_songs = 0, current_song = 0;
- // an array to hold the current_song's file name in ram. every file's name is
- // stored longer-term in the eeprom. this array is used for sd_file.open().
- char fn[max_name_len];
- // the program runs as a state machine. the 'state' enum includes the states.
- // 'current_state' is the default as the program starts. add new states here.
- enum state { DIR_PLAY, MP3_PLAY, IDLE };
- state current_state = DIR_PLAY;
- // you must open any song file that you want to play using sd_file_open prior
- // to fetching song data from the file. you can only open one file at a time.
- void sd_file_open() {
- map_current_song_to_fn();
- sd_file.open(&sd_root, fn, FILE_READ);
- // if you prefer to work with the current song index (only) instead of file
- // names, this version of the open command should also work for you:
- // sd_file.open(&sd_root, current_song, FILE_READ);
- }
- void mp3_play() {
- unsigned char bytes[read_buffer]; // buffer to read and send to the decoder
- unsigned int bytes_to_read; // number of bytes read from microsd card
- // send read_buffer bytes to be played. Mp3.play() tracks the index pointer
- // within the song being played of where to get the next read_buffer bytes.
- bytes_to_read = sd_file.read(bytes, read_buffer);
- Mp3.play(bytes, bytes_to_read);
- // bytes_to_read should only be less than read_buffer when the song's over.
- if(bytes_to_read < read_buffer) {
- sd_file.close();
- current_state = IDLE;
- }
- }
- // continue to play the current (playing) song, until there are no more songs
- // in the directory to play.
- void dir_play() {
- if (current_song < num_songs) {
- mp3_play();
- // if current_state is IDLE, then the currently playing song just ended.
- // in that case, increment to get the next song to play, open that file,
- // and return to the DIR_PLAY state (which will then play that song).
- // if we played the last part of the last song, we don't do anything,
- // and the current_state is already set to IDLE from mp3_play()
- if (current_state == IDLE && current_song < (num_songs - 1)) {
- current_song++;
- sd_file_open();
- current_state = DIR_PLAY;
- }
- }
- }
- // setup is pretty straightforward. initialize serial communication (used for
- // the following error messages), microsd card objects, mp3 library, and open
- // the first song in the root library to play.
- void setup() {
- Serial.begin(9600);
- pinMode(SS_PIN, OUTPUT); //SS_PIN must be output to use SPI
- pinMode(5, INPUT_PULLUP);
- attachInterrupt(0, pause, RISING);
- // the default state of the mp3 decoder chip keeps the SPI bus from
- // working with other SPI devices, so we have to initialize it first.
- Mp3.begin(mp3_cs, dcs, rst, dreq);
- // initialize the microsd (which checks the card, volume and root objects).
- sd_card_setup();
- //initialize the LCD
- lcd.init(40); //parameter is contrast value, between 0 [low] and 127 [high]
- lcd.clear();
- // initialize the mp3 library, and set default volume. 'mp3_cs' is the chip
- // select, 'dcs' is data chip select, 'rst' is reset and 'dreq' is the data
- // request. the decoder raises the dreq line (automatically) to signal that
- // it's input buffer can accommodate 32 more bytes of incoming song data.
- // we need to set the SPI speed with the mp3 initialize function since
- // it is the limiting factor, so we call its init function again.
- Mp3.begin(mp3_cs, dcs, rst, dreq);
- Mp3.volume(mp3_vol);
- // putting all of the root directory's songs into eeprom saves flash space.
- sd_dir_setup();
- // the program is setup to enter DIR_PLAY mode immediately, so this call to
- // open the root directory before reaching the state machine is needed.
- sd_file_open();
- //Test that LCD still works with other SPI devices
- lcd.writeString( 0, 0, "Barebones Mp3!", MODE_NORMAL);
- }
- // the state machine is setup (at least, at first) to open the microsd card's
- // root directory, play all of the songs within it, close the root directory,
- // and then stop playing. change these, or add new actions here.
- // the DIR_PLAY state plays all of the songs in a directory and then switches
- // into IDLE when done. the MP3_PLAY state plays one specified song, and then
- // switches into IDLE. this example program doesn't enter the MP3_PLAY state,
- // as its goal (for now) is just to play all the songs. you can change that.
- volatile boolean paused = false;
- void loop() {
- if(paused){
- return;
- }
- switch(current_state) {
- case DIR_PLAY:
- dir_play();
- break;
- case MP3_PLAY:
- mp3_play();
- break;
- case IDLE:
- break;
- }
- }
- void pause(){
- paused = !paused;
- Serial.println(paused);
- }
Advertisement
Add Comment
Please, Sign In to add comment