This project was our version of a theremin. It was created by using a Leap Motion controller to read in the number of fingers over the sensor. This data was sent to the k64f for translation into musical notes and then sent to a speaker. Features include playing hard coded songs such as Ode to Joy, recording and playing your own music with a SD card, and changing octaves at any time.

Dependencies:   SDFileSystem mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 //libraries
00002 #include "mbed.h"
00003 #include "SDFileSystem.h"                  // SD File System functions
00004 
00005 PwmOut tone(PTC2);              //create a PWM pin
00006 Serial pc(USBTX,USBRX);         //create a COM port
00007 SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd"); //MOSI, MISO, clk, CS
00008 //switches
00009 DigitalIn sw2(SW2);             //playback recording
00010 DigitalIn sw4(PTD1);            //play a song                 
00011 DigitalIn sw5(PTD3);            //start/end recording
00012 DigitalIn sw6(PTD2);            //play a song
00013 //LEDs
00014 DigitalOut led1(LED_RED);
00015 DigitalOut led2(LED_GREEN);
00016 DigitalOut led3(LED_BLUE);
00017 DigitalOut recordLight(PTA2);
00018 //interrupts
00019 InterruptIn Interrupt1(SW3);    //change the octave
00020 //defines
00021 #define MAXRECORDLENGTH 100
00022 #define ODE2JOYLENGTH 62
00023 #define JINGLELENGTH 51
00024 
00025 //vars                              
00026 int tonelevel = 4;                          //Default octave 4
00027 int mode = 0;                               //mode=0 play //mode=1 record
00028 int recordLength = 0;                       //keep track of the actual length vs. the max length
00029 float record[MAXRECORDLENGTH];              //array for storing recorded tone
00030 
00031 //determine which song is playing
00032 bool jingleSet = false;
00033 bool odeSet = false;
00034 
00035  //####################################################################################################### 
00036 float octave[7][12]={
00037     {55.0,62.0,33.0,37.0,41.0,44.0,49.0,58.0,35.0,39.0,46.0,52.0},                          //1
00038     {110.0,123.0,65.0,73.0,82.0,87.0,98.0,117.0,69.0,78.0,93.0,104.0},                      //2
00039     {220.0,247.0,131.0,147.0,165.0,175.0,196.0,233.0,139.0,156.0,185.0,208.0},              //3
00040     {440.0,494.0,262.0,294.0,330.0,349.0,392.0,466.0,277.0,311.0,370.0,415.0},              //4
00041     {880.0,988.0,523.0,587.0,659.0,698.0,784.0,932.0,554.0,622.0,740.0,831.0},              //5
00042     {1760.0,1976.0,1047.0,1175.0,1319.0,1397.0,1568.0,1865.0,1109.0,1245.0,1480.0,1661.0},  //6
00043     {3520.0,3951.0,2093.0,2349.0,2637.0,2794.0,3136.0,3729.0,2217.0,2489.0,2960.0,3322.0}   //7    
00044     };
00045  //#######################################################################################################    
00046 float starwars[]={octave[2][2],octave[2][6],octave[2][5],octave[2][4],octave[2][3],octave[3][2],
00047                   octave[2][2],octave[2][6],octave[2][5],octave[2][4],octave[2][3],octave[3][2],
00048                   octave[2][6],octave[2][5],octave[2][4],octave[2][5],octave[2][3]  
00049                 };               
00050  //####################################################################################################### 
00051 float ode2joy[]= {octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][5],octave[tonelevel][6],octave[tonelevel][6],octave[tonelevel][5],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][2],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][3],
00052                    octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][5],octave[tonelevel][6],octave[tonelevel][6],octave[tonelevel][5],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][2],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][2],octave[tonelevel][2],
00053                    octave[tonelevel][3],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][5],octave[tonelevel][4],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][5],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][2],
00054                    octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][5],octave[tonelevel][6],octave[tonelevel][6],octave[tonelevel][5],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][2],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][2],octave[tonelevel][2]};
00055  //####################################################################################################### 
00056 float jingle[]={octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][6],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][4],
00057                 octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],
00058                 octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][6],
00059                 octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][6],octave[tonelevel][2],octave[tonelevel][3],octave[tonelevel][4],
00060                 octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][5],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],octave[tonelevel][4],
00061                 octave[tonelevel][6],octave[tonelevel][6],octave[tonelevel][5],octave[tonelevel][3],octave[tonelevel][2]};
00062  //####################################################################################################### 
00063  int ode2joyNotes[] = {4,4,5,6,6,5,4,3,2,2,3,4,4,3,3,4,4,5,6,6,5,4,3,2,2,3,4,3,2,2,3,3,4,2,3,4,5,4,2,3,4,5,4,3,2,3,2,4,4,5,6,6,5,4,3,2,2,3,4,3,2,2};
00064  //####################################################################################################### 
00065  int jingleNotes[] =  {4,4,4,4,4,4,4,6,2,3,4,5,5,5,5,5,4,4,4,4,4,3,3,4,3,6,4,4,4,4,4,4,4,6,2,3,4,5,5,5,5,5,4,4,4,4,6,6,5,3,2};
00066  //#######################################################################################################  
00067 int      tempo[]={600,400,400,400,500,600,400,400,400,500,600,400,400,400,400,400,1000};
00068  //####################################################################################################### 
00069 int      tempo2[]={400,400,400,400,400,400,400,400,400,400,400,400,600,200,650,
00070               400,400,400,400,400,400,400,400,400,400,400,400,600,200,650,
00071               400,400,400,400,400,200,200,400,400,400,200,200,400,400,400,400,650,
00072               400,400,400,400,400,400,400,400,400,400,400,400,600,200,1000};   
00073  //#######################################################################################################             
00074 int         tempo3[]={400,400,500,350,350,500,350,350,350,350,700,
00075               400,400,400,350,350,350,400,150,600,
00076               400,400,400,400,450,600,
00077               400,400,500,350,350,500,350,350,350,350,700,
00078               400,400,400,350,350,350,400,150,600,
00079               400,400,400,400,600};       
00080  //####################################################################################################### 
00081 
00082 //function prototypes
00083 void changeOctave(void);
00084 bool writeSD(void);
00085 bool readSD(void);
00086 bool removeFile(void);
00087  
00088 int main()
00089 {
00090 //INITIALIZATIONS
00091     tone = 0;                                     //volume (duty cycle)
00092     int recordCounter = 0;                       //used to count up to max number of notes
00093     
00094     led1 = 1;                                      //turn all LEDs off
00095     led2 = 1;
00096     led3 = 1;
00097     recordLight = 0;
00098 
00099     pc.baud(9600);                              //set baud
00100     
00101     Interrupt1.fall(&changeOctave);             //detect interrupt on falling edge and call ISR 
00102     
00103 //BEGIN LOOP 
00104     while (true) 
00105     {       
00106         //CHECK SW4 -- determine if we should play this song
00107             if(sw4 == 1)
00108             {
00109                 led3 = !led3;
00110                 odeSet = true;
00111                 for(int i=0;i<ODE2JOYLENGTH;i++)
00112                 {
00113                     tone=0.5;
00114                     tone.period(1/ode2joy[i]);
00115                     wait_ms(tempo2[i]);
00116                 }
00117                 odeSet = false;
00118                 tone=0;
00119             }//end sw4
00120             
00121             //CHECK SW6 --  determine if we should play this song
00122             if(sw6 == 1)
00123             {
00124                 led2 = !led2;
00125                 jingleSet = true;
00126                 for(int i=0;i<JINGLELENGTH;i++)
00127                 {
00128                     tone=0.5;
00129                     tone.period(1/jingle[i]);
00130                     wait_ms(tempo2[i]);
00131                 }
00132                 jingleSet = false;
00133                 tone=0;
00134             }//end sw6
00135             
00136             //mode 0 just recieves a character from the COM port, looks up the corresponding node
00137             //and plays it over the speaker at a 50% duty cycle (loudest volume available)
00138             if(mode==0 && pc.readable())
00139             {
00140                 switch(pc.getc())           //Note selection
00141                 {
00142                     case 'a':
00143                     tone=0.5; 
00144                     tone.period(1/octave[tonelevel][0]);
00145                     break;
00146                     case 'b':
00147                     tone=0.5; 
00148                     tone.period(1/octave[tonelevel][1]);
00149                     break;
00150                     case 'c':
00151                     tone=0.5; 
00152                     tone.period(1/octave[tonelevel][2]);
00153                     break;
00154                     case 'd':
00155                     tone=0.5; 
00156                     tone.period(1/octave[tonelevel][3]);
00157                     break;
00158                     case 'e':
00159                     tone=0.5; 
00160                     tone.period(1/octave[tonelevel][4]);
00161                     break;
00162                     case 'f':
00163                     tone=0.5; 
00164                     tone.period(1/octave[tonelevel][5]);
00165                     break;
00166                     case 'g':
00167                     tone=0.5; 
00168                     tone.period(1/octave[tonelevel][6]);
00169                     break;
00170                     case 'h':
00171                     tone=0.5; 
00172                     tone.period(1/octave[tonelevel][7]);
00173                     break;
00174                     case 'i':
00175                     tone=0.5; 
00176                     tone.period(1/octave[tonelevel][8]);
00177                     break;
00178                     case 'j':
00179                     tone=0.5; 
00180                     tone.period(1/octave[tonelevel][9]);
00181                     break;
00182                     case 'k':
00183                     tone=0.5; 
00184                     tone.period(1/octave[tonelevel][10]);
00185                     break;
00186                     case 'l':
00187                     tone=0.5; 
00188                     tone.period(1/octave[tonelevel][11]);
00189                     break;
00190                     case 'm':
00191                     tone=0.5; 
00192                     tone.period(1/octave[tonelevel][11]);
00193                     break;
00194                     default:        //in the default case mute the sound
00195                     tone=0;
00196                 }//end switch
00197             
00198             }//end if mode 0
00199             
00200             
00201             //CHECK SW5 -- Go to recording mode
00202             if(sw5 == 1)
00203             {
00204                 while(sw5 == 1);
00205                 mode = 1; 
00206                 led1 = !led1;
00207                 //reset length when we record a new song
00208                 recordLength = 0;
00209                 //delete the current recording before storing a new one
00210                 removeFile();
00211             }
00212             
00213             
00214             //record notes and set mode back to 0
00215             if(mode==1)
00216             {
00217                 tone=0.5;
00218                 //play a tone to let user know they can record
00219                 tone.period(1/octave[3][6]);
00220                 wait_ms(500);
00221                 tone.period(1/octave[5][6]);
00222                 wait_ms(500);
00223                 tone.period(1/octave[3][6]);
00224                 wait_ms(500);
00225                 tone.period(1/octave[5][6]);
00226                 wait_ms(500);
00227                 tone=0;
00228                 
00229                 //read until we have reached max record length
00230                 while(recordCounter < MAXRECORDLENGTH )
00231                 {
00232                     switch(pc.getc())           //Note selection
00233                     {
00234                         case 'a':
00235                         record[recordCounter]=octave[tonelevel][0];
00236                         tone=0.5; 
00237                         tone.period(1/octave[tonelevel][0]);
00238                         
00239                         break;
00240                         case 'b':
00241                         record[recordCounter]=octave[tonelevel][1];
00242                         tone=0.5; 
00243                         tone.period(1/octave[tonelevel][1]);
00244                         
00245                         break;
00246                         case 'c':
00247                         record[recordCounter]=octave[tonelevel][2];
00248                         tone=0.5; 
00249                         tone.period(1/octave[tonelevel][2]);
00250                         
00251                         break;
00252                         case 'd':
00253                         record[recordCounter]=octave[tonelevel][3];
00254                         tone=0.5; 
00255                         tone.period(1/octave[tonelevel][3]);
00256                         break;
00257                         case 'e':
00258                         record[recordCounter]=octave[tonelevel][4];
00259                         tone=0.5; 
00260                         tone.period(1/octave[tonelevel][4]);
00261                         
00262                         break;
00263                         case 'f':
00264                         record[recordCounter]=octave[tonelevel][5];
00265                         tone=0.5; 
00266                         tone.period(1/octave[tonelevel][5]);
00267                         
00268                         break;
00269                         case 'g':
00270                         record[recordCounter]=octave[tonelevel][6];
00271                         tone=0.5; 
00272                         tone.period(1/octave[tonelevel][6]);
00273                         
00274                         break;
00275                         case 'h':
00276                         record[recordCounter]=octave[tonelevel][7];
00277                         tone=0.5; 
00278                         tone.period(1/octave[tonelevel][7]);
00279                         
00280                         break;
00281                         case 'i':
00282                         record[recordCounter]=octave[tonelevel][8];
00283                         tone=0.5; 
00284                         tone.period(1/octave[tonelevel][8]);
00285                         
00286                         break;
00287                         case 'j':
00288                         record[recordCounter]=octave[tonelevel][9];
00289                         tone=0.5; 
00290                         tone.period(1/octave[tonelevel][9]);
00291                         
00292                         break;
00293                         case 'k':
00294                         record[recordCounter]=octave[tonelevel][10];
00295                         tone=0.5; 
00296                         tone.period(1/octave[tonelevel][10]);
00297                         tone=0;
00298                         break;
00299                         case 'l':
00300                         record[recordCounter]=octave[tonelevel][11];
00301                         tone=0.5; 
00302                         tone.period(1/octave[tonelevel][11]);
00303                         
00304                         break;
00305                         case 'm':
00306                         record[recordCounter]=octave[tonelevel][11];
00307                         tone=0.5; 
00308                         tone.period(1/octave[tonelevel][11]);
00309                         
00310                         break;
00311                         default:            //use a dummy note that will never get played in the default case
00312                         record[recordCounter]=octave[6][6];
00313                         tone=0;
00314                     }//end switch  
00315                     
00316                     recordCounter++;
00317                     recordLight = !recordLight;
00318                     
00319                     //CHECK SW5 -- start or end recording
00320                     if(sw5 == 1)
00321                     {
00322                         while(sw5 == 1);
00323                         mode=1; 
00324                         led1 = !led1;
00325                         recordLength = recordCounter;
00326                         break;
00327                     }
00328                     
00329             }//end while
00330             recordCounter = 0;
00331             mode = 0;
00332             recordLight = 0;
00333             
00334             //play a tone to let user know they are done
00335             tone=0.5;
00336             tone.period(1/octave[3][6]);
00337             wait_ms(500);
00338             tone.period(1/octave[5][6]);
00339             wait_ms(500);
00340             tone.period(1/octave[3][6]);
00341             wait_ms(500);
00342             tone.period(1/octave[5][6]);
00343             wait_ms(500);
00344             tone=0;
00345     //write to the SD card after recording
00346             writeSD();
00347             
00348         }//end if
00349             
00350         //play recored notes
00351         if(mode==0 && sw2==0)
00352         {
00353             if(readSD() == true)
00354             {
00355                 tone = 0.5;
00356                 for(int i=0;i<recordLength;i++)
00357                 {
00358                     if(record[i]==octave[6][6])
00359                         tone=0;
00360                     else
00361                         tone=0.5;
00362                         
00363                     tone.period(1/record[i]);
00364                     //play the recording back a little faster than it was recorded
00365                     wait_ms(450);
00366                 }
00367                 led1 = !led1;
00368                 tone=0;
00369             }
00370         }//end play
00371         led1 = !led1;
00372         wait_ms(100);
00373         
00374     }//end main while loop
00375         
00376 }//main closes
00377     
00378 //used to change the current octave even in the middle of playing a preset song but
00379 //has no effect during playback of recorded music
00380 void changeOctave()
00381 {
00382     tonelevel+=1;
00383     if(tonelevel > 6)
00384         tonelevel = 2;
00385     led2 = !led2;
00386 
00387     //account for change in octave level
00388     if(odeSet == true)
00389     {
00390         for(int i=0; i<ODE2JOYLENGTH; i++)
00391         {
00392            ode2joy[i] = octave[tonelevel][ode2joyNotes[i]];
00393         } 
00394     }  
00395     else if(jingleSet == true)
00396     {
00397         for(int i=0; i<JINGLELENGTH; i++)
00398         {
00399            jingle[i]=      octave[tonelevel][jingleNotes[i]];
00400         } 
00401     } 
00402 }//end change octave
00403 
00404 //Write to the SD card
00405 bool writeSD()
00406 {
00407     FILE *fp = fopen("/sd/sdfile.txt", "w");   // open file for writing
00408     
00409     if (fp==NULL)
00410     {
00411         pc.printf("Could not open file to write\n");
00412         return false;
00413     }
00414     else
00415     {
00416         pc.printf("SC card opened\r\n");
00417         //wait_ms(1000);
00418     }
00419     
00420     if(fprintf(fp, "%d", recordLength))    //first store the size of the array
00421         pc.printf("Write of length of sucessful and it is %d\r\n\n", recordLength);
00422         
00423         //wait_ms(1000);
00424         fprintf(fp, " "); //delimit the values
00425     
00426     for(int i=0; i<recordLength; i++)   //copy all values over
00427     {
00428         if(fprintf(fp, "%f", record[i]))
00429         {
00430             fprintf(fp," ");    //delimit the values
00431             pc.printf("Number of tones stored is : %d\r\n\n", i+1);
00432             pc.printf("The tone is %f \r\n", record[i]);
00433         }
00434     } 
00435     //wait_ms(1000);
00436     fclose(fp);
00437     
00438     return true;
00439 }//end write
00440 
00441 //read from a SD card
00442 bool readSD()
00443 {
00444     FILE *fp = fopen("/sd/sdfile.txt", "r");   // open file for writing
00445     
00446     if (fp==NULL)
00447     {
00448         pc.printf("Could not open file to write\n");
00449         return false;
00450     }
00451     else
00452     {
00453         pc.printf("SC card opened\r\n");
00454         //wait_ms(1000);
00455     }
00456     
00457     
00458     
00459     if(fscanf(fp, "%d", &recordLength))    //first read the size of the array
00460     {
00461         pc.printf("Write of length of sucessful and its value is %d\r\n\n", recordLength);
00462         //wait_ms(1000);
00463     }
00464     else
00465         return false;
00466     
00467     for(int i=0; i<recordLength; i++)   //copy all values over
00468     {
00469         if(fscanf(fp, "%f", &record[i]))
00470             pc.printf("Tone stored is %f\r\n\n", record[i]);
00471         else
00472             return false;
00473     } 
00474     //wait_ms(1000);
00475     fclose(fp);
00476     return true;
00477 }//end read
00478 
00479 //remove the file from the SD card before we create a new one
00480 bool removeFile()
00481 {
00482     //create a string
00483     char filename[] = "/sd/sdfile.txt";
00484     
00485     int ret = remove(filename);
00486 
00487     if(ret == 0) 
00488     {
00489       pc.printf("File deleted successfully");
00490       return false;
00491     }
00492     else 
00493     {
00494       pc.printf("Error: unable to delete the file");
00495     } 
00496     return true;
00497 }