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/wav-player-with-RPG-based-menu/ for more information.
Dependencies: DebounceIn RPG SDFileSystem TextLCD mbed wav_header wave_player
Fork of Audio_Player by
main.cpp
00001 /* 00002 * Audio Player 00003 * Josh Dunn & Ryan Sartin 00004 */ 00005 00006 #include "mbed.h" 00007 #include "DebounceIn.h" 00008 #include "SDFileSystem.h" 00009 #include "wave_player.h" 00010 #include "TextLCD.h" 00011 #include "RPG.h" 00012 #include "Wav_Support_File.h" 00013 #include "string" 00014 00015 // Debug mode on: 1 00016 #define DEBUG 0 00017 00018 // -- Debug I/O -- 00019 DigitalOut myled(LED1); 00020 DigitalOut myled2(LED2); 00021 DigitalOut myled3(LED3); 00022 DigitalOut myled4(LED4); 00023 Serial pc(USBTX, USBRX); 00024 00025 // -- RPG I/O -- 00026 RPG rpg(p17, p16, p19); 00027 00028 // -- Text LCD I/O -- 00029 TextLCD lcd(p25, p26, p27, p28, p29, p30); // rs, e, d4-d7 00030 00031 // -- SD card I/O -- 00032 SDFileSystem sd(p5, p6, p7, p8, "sd"); // the pinout on the mbed Cool Components workshop board 00033 DigitalIn sdDetect(p9); // Grounded if no card is inserted, Requires pull up 00034 00035 // -- Wave Player I/O -- 00036 AnalogOut DACout(p18); 00037 wave_player waver(&DACout); 00038 00039 // Ticker for interrupting song 00040 Ticker songTick; 00041 time_t time_i; 00042 00043 struct playlist { 00044 // Doubly-linked list to easily traverse between filenames 00045 char s_name[30]; // File name without .wav extension 00046 playlist *prev; // Pointer to next filename 00047 playlist *next; // Pointer to previous filename 00048 }; 00049 00050 void insert( struct playlist *root, string songName) 00051 { 00052 /* Insert 00053 Put a new songname at the end of the linked list 00054 @param *head: Pointer to root node of playlist 00055 @param songName: String holding the song name to be inserted 00056 */ 00057 playlist *new1=(playlist *) malloc(sizeof(playlist)); // Create new playlist node 00058 playlist *temp = root; // Start at root node 00059 00060 while(temp -> next != NULL) 00061 { 00062 temp = temp -> next; // Traverse playlist until at last node 00063 } 00064 00065 strcpy(new1 -> s_name, songName.c_str()); // Copy song name into the file name of the node 00066 new1 -> next = NULL; // Set next pointer as null 00067 new1 -> prev = temp; // Set previous pointer to the last mode 00068 temp -> next = new1; // Hhave last node point to newly created node 00069 }; 00070 00071 int createPlaylist(const char *location, playlist *root) { 00072 /* createPlaylist 00073 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 00074 @param *location: Location to look for .wav files, tested for base SD card directory "/sd/" 00075 @param *root: Pointer to root of a playlist. The playlist should be empty except for the root node which will be overwritten 00076 @out count: Outputs the number of songs added to the playlist 00077 */ 00078 DIR *d; // Directory pointer 00079 dirent *file; // dirent to get file name 00080 // playlist *curr = root; 00081 int count = 0; // count of songs added to playlist 00082 00083 if(DEBUG) pc.printf("\n\rWell... Let's get started!\r\n"); 00084 if((d = opendir(location)) == NULL) { // Attempt to open directory at given location 00085 // If Error 00086 lcd.cls(); 00087 lcd.printf("Unable to open directory!"); 00088 if(DEBUG) pc.printf("[!] Unable to open directory\r\n"); 00089 }else{ 00090 // If Successful 00091 while((file = readdir(d)) !=NULL) { // While able to read files in directory 00092 if(DEBUG) pc.printf("Parsing file: %s\n\r", file->d_name); 00093 00094 string str(file->d_name); // Parse filename 00095 size_t exten = str.find_last_of("."); // Find final '.' 00096 00097 if(DEBUG) pc.printf("path: %s\n\r", (str.substr(0,exten)).c_str()); // Prints everything before final '.' 00098 if(DEBUG) pc.printf("file: %s\n\r", (str.substr(exten+1)).c_str()); // Prints everything after final '.' 00099 00100 // If the extension is wav or WAV, add to playlist. Otherwise read in next file 00101 if((str.substr(exten+1)).compare("wav") == 0 || (str.substr(exten+1)).compare("WAV") == 0 ){ 00102 if(DEBUG) pc.printf("This is a file that I like very much!\r\n"); 00103 00104 if(count == 0){ // If still at root node 00105 count++; // Increment count 00106 strcpy(root->s_name, (str.substr(0,exten)).c_str()); // Copy filename into root node 00107 // curr = root; 00108 }else{ 00109 count++; // Increment count 00110 insert(root,str.substr(0,exten)); // Add new song to playlist 00111 } 00112 } 00113 } 00114 closedir(d); // Close directory 00115 } 00116 return count; // Return number of songnames added to playlist 00117 } 00118 00119 void printList(playlist *root) { 00120 /* printList 00121 (DEBUG function) Traverses the playlist and writes all songnames to the pc 00122 @param *root: pointer to playlist to print 00123 */ 00124 int count = 1; // Track number, starts at 1 00125 struct playlist *curr = root; // playlist node used to traverse playlist 00126 pc.printf("\n\rPrinting File Names:\n\r"); 00127 pc.printf("Track #%d: %s\n\r", count, curr->s_name); //Root node song name 00128 00129 while(curr -> next != NULL) { // While there is a following node... 00130 curr = curr -> next; // Move to it 00131 count++; // Increment song count 00132 pc.printf("Track #%d: %s\n\r", count, curr->s_name); // And print the current song name 00133 } 00134 } 00135 00136 void freeList(playlist ** root) { 00137 /* freeList 00138 * Deallocate playlist structure memory, including root node 00139 * Sets root pointer to NULL so old memory location cannot be accessed 00140 * usage: freeList(&root); 00141 */ 00142 00143 playlist * node = *root; 00144 playlist * temp; 00145 00146 if(node == NULL) 00147 return; // Protect against an empty root node (no playlist) 00148 00149 while(node != NULL) { 00150 temp = node->next; 00151 free(node); 00152 node = temp; 00153 } 00154 *root = NULL; 00155 } 00156 00157 void deleteList(playlist * root) { 00158 /* deleteList 00159 * Deallocates all non-root playlist structures, leaving the root 00160 * node with a default "No wavefile" string and null'ed pointers 00161 */ 00162 00163 if(root == NULL) 00164 return; 00165 00166 freeList(&(root->next)); 00167 00168 root->next = NULL; 00169 root->prev = NULL; 00170 strcpy(root->s_name, "No wavefile"); 00171 } 00172 00173 void songClock() { 00174 /* 00175 * songClock 00176 * Reads in time and compares it to time_i, the global variable 00177 * Used with Ticker API to count number of seconds elapsed since song started playing 00178 */ 00179 time_t time_f; 00180 time_f = time(NULL); 00181 00182 // if(DEBUG) printf("Time Elapsed: %d. (Start: %d, Stop: %d)\n\r", time_f - time_i, time_i, time_f); 00183 lcd.locate(6,1); 00184 lcd.printf("%d", time_f - time_i + 1); 00185 } 00186 00187 int main() { 00188 // --- Control Variables --- 00189 int songCount = 0; // Number of songs in the playlist linked list 00190 00191 bool sdInsert = false; 00192 bool firstList = false; // Is it first instance of reading from SD card 00193 bool playlistExist = false; 00194 00195 // RPG Variables 00196 int rpgTick = 0; // Slow down RPG turning speed 00197 const int rpgThresh = 5; 00198 00199 // File interaction variables 00200 FILE *wave_file; 00201 string mySongName = "Invalid"; 00202 unsigned char wave_array[30]; 00203 00204 00205 // --- Debug That Junk --- 00206 lcd.printf("Hello World!"); 00207 if(DEBUG) pc.printf("Hello World!\n\r"); 00208 00209 // --- Initialize Playlist --- 00210 struct playlist *root; // Create root node 00211 root = (playlist *)malloc(sizeof(struct playlist)); 00212 root -> next = NULL; // Only node 00213 root -> prev = NULL; 00214 strcpy(root->s_name, "No wavefile"); // Put song name as "No wavfile" 00215 if(DEBUG) printList(root); 00216 00217 struct playlist *curr = root; // Current node for playlist traversal 00218 00219 // --- Internal Pull-ups --- 00220 sdDetect.mode(PullUp); 00221 wait(.001); 00222 00223 /* ================================ 00224 =========== Start Main Program ============ 00225 ================================ 00226 */ 00227 while(1) { 00228 // ------------- No SD Card Detected ------------- 00229 // Current bug... When SD card is removed and replaced, stays in not detected loop... or something 00230 if(DEBUG) myled = sdDetect; 00231 if(DEBUG) myled2 = 0; 00232 if(!sdDetect) 00233 { 00234 if(DEBUG) { 00235 myled2 = 1 - myled2; 00236 wait_ms(50); 00237 } 00238 sdInsert = false; // Note no card is inserted 00239 if(playlistExist){ // If a playlist has been made 00240 playlistExist = false; 00241 deleteList(root); // Clear playlist 00242 curr = root; 00243 } 00244 lcd.cls(); 00245 lcd.printf("No SD Card!"); 00246 if(DEBUG) pc.printf("No SD card detected! Please insert one\n\r"); 00247 } 00248 // ------------ SD Card Detected ------------ 00249 else { 00250 // ---------- Set-up Playlist ---------- 00251 if(!sdInsert) { 00252 // If first loop after inserting SD card 00253 sdInsert = true; 00254 songCount = createPlaylist("/sd/", root); // Create playlist from .wav files in "/sd/" 00255 playlistExist = true; // A playlist now exists 00256 firstList = true; // First time through playlist 00257 curr = root; // Put current at root node 00258 if(DEBUG) printList(root); 00259 lcd.cls(); // Display number of songs found 00260 lcd.printf("Songs found: %d", songCount); 00261 } 00262 00263 // ----------------- Turn RPG Clockwise ----------------- 00264 if(rpg.dir() == 1) { 00265 // If turned clockwise, see if increment is greater than threshold 00266 if(rpgTick < rpgThresh){ 00267 rpgTick++; //if not increment and do nothing else 00268 if(DEBUG) printf("rpgThresh: %d\r\n", rpgThresh); 00269 } 00270 else { 00271 rpgTick = 0; // Clear rpg counter 00272 00273 if(firstList){ // If first time controlling just put display node song name 00274 firstList = false; 00275 lcd.cls(); 00276 lcd.printf("%s", curr->s_name); 00277 } 00278 else { // Otherwise increment if possible and display song name 00279 if(curr -> next != NULL){ 00280 curr = curr -> next; 00281 lcd.cls(); 00282 lcd.printf("%s",curr->s_name); 00283 } 00284 } 00285 } 00286 } 00287 // ----------------- Turn RPG Counter Clockwise ----------------- 00288 else { 00289 if(rpg.dir() == -1) { 00290 // Check if increment is greater than threshold 00291 if(rpgTick < rpgThresh) { 00292 rpgTick++; 00293 } 00294 else { 00295 rpgTick = 0; // Clear increment 00296 00297 if(!firstList ){ //if on song selection, decrement if possible and displays song name 00298 if(curr -> prev != NULL){ 00299 curr = curr -> prev; 00300 lcd.cls(); 00301 lcd.printf("%s",curr->s_name); 00302 } 00303 } 00304 } 00305 } 00306 } 00307 // ----------------- Press RPG Button ----------------- 00308 if(rpg.pb()) { 00309 // if push button is pressed: 00310 lcd.cls(); 00311 lcd.printf("Song playing"); // Inform user song is playing 00312 00313 // File location name 00314 mySongName.erase(); 00315 mySongName.append("/sd/"); // ======== Change if not using base sd card location ===== 00316 mySongName.append(curr->s_name); // Add current song name 00317 mySongName.append(".wav"); // Add .wav extension 00318 if(DEBUG) printf("Appended Name: %s\n\r", mySongName.c_str()); 00319 00320 // Wav file header info 00321 wave_file=fopen(mySongName.c_str(),"r"); // Open file to get header information 00322 wave_file_check(wave_array, wave_file); // Put info in global variable 00323 if(DEBUG) printf("Sample Rate: %d\r\n", wave_file_info.samples_per_second); 00324 fclose(wave_file); // Close file 00325 00326 // Initialize bottom row of LCD screen 00327 lcd.locate(0,1); 00328 lcd.printf("Time: / sec"); 00329 lcd.locate(10,1); 00330 // Print length of selected wavfile 00331 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)) ); 00332 00333 // Open song for playing 00334 wave_file=fopen(mySongName.c_str(),"r"); 00335 // Start Ticker function that counts time elapsed each second 00336 songTick.attach(&songClock, 1.0); 00337 // Set reference time 00338 set_time(1357020000); 00339 time_i = time(NULL); 00340 // Play song 00341 if(DEBUG) printf("Start Song\r\n"); 00342 waver.play(wave_file); 00343 // Close file 00344 if(DEBUG) printf("Close Song!\r\n"); 00345 fclose(wave_file); 00346 00347 // End ticker function 00348 songTick.detach(); 00349 time_i = 0; 00350 00351 // Clear LCD and show selected wav file 00352 lcd.cls(); 00353 lcd.printf(curr->s_name); 00354 if(DEBUG) printf("Finished mai SONG!\r\n"); 00355 } 00356 } 00357 } 00358 }
Generated on Tue Jul 12 2022 18:37:18 by 1.7.2