This program utilizes an LCD, RPG, 8 ohm speaker, and SD card to provide the basic functions of a music player. The project cycles through the SD card for .wav files and tracks elapsed time. See http://mbed.org/users/rsartin3/notebook/audio-player/ for more information.
Dependencies: DebounceIn RPG SDFileSystem TextLCD mbed wav_header wave_player
Diff: main.cpp
- Revision:
- 0:040129c3d961
- Child:
- 1:f31b40073d35
diff -r 000000000000 -r 040129c3d961 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Mar 04 22:37:29 2013 +0000 @@ -0,0 +1,351 @@ +/* + MUSIC PLAYER HOORAY + wumbo +*/ + +#include "mbed.h" +#include "DebounceIn.h" +#include "SDFileSystem.h" +#include "wave_player.h" +#include "TextLCD.h" +#include "RPG.h" +#include "Wav_Support_File.h" +#include "string" + +// Debug mode on: 1 +#define DEBUG 0 + +// -- Debug I/O -- +DigitalOut myled(LED1); +DigitalOut myled2(LED2); +DigitalOut myled3(LED3); +DigitalOut myled4(LED4); +Serial pc(USBTX, USBRX); + +// -- RPG I/O -- +RPG rpg(p17, p16, p19); + +// -- Text LCD I/O -- +TextLCD lcd(p25, p26, p27, p28, p29, p30); // rs, e, d4-d7 + +// -- SD card I/O -- +SDFileSystem sd(p5, p6, p7, p8, "sd"); // the pinout on the mbed Cool Components workshop board +DigitalIn sdDetect(p9); // Grounded if no card is inserted, Requires pull up + +// -- Wave Player I/O -- +AnalogOut DACout(p18); +wave_player waver(&DACout); + +// Timer Junk +Ticker songTick; +time_t time_i; + +struct playlist { + // Doubly-linked list to easily traverse between filenames + char s_name[30]; // File name without .wav extension + playlist *prev; // Pointer to next filename + playlist *next; // Pointer to previous filename +}; // Structure name courtesy of Layla Marshall + +void insert( struct playlist *root, string songName) +{ + /* Insert + Put a new songname at the end of the linked list + @param *head: Pointer to root node of playlist + @param songName: String holding the song name to be inserted + */ + playlist *new1=(playlist *) malloc(sizeof(playlist)); // Create new playlist node + playlist *temp = root; // Start at root node + + while(temp -> next != NULL) + { + temp = temp -> next; // Traverse playlist until at last node + } + + strcpy(new1 -> s_name, songName.c_str()); // Copy song name into the file name of the node + new1 -> next = NULL; // Set next pointer as null + new1 -> prev = temp; // Set previous pointer to the last mode + temp -> next = new1; // Hhave last node point to newly created node +}; + +int createPlaylist(const char *location, playlist *root) { + /* createPlaylist + Read from given directory and if a file has a .wav extension, add it to the playlist. Output the number of songs added to playlist + @param *location: Location to look for .wav files, tested for base SD card directory "/sd/" + @param *root: Pointer to root of a playlist. The playlist should be empty except for the root node which will be overwritten + @out count: Outputs the number of songs added to the playlist + */ + DIR *d; // Directory pointer + dirent *file; // dirent to get file name + // playlist *curr = root; // + int count = 0; // count of songs added to playlist + + if(DEBUG) pc.printf("\n\rWell... Let's get started!\r\n"); + if((d = opendir(location)) == NULL) { //Attempt to open directory at given location + // If Error + lcd.cls(); + lcd.printf("Unable to open directory!"); + if(DEBUG) pc.printf("[!] Unable to open directory\r\n"); + }else{ + // If Successful + while((file = readdir(d)) !=NULL) { // While able to read files in directory + if(DEBUG) pc.printf("Parsing file: %s\n\r", file->d_name); + + string str(file->d_name); // Parse filename + size_t exten = str.find_last_of("."); // Find final '.' + + if(DEBUG) pc.printf("path: %s\n\r", (str.substr(0,exten)).c_str()); // Prints everything before final '.' + if(DEBUG) pc.printf("file: %s\n\r", (str.substr(exten+1)).c_str()); // Prints everything after final '.' + + // If the extension is wav or WAV, add to playlist. Otherwise read in next file + if((str.substr(exten+1)).compare("wav") == 0 || (str.substr(exten+1)).compare("WAV") == 0 ){ + if(DEBUG) pc.printf("This is a file that I like very much!\r\n"); + + if(count == 0){ // If still at root node + count++; // Increment count + strcpy(root->s_name, (str.substr(0,exten)).c_str()); //Copy filename into root node + // curr = root; + }else{ + count++; // Increment count + insert(root,str.substr(0,exten)); // Add new song to playlist + } + } + } + closedir(d); // Close directory + } + return count; //Return number of songnames added to playlist +} + +void printList(playlist *root) { + /* printList + (DEBUG function) Traverses the playlist and writes all songnames to the pc + @param *root: pointer to playlist to print + */ + int count = 1; // Track number, starts at 1 + struct playlist *curr = root; // playlist node used to traverse playlist + pc.printf("\n\rPrinting File Names:\n\r"); + pc.printf("Track #%d: %s\n\r", count, curr->s_name); //Root node song name + + while(curr -> next != NULL) { // While there is a following node... + curr = curr -> next; // Move to it + count++; // Increment song count + pc.printf("Track #%d: %s\n\r", count, curr->s_name); // And print the current song name + } +} + +void freeList(playlist ** root) { +/* freeList + * Deallocate playlist structure memory, including root node + * Sets root pointer to NULL so old memory location cannot be accessed + * usage: freeList(&root); + */ + +playlist * node = *root; +playlist * temp; + +if(node == NULL) + return; // Protect against an empty root node (no playlist) + + while(node != NULL) { + temp = node->next; + free(node); + node = temp; + } + *root = NULL; +} + +void deleteList(playlist * root) { +/* deleteList + * Deallocates all non-root playlist structures, leaving the root + * node with a default "No wavefile" string and null'ed pointers + */ + +if(root == NULL) + return; + + freeList(&(root->next)); + + root->next = NULL; + root->prev = NULL; + strcpy(root->s_name, "No wavefile"); +} + +void songClock() { + time_t time_f; + time_f = time(NULL); + + // if(DEBUG) printf("Time Elapsed: %d. (Start: %d, Stop: %d)\n\r", time_f - time_i, time_i, time_f); + lcd.locate(6,1); + lcd.printf("%d", time_f - time_i + 1); + +} + +int main() { + // --- Control Variables --- + int songCount = 0; // Number of songs in the playlist linked list + + bool sdInsert = false; + bool firstList = false; // Is it first instance of reading from SD card + bool playlistExist = false; + + int rpgTick = 0; // Slow down RPG turning speed + const int rpgThresh = 5; + + FILE *wave_file; + string mySongName = "Invalid"; + unsigned char wave_array[30]; + + + // --- Debug That Junk --- + lcd.printf("Hello World!"); + if(DEBUG) pc.printf("Hello World!\n\r"); + + // --- Initialize Playlist --- + struct playlist *root; // Create root node + root = (playlist *)malloc(sizeof(struct playlist)); + root -> next = NULL; // Only node + root -> prev = NULL; + strcpy(root->s_name, "No wavefile"); // Put song name as "No wavfile" + if(DEBUG) printList(root); + + struct playlist *curr = root; // Current node for playlist traversal + + // --- Internal Pull-ups --- + sdDetect.mode(PullUp); + wait(.001); + + /* ================================ + =========== Start Main Program ============ + ================================ + */ + while(1) { + // ------------- No SD Card Detected ------------- + // Current bug... When SD card is removed and replaced, stays in not detected loop... or something + myled = sdDetect; + myled2 = 0; + if(!sdDetect) + { + if(DEBUG) { + myled2 = 1 - myled2; + wait_ms(50); + } + sdInsert = false; // Note no card is inserted + if(playlistExist){ + playlistExist = false; + deleteList(root); + curr = root; + } + lcd.cls(); + lcd.printf("No SD Card!"); + if(DEBUG) pc.printf("No SD card detected! Please insert one\n\r"); + } + // ------------ SD Card Detected ------------ + else { + // ---------- Set-up Playlist ---------- + if(!sdInsert) { + // If first loop after inserting SD card + sdInsert = true; + songCount = createPlaylist("/sd/", root); // Create playlist from .wav files in "/sd/" + playlistExist = true; // A playlist now exists + firstList = true; // First time through playlist + curr = root; // Put current at root node + if(DEBUG) printList(root); + lcd.cls(); // Display number of songs found + lcd.printf("Songs found: %d", songCount); + } + + // ----------------- Turn RPG Clockwise ----------------- + if(rpg.dir() == 1) { + // If turned clockwise, see if increment is greater than threshold + if(rpgTick < rpgThresh){ + rpgTick++; //if not increment and do nothing else + if(DEBUG) printf("rpgThresh: %d\r\n", rpgThresh); + } + else { + rpgTick = 0; // Clear rpg counter + + if(firstList){ // If first time controlling just put display node song name + firstList = false; + lcd.cls(); + lcd.printf("%s", curr->s_name); + } + else { // Otherwise increment if possible and display song name + if(curr -> next != NULL){ + curr = curr -> next; + lcd.cls(); + lcd.printf("%s",curr->s_name); + } + } + } + } + // ----------------- Turn RPG Counter Clockwise ----------------- + else { + if(rpg.dir() == -1) { + // Check if increment is greater than threshold + if(rpgTick < rpgThresh) { + rpgTick++; + } + else { + rpgTick = 0; // Clear increment + + if(!firstList ){ //if on song selection, decrement if possible and displays song name + if(curr -> prev != NULL){ + curr = curr -> prev; + lcd.cls(); + lcd.printf("%s",curr->s_name); + } + } + } + } + } + // ----------------- Press RPG Button ----------------- + if(rpg.pb()) { + // if push button is pressed ... SOMETHING + lcd.cls(); + lcd.printf("Song playing"); + + //Check sd card maybes + + // File location name thing + mySongName.erase(); + mySongName.append("/sd/"); + mySongName.append(curr->s_name); + mySongName.append(".wav"); + + // Open File + if(DEBUG) printf("Appended Name: %s\n\r", mySongName.c_str()); + wave_file=fopen(mySongName.c_str(),"r"); + + wave_file_check(wave_array, wave_file); + if(DEBUG) printf("Sample Rate: %d\r\n", wave_file_info.samples_per_second); + fclose(wave_file); + + lcd.locate(0,1); + lcd.printf("Time: / sec"); + lcd.locate(10,1); + lcd.printf("%d", (int)(wave_file_info.length_of_file / (wave_file_info.samples_per_second * wave_file_info.number_of_channels * wave_file_info.bytes_per_sample)) ); + + + wave_file=fopen(mySongName.c_str(),"r"); + + songTick.attach(&songClock, 1.0); + set_time(1357020000); + time_i = time(NULL); + + if(DEBUG) printf("Start Song\r\n"); + waver.play(wave_file); + + if(DEBUG) printf("Close Song!\r\n"); + fclose(wave_file); + + songTick.detach(); + time_i = 0; + + lcd.cls(); + lcd.printf(curr->s_name); + if(DEBUG) printf("Finished mai SONG!\r\n"); + } + if(DEBUG) printf("rpgTick: %d \r\n",rpgTick); + } + } +}