Georges Kamar / Mbed 2 deprecated Speech_Controlled_Music_Player

Dependencies:   4DGL-uLCD-SE PinDetect SDFileSystem Speaker mbed wave_player

Fork of Project_MP by Angus MacLean

Revision:
3:ecf799cef1db
Parent:
2:54dcfef5c648
--- a/main.cpp	Wed Dec 06 08:51:00 2017 +0000
+++ b/main.cpp	Wed Dec 13 05:30:52 2017 +0000
@@ -7,138 +7,675 @@
 #include <vector>
 #include <string>
 
+Serial pc(USBTX, USBRX);
+Serial esp(p28, p27); // tx, rx
+DigitalOut reset(p26);
+
 //Set up LEDs
 DigitalOut myled(LED1);
 DigitalOut myled2(LED2);
 DigitalOut myled3(LED3);
 DigitalOut myled4(LED4);
 
+AnalogIn seed(p16);
+Timer t;
+ 
+int  count,ended,timeout;
+char buf[2024];
+char snd[1024];
+
+char ssid[32] = "Mbednode";     // enter WiFi router ssid inside the quotes
+char pwd [32] = "Hello";        // enter WiFi router password inside the quotes 
+
 using namespace std;
 
 SDFileSystem sd(p5, p6, p7, p8, "sd"); //SD card
 uLCD_4DGL uLCD(p9,p10,p11);
 DigitalIn sdDetect(p17); // Set up a pin for SD Card Detect
 
-PinDetect pb1(p21); // pb forup shift
-PinDetect pb2(p22); // pb fordown shift
-PinDetect pb3(p23); // pb for pause
-
-
-
-
 AnalogOut DACout(p18); //set up speaker
 wave_player waver(&DACout); //set up wave player library
 int pos = 0; // index of the song
+int currentSongIndex = -1;
 int vol = 0;
 
  
-bool playing = false; //variable for pause/play since we only have 1 pb for that
-vector<string> filenames; //filenames are stored in a vector string
-void read_file_names(char *dir) // function that reads in file names from sd cards
+bool playing = false; //variable for pause/play
+vector<string> song_names; //filenames are stored in a vector string
+vector<string> artist_names; //filenames are stored in a vector string
+string fname;
+FILE *wave_file;
+
+void SendCMD(),getreply(),ESPconfig(),ESPsetbaudrate();
+
+/* implementation of strcmp that ignores cases */
+int strcmpi(char *s1, char *s2)
+{
+    int i;
+    for (i = 0; s1[i] && s2[i]; ++i)
+    {
+        /* If characters are same or inverting the 
+           6th bit makes them same */
+        if (s1[i] == s2[i] || (s1[i] ^ 32) == s2[i])
+           continue;
+        else
+           break;
+    }
+ 
+    /* Compare the last (or first mismatching in 
+       case of not same) characters */
+    if (s1[i] == s2[i])
+        return 0;
+ 
+    // Set the 6th bit in both, then compare
+    if ((s1[i] | 32) < (s2[i] | 32)) 
+        return -1;
+    return 1;
+}
+
+void read_file_names(char *dir, vector<string> &filenames) // function that reads in file names from sd cards
 {
     DIR *dp;
     struct dirent *dirp;
     dp = opendir(dir);
     //read all directory and file names in current directory into filename vector
+    if(dp == NULL){
+        return;
+    }
+    if((dirp = readdir(dp)) != NULL) {
+        filenames.clear();
+        filenames.push_back(string(dirp->d_name));
+    }  
+    
     while((dirp = readdir(dp)) != NULL) {
         filenames.push_back(string(dirp->d_name));
     }
 }
-//interrupt handler for pb1 
-void pb1_hit_callback (void)
-{
-    // it checks for the total number of songs in the sd card..then increments the index until it reaches the last one, then resets to 0
-    int l = filenames.size();
-    if (pos < (l-1)) {
-        pos++;
-    } else if (pos == (l-1)) {
-        pos = 0;
-    }
-    string songname = filenames[pos];
-    unsigned index = songname.find(".wav");
-    songname = songname.substr(0,index);
-    uLCD.cls();
-    uLCD.printf(songname.c_str()); //it clears screen and then sets the new index song in the uLCD display
-}
-//interrupt handler for pb2
-void pb2_hit_callback (void)
+
+char pcCommand[1024] = "";
+char espCommand[1024] = "";
+string testIt = "";
+bool flag = false;
+bool espflag = false;
+
+int espcnt = -1;
+
+ void dev_recv()
 {
-    //does opposite of pb1..moves the index down..from 2nd song to 1st song via changing the index number and then calling in the vector
-    int l = filenames.size();
-    if (pos > 0) {
-        pos--;
-    } else if (pos == 0 ) {
-        pos = l-1;
+    while(esp.readable()) {
+        
+        if(espcnt == -1) {
+            espcnt++;
+            esp.getc();
+        } else {
+            espCommand[espcnt] = esp.getc();
+            espcnt++;
+                
+            if(espCommand[espcnt-1] == 34) {
+                playing = 0;
+                espflag = true;
+            }
+        } 
     }
-    string songname = filenames[pos];
-    unsigned index = songname.find(".wav");
-    songname = songname.substr(0,index);
-    uLCD.cls();
-    uLCD.printf(songname.c_str());
+
 }
-//interrupt handler for 3rd pushbutton
-void pb3_hit_callback (void)
+
+int cnt = -1;
+
+void pc_recv()
 {
-    //this interrupt handler changes the play to pause mode or vice versa
-    //this is done using the boolean playing
-    if (playing == false) {
-        playing = true; 
-    } else if (playing == true) {
-        uLCD.cls();
-        playing = false; 
-        string songname = filenames[pos];
-        unsigned index = songname.find(".wav");
-        songname = songname.substr(0,index);
-        uLCD.printf(songname.c_str());
+    while(pc.readable()) {
+        
+        if(cnt == -1) {
+            cnt++;
+            pc.getc();
+        } else {
+            pcCommand[cnt] = pc.getc();
+            cnt++;
+                
+            if(pcCommand[cnt-1] == 34) {
+                playing = 0;
+                flag = true;
+            }
+        }  
     }
 }
 
+string song = "";
+string artist = "";
 
-int main()
+void executeCommand(char command[])
 {
+
+    uLCD.printf("Command: %s\n", command); 
+  
+    char parsedCommand[20][20]; 
+    int finalCommand = 0;
+    song = "";
+    int i,j,ctr;
+ 
+    j=0; ctr=0;
+    for(i=0;i<=(strlen(command));i++)
+    {
+        // if space or NULL found, assign NULL into parsedCommand[ctr]
+        if(command[i]==' '||command[i]=='\0')
+        {
+            parsedCommand[ctr][j]='\0';
+            ctr++;  //for next word
+            j=0;    //for next word, init index to 0
+        }
+        else
+        {
+            parsedCommand[ctr][j]=command[i];
+            j++;
+        }
+    }
+
+    if(strcmp (parsedCommand[0],"play") == 0) {
+        finalCommand = 1;
+    }else if(strcmp (parsedCommand[0],"stop") == 0) {
+        finalCommand = 0;
+    }else if(strcmp (parsedCommand[0],"playnext") == 0) {
+        finalCommand = 2;
+    }else if(strcmp (parsedCommand[0],"playback") == 0) {
+        finalCommand = 3;
+    }
+    
+    
+    int ii = 2;
+    int songLength = 0;
+    int artistLength = 0;
+    
+    
+    if(strcmp (parsedCommand[0],"play") == 0) {
+        ctr--;
+        artist = "";
+        if(strcmp (parsedCommand[1],"song") == 0) {
+            while((ii <= ctr) && (strcmp (parsedCommand[ii],"artist") != 0)){
+                string songstr(parsedCommand[ii]);
+                songLength++;
+                if(ii == ctr || (strcmp (parsedCommand[ii+1],"artist") == 0)){
+                    song = song + songstr;
+                }else{
+                    song = song + songstr + " ";
+                }
+                ii++;
+            }
+            if(strcmp (parsedCommand[ii],"artist") == 0) {
+                
+                ii++;
+                while(ii <= ctr) {
+                    string artiststr(parsedCommand[ii]);
+                    artistLength++;
+                    if(ii == ctr) {
+                        artist = artist + artiststr;
+                    } else {
+                        artist = artist + artiststr + " ";
+                    }
+                    ii++;
+                }
+            }
+        }else if(strcmp (parsedCommand[1],"artist") == 0) {
+            
+            while(ii <= ctr){
+                string artiststr(parsedCommand[ii]);
+                artistLength++;
+                if(ii == ctr) {
+                    artist = artist + artiststr;
+                } else {
+                    artist = artist + artiststr + " ";
+                }
+                ii++;
+            }
+        }
+    }   
+    
     sdDetect.mode(PullUp);
      wait(.1);
      //wait after pulling up the sd card, 
-    // read file names into vector of strings
-    pb1.mode(PullUp);
-    pb2.mode(PullUp);
-    pb3.mode(PullUp);
-    //pb4.mode(PullUp);
-    // Delay for initial pullup to take effect
-    wait(.01);
-    // Setup Interrupt callback functions for a pb hit
-    pb1.attach_deasserted(&pb1_hit_callback);
-    pb2.attach_deasserted(&pb2_hit_callback);
-    pb3.attach_deasserted(&pb3_hit_callback);
-    
-    // Start sampling pb inputs using interrupts
-    pb1.setSampleFrequency();
-    pb2.setSampleFrequency();
-    pb3.setSampleFrequency();
     
     uLCD.cls();
     //detects whethere there is a SD card or not.. if not then it prints and informs the user
-    while(sdDetect ==0) {
+    while(sdDetect == 0) {
         uLCD.locate(0,0);
         uLCD.printf("Insert SD Card");
         wait(.5);
     }    
-    uLCD.cls(); 
+    uLCD.cls();
+     
     wait(.5);
     sd.disk_initialize();
-    read_file_names("/sd/");
+        
+
+    switch(finalCommand) {
+        
+        case 0:         // stop
+        {
+            fclose(wave_file);
+            uLCD.cls();
+            playing = false;
+            pc.printf("Case 0: Stop !");
+            break;
+        }
+        case 1:         // play song
+        {
+            read_file_names("/sd/wave", artist_names);
+            
+            if((strcmp (artist.c_str(), "") == 0) && (strcmp (song.c_str(), "") != 0)) {        // no artist, but song name
+                
+                int search = 1;
+                int artistCounter = 0;
+                artist = "";
+                while(search){
+                    fname = "/sd/wave/" + artist_names[artistCounter] + "/" + song + ".wav";
+                    wave_file = fopen(fname.c_str(),"r");
+                    if(wave_file != NULL){
+                        search = 0;
+                        fclose(wave_file);
+                        string artistDirectory = "/sd/wave/" + artist_names[artistCounter];
+                        char *charArtistDirectory = new char[artistDirectory.length() + 1];
+                        strcpy(charArtistDirectory, artistDirectory.c_str());
+                        read_file_names(charArtistDirectory, song_names);
+                        artist = artist_names[artistCounter];
+                        delete [] charArtistDirectory;
+                        playing = true;
+                    }else{
+                        artistCounter++;
+                    }
+                    if(artistCounter >= artist_names.size()){
+                        uLCD.printf("Song not found");
+                        break;
+                    }    
+                }
+                
+            } else if((strcmp (artist.c_str(), "") == 0) && (strcmp (song.c_str(), "") == 0)) {     // no artist, no song name. Plays random song
+
+                artist = "";
+                int seedVal = seed * 1000;
+                srand(seedVal);
+                int artistIndex = rand() % artist_names.size();
+                string artistDirectory = "/sd/wave/" + artist_names[artistIndex];
+                char *charArtistDirectory = new char[artistDirectory.length() + 1];
+                strcpy(charArtistDirectory, artistDirectory.c_str());
+                read_file_names(charArtistDirectory, song_names);
+                delete [] charArtistDirectory;
+                int songIndex = rand() % song_names.size();
+                fname = artistDirectory + "/" + song_names[songIndex];
+                song = song_names[songIndex].substr(0 ,((song_names[songIndex]).length() - 4));
+                artist = artist_names[artistIndex];
+                playing = true;
+                
+            }else if((strcmp (artist.c_str(), "") != 0) && (strcmp (song.c_str(), "") == 0)){           //no song name but artist
+                string artistDirectory = "/sd/wave/" + artist;
+                char *charArtistDirectory = new char[artistDirectory.length() + 1];
+                strcpy(charArtistDirectory, artistDirectory.c_str());
+                read_file_names(charArtistDirectory, song_names);
+                delete [] charArtistDirectory;
+                fname = artistDirectory + "/" + song_names[0];
+                song = song_names[0].substr(0, ((song_names[0]).length() - 4));
+                wave_file = fopen(fname.c_str(),"r");
+                playing = true;
+                if(wave_file == NULL){
+                    uLCD.printf("Artist not found");
+                    playing = false;
+                }
+                fclose(wave_file);
+            }else{                                                              // song name and artist
+                fname = "/sd/wave/" + artist + "/" + song + ".wav";
+                wave_file = fopen(fname.c_str(),"r");
+                playing = true;
+                if(wave_file == NULL){
+                    uLCD.printf("Song not found");
+                    playing = false;
+                }
+                fclose(wave_file);
+            }
+            
+            int entering = 1;
+            
+            while(playing == true){
+                uLCD.cls();
+                uLCD.printf("Now playing ");
+                uLCD.printf("\n%s\n%s\n", song.c_str(), artist.c_str());
+                
+                if(entering == 1) {
+                    entering = 0;
+                    string songWav = song + ".wav";
+                    char *songNameChar = new char[songWav.length() + 1];
+                    strcpy(songNameChar, songWav.c_str());
+                    for(int index=0; index<song_names.size(); index++) {
+                        char *songNameChar2 = new char[song_names[index].length() + 1];
+                        strcpy(songNameChar2, song_names[index].c_str());
+                        if(strcmpi(songNameChar, songNameChar2) == 0) {
+                            currentSongIndex = index;
+                            delete [] songNameChar2;
+                            break;
+                        }
+                        delete [] songNameChar2;
+                    }
+                    delete [] songNameChar;
+                }
+                wave_file = fopen(fname.c_str(),"r");
+                waver.play(wave_file);
+                fclose(wave_file);
+                if(!flag && !espflag){
+                    if (currentSongIndex < (song_names.size()-1)) {
+                        currentSongIndex++;
+                    } else if (currentSongIndex == (song_names.size()-1)) {
+                        currentSongIndex = 0;
+                    }
+                    song = song_names[currentSongIndex].substr(0, ((song_names[currentSongIndex]).length() - 4));
+                    fname = "/sd/wave/" + artist + "/" + song + ".wav";
+                }
+            }
+            
+      //      fclose(wave_file);
+            
+            pc.printf("Case 1: Play !");
+            break;
+        }
+        case 2:         // play next
+        {
+            
+            if(currentSongIndex != -1){
+                currentSongIndex++;
+                playing = true;
+                song = song_names[currentSongIndex].substr(0, ((song_names[currentSongIndex]).length() - 4));
+                fname = "/sd/wave/" + artist + "/" + song + ".wav";
+            }else{
+                uLCD.printf("No song playing");
+            }
+            
+            while(playing == true){
+                uLCD.cls();
+                uLCD.printf("Now playing ");
+                uLCD.printf("\n%s\n%s\n", song.c_str(), artist.c_str());
+                
+
+                wave_file = fopen(fname.c_str(),"r");
+                waver.play(wave_file);
+                fclose(wave_file);
+                if(!flag && !espflag){
+                    if (currentSongIndex < (song_names.size()-1)) {
+                        currentSongIndex++;
+                    } else if (currentSongIndex == (song_names.size()-1)) {
+                        currentSongIndex = 0;
+                    }
+                    song = song_names[currentSongIndex].substr(0, ((song_names[currentSongIndex]).length() - 4));
+                    fname = "/sd/wave/" + artist + "/" + song + ".wav";
+                }
+                
+            }
+            
+            pc.printf("Case 2: Play Next!");
+            break;
+        }    
+        case 3:         // play back
+        {
+            if(currentSongIndex != -1){
+                if (currentSongIndex > 0) {
+                    currentSongIndex--;
+                } else if (currentSongIndex == 0) {
+                    currentSongIndex = (song_names.size()-1);
+                }
+                playing = true;
+                song = song_names[currentSongIndex].substr(0, ((song_names[currentSongIndex]).length() - 4));
+                fname = "/sd/wave/" + artist + "/" + song + ".wav";
+            }else{
+                uLCD.printf("No song playing");
+            }
+            
+            while(playing == true){
+                uLCD.cls();
+                uLCD.printf("Now playing ");
+                uLCD.printf("\n%s\n%s\n", song.c_str(), artist.c_str());
+                
+
+                wave_file = fopen(fname.c_str(),"r");
+                waver.play(wave_file);
+                fclose(wave_file);
+                if(!flag && !espflag){
+                    if (currentSongIndex < (song_names.size()-1)) {
+                        currentSongIndex++;
+                    } else if (currentSongIndex == (song_names.size()-1)) {
+                        currentSongIndex = 0;
+                    }
+                    song = song_names[currentSongIndex].substr(0, ((song_names[currentSongIndex]).length() - 4));
+                    fname = "/sd/wave/" + artist + "/" + song + ".wav";
+                }
+            }
+            pc.printf("Case 3: Play Previous!");
+            break;
+        }    
+        default:        // stop
+        {
+            pc.printf("DEFAULT");
+            break;
+        }    
+    }
+
+ }
+
+int main(){
+  
+    reset=0; //hardware reset for 8266
+    pc.baud(9600);  // set what you want here depending on your terminal program speed
+    pc.printf("\f\n\r-------------ESP8266 Hardware Reset-------------\n\r");
+    wait(0.5);
+    reset=1;
+    timeout=2;
+    getreply();
+    esp.baud(9600);
+    ESPconfig();        //******************  include Config to set the ESP8266 configuration  ***********************
+
+    pc.baud(9600);
+    char oldCommand[1024];
+    pc.attach(&pc_recv, Serial::RxIrq);
+    esp.attach(&dev_recv, Serial::RxIrq);
+    
     while(1) {
-        //while pb3 is low, then we can start playing the song
-        while(playing == true) { //we have 2 while loops..one while loop makes sure the music player is always on, the other one is for the song
-            string songname = filenames[pos];
-            string a = "/sd/";
-            string fname = a + songname; //retrieves the file name
-            FILE *wave_file; 
-            uLCD.locate(0,4);
-            uLCD.printf("Now Playing");
-            wave_file = fopen(fname.c_str(),"r"); //opens the music file
-            waver.play(wave_file); //plays the music file
-            fclose(wave_file);
+        
+        if(flag){
+            memset(oldCommand, '\0', 1024);
+            pcCommand[cnt-1] = '\0';
+            pc.printf("pcCommand: %s", pcCommand);
+            strncpy(oldCommand, pcCommand, sizeof(pcCommand));
+            flag = false;
+            espflag = false;
+            memset(pcCommand, '\0', sizeof(pcCommand));
+            memset(espCommand, '\0', sizeof(espCommand));
+            cnt = -1;
+            espcnt = -1;
+            executeCommand(oldCommand);
+        }  
+        
+        if(espflag){
+            memset(oldCommand, '\0', 1024);
+            espCommand[espcnt-1] = '\0';
+            for(int j = espcnt; j > 0; j--){
+                if(espCommand[j] == 34){
+                    espCommand[j] = '\0';
+                    break;
+                }
+            }
+            pc.printf("espCommand: %s", espCommand);
+            strncpy(oldCommand, espCommand, sizeof(espCommand));
+            espflag = false;
+            flag = false;
+            memset(espCommand, '\0', sizeof(espCommand));
+            memset(pcCommand, '\0', sizeof(pcCommand));
+            cnt = -1;
+            espcnt = -1;
+            executeCommand(oldCommand);
+        }
+        
+    }
+
+}
+
+void ESPsetbaudrate()
+{
+    strcpy(snd, "AT+CIOBAUD=9600\r\n");   // change the numeric value to the required baudrate
+    SendCMD();
+}
+ 
+//  +++++++++++++++++++++++++++++++++ This is for ESP8266 config only, run this once to set up the ESP8266 +++++++++++++++
+void ESPconfig()
+{
+
+    wait(5);
+    pc.printf("\f---------- Starting ESP Config ----------\r\n\n");
+        strcpy(snd,".\r\n.\r\n");
+    SendCMD();
+        wait(1);
+    pc.printf("---------- Reset & get Firmware ----------\r\n");
+    strcpy(snd,"node.restart()\r\n");
+    SendCMD();
+    timeout=5;
+    getreply();
+    pc.printf(buf);
+ 
+    wait(2);
+ 
+    pc.printf("\n---------- Get Version ----------\r\n");
+    strcpy(snd,"print(node.info())\r\n");
+    SendCMD();
+    timeout=4;
+    getreply();
+    pc.printf(buf);
+ 
+    wait(3);
+ 
+    // set CWMODE to 1=Station,2=AP,3=BOTH, default mode 1 (Station)
+    pc.printf("\n---------- Setting Mode ----------\r\n");
+    strcpy(snd, "wifi.setmode(wifi.STATION)\r\n");
+    SendCMD();
+    timeout=4;
+    getreply();
+    pc.printf(buf);
+ 
+    wait(2);
+ 
+   
+ 
+    pc.printf("\n---------- Listing Access Points ----------\r\n");
+    strcpy(snd, "function listap(t)\r\n");
+        SendCMD();
+        wait(1);
+        strcpy(snd, "for k,v in pairs(t) do\r\n");
+        SendCMD();
+        wait(1);
+        strcpy(snd, "print(k..\" : \"..v)\r\n");
+        SendCMD();
+        wait(1);
+        strcpy(snd, "end\r\n");
+        SendCMD();
+        wait(1);
+        strcpy(snd, "end\r\n");
+        SendCMD();
+        wait(1);
+        strcpy(snd, "wifi.sta.getap(listap)\r\n");
+    SendCMD();
+    wait(1);
+        timeout=15;
+    getreply();
+    pc.printf(buf);
+ 
+    wait(2);
+ 
+    pc.printf("\n---------- Connecting to AP ----------\r\n");
+    pc.printf("ssid = %s   pwd = %s\r\n",ssid,pwd);
+    strcpy(snd, "wifi.sta.config(\"");
+    strcat(snd, ssid);
+    strcat(snd, "\",\"");
+    strcat(snd, pwd);
+    strcat(snd, "\")\r\n");
+    SendCMD();
+    timeout=10;
+    getreply();
+    pc.printf(buf);
+ 
+    wait(5);
+ 
+    pc.printf("\n---------- Get IP's ----------\r\n");
+    strcpy(snd, "print(wifi.sta.getip())\r\n");
+    SendCMD();
+    timeout=3;
+    getreply();
+    pc.printf(buf);
+ 
+    wait(1);
+ 
+    pc.printf("\n---------- Get Connection Status ----------\r\n");
+    strcpy(snd, "print(wifi.sta.status())\r\n");
+    SendCMD();
+    timeout=5;
+    getreply();
+    pc.printf(buf);
+ 
+    pc.printf("\n\n\n  If you get a valid (non zero) IP, ESP8266 has been set up.\r\n");
+    pc.printf("  Run this if you want to reconfig the ESP8266 at any time.\r\n");
+    pc.printf("  It saves the SSID and password settings internally\r\n");
+    wait(10);
+        
+        
+        pc.printf("\n---------- Setting up http server ----------\r\n");
+        strcpy(snd, "srv=net.createServer(net.TCP)\r\n");
+        SendCMD();
+        wait(1);
+        
+        strcpy(snd, "srv:listen(80,function(conn)\r\n");
+        SendCMD();
+        wait(1);
+        
+        strcpy(snd, "conn:on(\"receive\",function(conn,payload)\r\n");
+        SendCMD();
+        wait(1);
+        
+        strcpy(snd, "print(payload)");
+        SendCMD();
+        wait(1);
+        
+        strcpy(snd, "end)\r\n");
+        SendCMD();
+        wait(1);
+        
+        strcpy(snd, "conn:on(\"sent\",function(conn) conn:close() end)\r\n");
+        SendCMD();
+        wait(1);
+        
+        strcpy(snd, "end)\r\n");
+        SendCMD();
+        wait(1);
+        
+        timeout=17;
+        getreply();
+        pc.printf(buf);
+        pc.printf("\r\nDONE");
+}
+ 
+void SendCMD()
+{
+    esp.printf("%s", snd);
+}
+ 
+void getreply()
+{
+    memset(buf, '\0', sizeof(buf));
+    t.start();
+    ended=0;
+    count=0;
+    while(!ended) {
+        if(esp.readable()) {
+            buf[count] = esp.getc();
+            count++;
+        }
+        if(t.read() > timeout) {
+            ended = 1;
+            t.stop();
+            t.reset();
         }
     }
 }
+ 
+