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
Additional project materials:
- C# code written to read and send sensor inputs
- Alternate version of our code
- Project report explaining the entire project
- Demonstration video
/media/uploads/mvanderpohl/project_materials.zip
main.cpp@0:660f0e3ac256, 2016-04-30 (annotated)
- Committer:
- mvanderpohl
- Date:
- Sat Apr 30 14:12:06 2016 +0000
- Revision:
- 0:660f0e3ac256
initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mvanderpohl | 0:660f0e3ac256 | 1 | //libraries |
mvanderpohl | 0:660f0e3ac256 | 2 | #include "mbed.h" |
mvanderpohl | 0:660f0e3ac256 | 3 | #include "SDFileSystem.h" // SD File System functions |
mvanderpohl | 0:660f0e3ac256 | 4 | |
mvanderpohl | 0:660f0e3ac256 | 5 | PwmOut tone(PTC2); //create a PWM pin |
mvanderpohl | 0:660f0e3ac256 | 6 | Serial pc(USBTX,USBRX); //create a COM port |
mvanderpohl | 0:660f0e3ac256 | 7 | SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd"); //MOSI, MISO, clk, CS |
mvanderpohl | 0:660f0e3ac256 | 8 | //switches |
mvanderpohl | 0:660f0e3ac256 | 9 | DigitalIn sw2(SW2); //playback recording |
mvanderpohl | 0:660f0e3ac256 | 10 | DigitalIn sw4(PTD1); //play a song |
mvanderpohl | 0:660f0e3ac256 | 11 | DigitalIn sw5(PTD3); //start/end recording |
mvanderpohl | 0:660f0e3ac256 | 12 | DigitalIn sw6(PTD2); //play a song |
mvanderpohl | 0:660f0e3ac256 | 13 | //LEDs |
mvanderpohl | 0:660f0e3ac256 | 14 | DigitalOut led1(LED_RED); |
mvanderpohl | 0:660f0e3ac256 | 15 | DigitalOut led2(LED_GREEN); |
mvanderpohl | 0:660f0e3ac256 | 16 | DigitalOut led3(LED_BLUE); |
mvanderpohl | 0:660f0e3ac256 | 17 | DigitalOut recordLight(PTA2); |
mvanderpohl | 0:660f0e3ac256 | 18 | //interrupts |
mvanderpohl | 0:660f0e3ac256 | 19 | InterruptIn Interrupt1(SW3); //change the octave |
mvanderpohl | 0:660f0e3ac256 | 20 | //defines |
mvanderpohl | 0:660f0e3ac256 | 21 | #define MAXRECORDLENGTH 100 |
mvanderpohl | 0:660f0e3ac256 | 22 | #define ODE2JOYLENGTH 62 |
mvanderpohl | 0:660f0e3ac256 | 23 | #define JINGLELENGTH 51 |
mvanderpohl | 0:660f0e3ac256 | 24 | |
mvanderpohl | 0:660f0e3ac256 | 25 | //vars |
mvanderpohl | 0:660f0e3ac256 | 26 | int tonelevel = 4; //Default octave 4 |
mvanderpohl | 0:660f0e3ac256 | 27 | int mode = 0; //mode=0 play //mode=1 record |
mvanderpohl | 0:660f0e3ac256 | 28 | int recordLength = 0; //keep track of the actual length vs. the max length |
mvanderpohl | 0:660f0e3ac256 | 29 | float record[MAXRECORDLENGTH]; //array for storing recorded tone |
mvanderpohl | 0:660f0e3ac256 | 30 | |
mvanderpohl | 0:660f0e3ac256 | 31 | //determine which song is playing |
mvanderpohl | 0:660f0e3ac256 | 32 | bool jingleSet = false; |
mvanderpohl | 0:660f0e3ac256 | 33 | bool odeSet = false; |
mvanderpohl | 0:660f0e3ac256 | 34 | |
mvanderpohl | 0:660f0e3ac256 | 35 | //####################################################################################################### |
mvanderpohl | 0:660f0e3ac256 | 36 | float octave[7][12]={ |
mvanderpohl | 0:660f0e3ac256 | 37 | {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 |
mvanderpohl | 0:660f0e3ac256 | 38 | {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 |
mvanderpohl | 0:660f0e3ac256 | 39 | {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 |
mvanderpohl | 0:660f0e3ac256 | 40 | {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 |
mvanderpohl | 0:660f0e3ac256 | 41 | {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 |
mvanderpohl | 0:660f0e3ac256 | 42 | {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 |
mvanderpohl | 0:660f0e3ac256 | 43 | {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 |
mvanderpohl | 0:660f0e3ac256 | 44 | }; |
mvanderpohl | 0:660f0e3ac256 | 45 | //####################################################################################################### |
mvanderpohl | 0:660f0e3ac256 | 46 | float starwars[]={octave[2][2],octave[2][6],octave[2][5],octave[2][4],octave[2][3],octave[3][2], |
mvanderpohl | 0:660f0e3ac256 | 47 | octave[2][2],octave[2][6],octave[2][5],octave[2][4],octave[2][3],octave[3][2], |
mvanderpohl | 0:660f0e3ac256 | 48 | octave[2][6],octave[2][5],octave[2][4],octave[2][5],octave[2][3] |
mvanderpohl | 0:660f0e3ac256 | 49 | }; |
mvanderpohl | 0:660f0e3ac256 | 50 | //####################################################################################################### |
mvanderpohl | 0:660f0e3ac256 | 51 | 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], |
mvanderpohl | 0:660f0e3ac256 | 52 | 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], |
mvanderpohl | 0:660f0e3ac256 | 53 | 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], |
mvanderpohl | 0:660f0e3ac256 | 54 | 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]}; |
mvanderpohl | 0:660f0e3ac256 | 55 | //####################################################################################################### |
mvanderpohl | 0:660f0e3ac256 | 56 | 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], |
mvanderpohl | 0:660f0e3ac256 | 57 | 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], |
mvanderpohl | 0:660f0e3ac256 | 58 | octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][3],octave[tonelevel][4],octave[tonelevel][3],octave[tonelevel][6], |
mvanderpohl | 0:660f0e3ac256 | 59 | 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], |
mvanderpohl | 0:660f0e3ac256 | 60 | 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], |
mvanderpohl | 0:660f0e3ac256 | 61 | octave[tonelevel][6],octave[tonelevel][6],octave[tonelevel][5],octave[tonelevel][3],octave[tonelevel][2]}; |
mvanderpohl | 0:660f0e3ac256 | 62 | //####################################################################################################### |
mvanderpohl | 0:660f0e3ac256 | 63 | 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}; |
mvanderpohl | 0:660f0e3ac256 | 64 | //####################################################################################################### |
mvanderpohl | 0:660f0e3ac256 | 65 | 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}; |
mvanderpohl | 0:660f0e3ac256 | 66 | //####################################################################################################### |
mvanderpohl | 0:660f0e3ac256 | 67 | int tempo[]={600,400,400,400,500,600,400,400,400,500,600,400,400,400,400,400,1000}; |
mvanderpohl | 0:660f0e3ac256 | 68 | //####################################################################################################### |
mvanderpohl | 0:660f0e3ac256 | 69 | int tempo2[]={400,400,400,400,400,400,400,400,400,400,400,400,600,200,650, |
mvanderpohl | 0:660f0e3ac256 | 70 | 400,400,400,400,400,400,400,400,400,400,400,400,600,200,650, |
mvanderpohl | 0:660f0e3ac256 | 71 | 400,400,400,400,400,200,200,400,400,400,200,200,400,400,400,400,650, |
mvanderpohl | 0:660f0e3ac256 | 72 | 400,400,400,400,400,400,400,400,400,400,400,400,600,200,1000}; |
mvanderpohl | 0:660f0e3ac256 | 73 | //####################################################################################################### |
mvanderpohl | 0:660f0e3ac256 | 74 | int tempo3[]={400,400,500,350,350,500,350,350,350,350,700, |
mvanderpohl | 0:660f0e3ac256 | 75 | 400,400,400,350,350,350,400,150,600, |
mvanderpohl | 0:660f0e3ac256 | 76 | 400,400,400,400,450,600, |
mvanderpohl | 0:660f0e3ac256 | 77 | 400,400,500,350,350,500,350,350,350,350,700, |
mvanderpohl | 0:660f0e3ac256 | 78 | 400,400,400,350,350,350,400,150,600, |
mvanderpohl | 0:660f0e3ac256 | 79 | 400,400,400,400,600}; |
mvanderpohl | 0:660f0e3ac256 | 80 | //####################################################################################################### |
mvanderpohl | 0:660f0e3ac256 | 81 | |
mvanderpohl | 0:660f0e3ac256 | 82 | //function prototypes |
mvanderpohl | 0:660f0e3ac256 | 83 | void changeOctave(void); |
mvanderpohl | 0:660f0e3ac256 | 84 | bool writeSD(void); |
mvanderpohl | 0:660f0e3ac256 | 85 | bool readSD(void); |
mvanderpohl | 0:660f0e3ac256 | 86 | bool removeFile(void); |
mvanderpohl | 0:660f0e3ac256 | 87 | |
mvanderpohl | 0:660f0e3ac256 | 88 | int main() |
mvanderpohl | 0:660f0e3ac256 | 89 | { |
mvanderpohl | 0:660f0e3ac256 | 90 | //INITIALIZATIONS |
mvanderpohl | 0:660f0e3ac256 | 91 | tone = 0; //volume (duty cycle) |
mvanderpohl | 0:660f0e3ac256 | 92 | int recordCounter = 0; //used to count up to max number of notes |
mvanderpohl | 0:660f0e3ac256 | 93 | |
mvanderpohl | 0:660f0e3ac256 | 94 | led1 = 1; //turn all LEDs off |
mvanderpohl | 0:660f0e3ac256 | 95 | led2 = 1; |
mvanderpohl | 0:660f0e3ac256 | 96 | led3 = 1; |
mvanderpohl | 0:660f0e3ac256 | 97 | recordLight = 0; |
mvanderpohl | 0:660f0e3ac256 | 98 | |
mvanderpohl | 0:660f0e3ac256 | 99 | pc.baud(9600); //set baud |
mvanderpohl | 0:660f0e3ac256 | 100 | |
mvanderpohl | 0:660f0e3ac256 | 101 | Interrupt1.fall(&changeOctave); //detect interrupt on falling edge and call ISR |
mvanderpohl | 0:660f0e3ac256 | 102 | |
mvanderpohl | 0:660f0e3ac256 | 103 | //BEGIN LOOP |
mvanderpohl | 0:660f0e3ac256 | 104 | while (true) |
mvanderpohl | 0:660f0e3ac256 | 105 | { |
mvanderpohl | 0:660f0e3ac256 | 106 | //CHECK SW4 -- determine if we should play this song |
mvanderpohl | 0:660f0e3ac256 | 107 | if(sw4 == 1) |
mvanderpohl | 0:660f0e3ac256 | 108 | { |
mvanderpohl | 0:660f0e3ac256 | 109 | led3 = !led3; |
mvanderpohl | 0:660f0e3ac256 | 110 | odeSet = true; |
mvanderpohl | 0:660f0e3ac256 | 111 | for(int i=0;i<ODE2JOYLENGTH;i++) |
mvanderpohl | 0:660f0e3ac256 | 112 | { |
mvanderpohl | 0:660f0e3ac256 | 113 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 114 | tone.period(1/ode2joy[i]); |
mvanderpohl | 0:660f0e3ac256 | 115 | wait_ms(tempo2[i]); |
mvanderpohl | 0:660f0e3ac256 | 116 | } |
mvanderpohl | 0:660f0e3ac256 | 117 | odeSet = false; |
mvanderpohl | 0:660f0e3ac256 | 118 | tone=0; |
mvanderpohl | 0:660f0e3ac256 | 119 | }//end sw4 |
mvanderpohl | 0:660f0e3ac256 | 120 | |
mvanderpohl | 0:660f0e3ac256 | 121 | //CHECK SW6 -- determine if we should play this song |
mvanderpohl | 0:660f0e3ac256 | 122 | if(sw6 == 1) |
mvanderpohl | 0:660f0e3ac256 | 123 | { |
mvanderpohl | 0:660f0e3ac256 | 124 | led2 = !led2; |
mvanderpohl | 0:660f0e3ac256 | 125 | jingleSet = true; |
mvanderpohl | 0:660f0e3ac256 | 126 | for(int i=0;i<JINGLELENGTH;i++) |
mvanderpohl | 0:660f0e3ac256 | 127 | { |
mvanderpohl | 0:660f0e3ac256 | 128 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 129 | tone.period(1/jingle[i]); |
mvanderpohl | 0:660f0e3ac256 | 130 | wait_ms(tempo2[i]); |
mvanderpohl | 0:660f0e3ac256 | 131 | } |
mvanderpohl | 0:660f0e3ac256 | 132 | jingleSet = false; |
mvanderpohl | 0:660f0e3ac256 | 133 | tone=0; |
mvanderpohl | 0:660f0e3ac256 | 134 | }//end sw6 |
mvanderpohl | 0:660f0e3ac256 | 135 | |
mvanderpohl | 0:660f0e3ac256 | 136 | //mode 0 just recieves a character from the COM port, looks up the corresponding node |
mvanderpohl | 0:660f0e3ac256 | 137 | //and plays it over the speaker at a 50% duty cycle (loudest volume available) |
mvanderpohl | 0:660f0e3ac256 | 138 | if(mode==0 && pc.readable()) |
mvanderpohl | 0:660f0e3ac256 | 139 | { |
mvanderpohl | 0:660f0e3ac256 | 140 | switch(pc.getc()) //Note selection |
mvanderpohl | 0:660f0e3ac256 | 141 | { |
mvanderpohl | 0:660f0e3ac256 | 142 | case 'a': |
mvanderpohl | 0:660f0e3ac256 | 143 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 144 | tone.period(1/octave[tonelevel][0]); |
mvanderpohl | 0:660f0e3ac256 | 145 | break; |
mvanderpohl | 0:660f0e3ac256 | 146 | case 'b': |
mvanderpohl | 0:660f0e3ac256 | 147 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 148 | tone.period(1/octave[tonelevel][1]); |
mvanderpohl | 0:660f0e3ac256 | 149 | break; |
mvanderpohl | 0:660f0e3ac256 | 150 | case 'c': |
mvanderpohl | 0:660f0e3ac256 | 151 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 152 | tone.period(1/octave[tonelevel][2]); |
mvanderpohl | 0:660f0e3ac256 | 153 | break; |
mvanderpohl | 0:660f0e3ac256 | 154 | case 'd': |
mvanderpohl | 0:660f0e3ac256 | 155 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 156 | tone.period(1/octave[tonelevel][3]); |
mvanderpohl | 0:660f0e3ac256 | 157 | break; |
mvanderpohl | 0:660f0e3ac256 | 158 | case 'e': |
mvanderpohl | 0:660f0e3ac256 | 159 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 160 | tone.period(1/octave[tonelevel][4]); |
mvanderpohl | 0:660f0e3ac256 | 161 | break; |
mvanderpohl | 0:660f0e3ac256 | 162 | case 'f': |
mvanderpohl | 0:660f0e3ac256 | 163 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 164 | tone.period(1/octave[tonelevel][5]); |
mvanderpohl | 0:660f0e3ac256 | 165 | break; |
mvanderpohl | 0:660f0e3ac256 | 166 | case 'g': |
mvanderpohl | 0:660f0e3ac256 | 167 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 168 | tone.period(1/octave[tonelevel][6]); |
mvanderpohl | 0:660f0e3ac256 | 169 | break; |
mvanderpohl | 0:660f0e3ac256 | 170 | case 'h': |
mvanderpohl | 0:660f0e3ac256 | 171 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 172 | tone.period(1/octave[tonelevel][7]); |
mvanderpohl | 0:660f0e3ac256 | 173 | break; |
mvanderpohl | 0:660f0e3ac256 | 174 | case 'i': |
mvanderpohl | 0:660f0e3ac256 | 175 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 176 | tone.period(1/octave[tonelevel][8]); |
mvanderpohl | 0:660f0e3ac256 | 177 | break; |
mvanderpohl | 0:660f0e3ac256 | 178 | case 'j': |
mvanderpohl | 0:660f0e3ac256 | 179 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 180 | tone.period(1/octave[tonelevel][9]); |
mvanderpohl | 0:660f0e3ac256 | 181 | break; |
mvanderpohl | 0:660f0e3ac256 | 182 | case 'k': |
mvanderpohl | 0:660f0e3ac256 | 183 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 184 | tone.period(1/octave[tonelevel][10]); |
mvanderpohl | 0:660f0e3ac256 | 185 | break; |
mvanderpohl | 0:660f0e3ac256 | 186 | case 'l': |
mvanderpohl | 0:660f0e3ac256 | 187 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 188 | tone.period(1/octave[tonelevel][11]); |
mvanderpohl | 0:660f0e3ac256 | 189 | break; |
mvanderpohl | 0:660f0e3ac256 | 190 | case 'm': |
mvanderpohl | 0:660f0e3ac256 | 191 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 192 | tone.period(1/octave[tonelevel][11]); |
mvanderpohl | 0:660f0e3ac256 | 193 | break; |
mvanderpohl | 0:660f0e3ac256 | 194 | default: //in the default case mute the sound |
mvanderpohl | 0:660f0e3ac256 | 195 | tone=0; |
mvanderpohl | 0:660f0e3ac256 | 196 | }//end switch |
mvanderpohl | 0:660f0e3ac256 | 197 | |
mvanderpohl | 0:660f0e3ac256 | 198 | }//end if mode 0 |
mvanderpohl | 0:660f0e3ac256 | 199 | |
mvanderpohl | 0:660f0e3ac256 | 200 | |
mvanderpohl | 0:660f0e3ac256 | 201 | //CHECK SW5 -- Go to recording mode |
mvanderpohl | 0:660f0e3ac256 | 202 | if(sw5 == 1) |
mvanderpohl | 0:660f0e3ac256 | 203 | { |
mvanderpohl | 0:660f0e3ac256 | 204 | while(sw5 == 1); |
mvanderpohl | 0:660f0e3ac256 | 205 | mode = 1; |
mvanderpohl | 0:660f0e3ac256 | 206 | led1 = !led1; |
mvanderpohl | 0:660f0e3ac256 | 207 | //reset length when we record a new song |
mvanderpohl | 0:660f0e3ac256 | 208 | recordLength = 0; |
mvanderpohl | 0:660f0e3ac256 | 209 | //delete the current recording before storing a new one |
mvanderpohl | 0:660f0e3ac256 | 210 | removeFile(); |
mvanderpohl | 0:660f0e3ac256 | 211 | } |
mvanderpohl | 0:660f0e3ac256 | 212 | |
mvanderpohl | 0:660f0e3ac256 | 213 | |
mvanderpohl | 0:660f0e3ac256 | 214 | //record notes and set mode back to 0 |
mvanderpohl | 0:660f0e3ac256 | 215 | if(mode==1) |
mvanderpohl | 0:660f0e3ac256 | 216 | { |
mvanderpohl | 0:660f0e3ac256 | 217 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 218 | //play a tone to let user know they can record |
mvanderpohl | 0:660f0e3ac256 | 219 | tone.period(1/octave[3][6]); |
mvanderpohl | 0:660f0e3ac256 | 220 | wait_ms(500); |
mvanderpohl | 0:660f0e3ac256 | 221 | tone.period(1/octave[5][6]); |
mvanderpohl | 0:660f0e3ac256 | 222 | wait_ms(500); |
mvanderpohl | 0:660f0e3ac256 | 223 | tone.period(1/octave[3][6]); |
mvanderpohl | 0:660f0e3ac256 | 224 | wait_ms(500); |
mvanderpohl | 0:660f0e3ac256 | 225 | tone.period(1/octave[5][6]); |
mvanderpohl | 0:660f0e3ac256 | 226 | wait_ms(500); |
mvanderpohl | 0:660f0e3ac256 | 227 | tone=0; |
mvanderpohl | 0:660f0e3ac256 | 228 | |
mvanderpohl | 0:660f0e3ac256 | 229 | //read until we have reached max record length |
mvanderpohl | 0:660f0e3ac256 | 230 | while(recordCounter < MAXRECORDLENGTH ) |
mvanderpohl | 0:660f0e3ac256 | 231 | { |
mvanderpohl | 0:660f0e3ac256 | 232 | switch(pc.getc()) //Note selection |
mvanderpohl | 0:660f0e3ac256 | 233 | { |
mvanderpohl | 0:660f0e3ac256 | 234 | case 'a': |
mvanderpohl | 0:660f0e3ac256 | 235 | record[recordCounter]=octave[tonelevel][0]; |
mvanderpohl | 0:660f0e3ac256 | 236 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 237 | tone.period(1/octave[tonelevel][0]); |
mvanderpohl | 0:660f0e3ac256 | 238 | |
mvanderpohl | 0:660f0e3ac256 | 239 | break; |
mvanderpohl | 0:660f0e3ac256 | 240 | case 'b': |
mvanderpohl | 0:660f0e3ac256 | 241 | record[recordCounter]=octave[tonelevel][1]; |
mvanderpohl | 0:660f0e3ac256 | 242 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 243 | tone.period(1/octave[tonelevel][1]); |
mvanderpohl | 0:660f0e3ac256 | 244 | |
mvanderpohl | 0:660f0e3ac256 | 245 | break; |
mvanderpohl | 0:660f0e3ac256 | 246 | case 'c': |
mvanderpohl | 0:660f0e3ac256 | 247 | record[recordCounter]=octave[tonelevel][2]; |
mvanderpohl | 0:660f0e3ac256 | 248 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 249 | tone.period(1/octave[tonelevel][2]); |
mvanderpohl | 0:660f0e3ac256 | 250 | |
mvanderpohl | 0:660f0e3ac256 | 251 | break; |
mvanderpohl | 0:660f0e3ac256 | 252 | case 'd': |
mvanderpohl | 0:660f0e3ac256 | 253 | record[recordCounter]=octave[tonelevel][3]; |
mvanderpohl | 0:660f0e3ac256 | 254 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 255 | tone.period(1/octave[tonelevel][3]); |
mvanderpohl | 0:660f0e3ac256 | 256 | break; |
mvanderpohl | 0:660f0e3ac256 | 257 | case 'e': |
mvanderpohl | 0:660f0e3ac256 | 258 | record[recordCounter]=octave[tonelevel][4]; |
mvanderpohl | 0:660f0e3ac256 | 259 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 260 | tone.period(1/octave[tonelevel][4]); |
mvanderpohl | 0:660f0e3ac256 | 261 | |
mvanderpohl | 0:660f0e3ac256 | 262 | break; |
mvanderpohl | 0:660f0e3ac256 | 263 | case 'f': |
mvanderpohl | 0:660f0e3ac256 | 264 | record[recordCounter]=octave[tonelevel][5]; |
mvanderpohl | 0:660f0e3ac256 | 265 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 266 | tone.period(1/octave[tonelevel][5]); |
mvanderpohl | 0:660f0e3ac256 | 267 | |
mvanderpohl | 0:660f0e3ac256 | 268 | break; |
mvanderpohl | 0:660f0e3ac256 | 269 | case 'g': |
mvanderpohl | 0:660f0e3ac256 | 270 | record[recordCounter]=octave[tonelevel][6]; |
mvanderpohl | 0:660f0e3ac256 | 271 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 272 | tone.period(1/octave[tonelevel][6]); |
mvanderpohl | 0:660f0e3ac256 | 273 | |
mvanderpohl | 0:660f0e3ac256 | 274 | break; |
mvanderpohl | 0:660f0e3ac256 | 275 | case 'h': |
mvanderpohl | 0:660f0e3ac256 | 276 | record[recordCounter]=octave[tonelevel][7]; |
mvanderpohl | 0:660f0e3ac256 | 277 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 278 | tone.period(1/octave[tonelevel][7]); |
mvanderpohl | 0:660f0e3ac256 | 279 | |
mvanderpohl | 0:660f0e3ac256 | 280 | break; |
mvanderpohl | 0:660f0e3ac256 | 281 | case 'i': |
mvanderpohl | 0:660f0e3ac256 | 282 | record[recordCounter]=octave[tonelevel][8]; |
mvanderpohl | 0:660f0e3ac256 | 283 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 284 | tone.period(1/octave[tonelevel][8]); |
mvanderpohl | 0:660f0e3ac256 | 285 | |
mvanderpohl | 0:660f0e3ac256 | 286 | break; |
mvanderpohl | 0:660f0e3ac256 | 287 | case 'j': |
mvanderpohl | 0:660f0e3ac256 | 288 | record[recordCounter]=octave[tonelevel][9]; |
mvanderpohl | 0:660f0e3ac256 | 289 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 290 | tone.period(1/octave[tonelevel][9]); |
mvanderpohl | 0:660f0e3ac256 | 291 | |
mvanderpohl | 0:660f0e3ac256 | 292 | break; |
mvanderpohl | 0:660f0e3ac256 | 293 | case 'k': |
mvanderpohl | 0:660f0e3ac256 | 294 | record[recordCounter]=octave[tonelevel][10]; |
mvanderpohl | 0:660f0e3ac256 | 295 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 296 | tone.period(1/octave[tonelevel][10]); |
mvanderpohl | 0:660f0e3ac256 | 297 | tone=0; |
mvanderpohl | 0:660f0e3ac256 | 298 | break; |
mvanderpohl | 0:660f0e3ac256 | 299 | case 'l': |
mvanderpohl | 0:660f0e3ac256 | 300 | record[recordCounter]=octave[tonelevel][11]; |
mvanderpohl | 0:660f0e3ac256 | 301 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 302 | tone.period(1/octave[tonelevel][11]); |
mvanderpohl | 0:660f0e3ac256 | 303 | |
mvanderpohl | 0:660f0e3ac256 | 304 | break; |
mvanderpohl | 0:660f0e3ac256 | 305 | case 'm': |
mvanderpohl | 0:660f0e3ac256 | 306 | record[recordCounter]=octave[tonelevel][11]; |
mvanderpohl | 0:660f0e3ac256 | 307 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 308 | tone.period(1/octave[tonelevel][11]); |
mvanderpohl | 0:660f0e3ac256 | 309 | |
mvanderpohl | 0:660f0e3ac256 | 310 | break; |
mvanderpohl | 0:660f0e3ac256 | 311 | default: //use a dummy note that will never get played in the default case |
mvanderpohl | 0:660f0e3ac256 | 312 | record[recordCounter]=octave[6][6]; |
mvanderpohl | 0:660f0e3ac256 | 313 | tone=0; |
mvanderpohl | 0:660f0e3ac256 | 314 | }//end switch |
mvanderpohl | 0:660f0e3ac256 | 315 | |
mvanderpohl | 0:660f0e3ac256 | 316 | recordCounter++; |
mvanderpohl | 0:660f0e3ac256 | 317 | recordLight = !recordLight; |
mvanderpohl | 0:660f0e3ac256 | 318 | |
mvanderpohl | 0:660f0e3ac256 | 319 | //CHECK SW5 -- start or end recording |
mvanderpohl | 0:660f0e3ac256 | 320 | if(sw5 == 1) |
mvanderpohl | 0:660f0e3ac256 | 321 | { |
mvanderpohl | 0:660f0e3ac256 | 322 | while(sw5 == 1); |
mvanderpohl | 0:660f0e3ac256 | 323 | mode=1; |
mvanderpohl | 0:660f0e3ac256 | 324 | led1 = !led1; |
mvanderpohl | 0:660f0e3ac256 | 325 | recordLength = recordCounter; |
mvanderpohl | 0:660f0e3ac256 | 326 | break; |
mvanderpohl | 0:660f0e3ac256 | 327 | } |
mvanderpohl | 0:660f0e3ac256 | 328 | |
mvanderpohl | 0:660f0e3ac256 | 329 | }//end while |
mvanderpohl | 0:660f0e3ac256 | 330 | recordCounter = 0; |
mvanderpohl | 0:660f0e3ac256 | 331 | mode = 0; |
mvanderpohl | 0:660f0e3ac256 | 332 | recordLight = 0; |
mvanderpohl | 0:660f0e3ac256 | 333 | |
mvanderpohl | 0:660f0e3ac256 | 334 | //play a tone to let user know they are done |
mvanderpohl | 0:660f0e3ac256 | 335 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 336 | tone.period(1/octave[3][6]); |
mvanderpohl | 0:660f0e3ac256 | 337 | wait_ms(500); |
mvanderpohl | 0:660f0e3ac256 | 338 | tone.period(1/octave[5][6]); |
mvanderpohl | 0:660f0e3ac256 | 339 | wait_ms(500); |
mvanderpohl | 0:660f0e3ac256 | 340 | tone.period(1/octave[3][6]); |
mvanderpohl | 0:660f0e3ac256 | 341 | wait_ms(500); |
mvanderpohl | 0:660f0e3ac256 | 342 | tone.period(1/octave[5][6]); |
mvanderpohl | 0:660f0e3ac256 | 343 | wait_ms(500); |
mvanderpohl | 0:660f0e3ac256 | 344 | tone=0; |
mvanderpohl | 0:660f0e3ac256 | 345 | //write to the SD card after recording |
mvanderpohl | 0:660f0e3ac256 | 346 | writeSD(); |
mvanderpohl | 0:660f0e3ac256 | 347 | |
mvanderpohl | 0:660f0e3ac256 | 348 | }//end if |
mvanderpohl | 0:660f0e3ac256 | 349 | |
mvanderpohl | 0:660f0e3ac256 | 350 | //play recored notes |
mvanderpohl | 0:660f0e3ac256 | 351 | if(mode==0 && sw2==0) |
mvanderpohl | 0:660f0e3ac256 | 352 | { |
mvanderpohl | 0:660f0e3ac256 | 353 | if(readSD() == true) |
mvanderpohl | 0:660f0e3ac256 | 354 | { |
mvanderpohl | 0:660f0e3ac256 | 355 | tone = 0.5; |
mvanderpohl | 0:660f0e3ac256 | 356 | for(int i=0;i<recordLength;i++) |
mvanderpohl | 0:660f0e3ac256 | 357 | { |
mvanderpohl | 0:660f0e3ac256 | 358 | if(record[i]==octave[6][6]) |
mvanderpohl | 0:660f0e3ac256 | 359 | tone=0; |
mvanderpohl | 0:660f0e3ac256 | 360 | else |
mvanderpohl | 0:660f0e3ac256 | 361 | tone=0.5; |
mvanderpohl | 0:660f0e3ac256 | 362 | |
mvanderpohl | 0:660f0e3ac256 | 363 | tone.period(1/record[i]); |
mvanderpohl | 0:660f0e3ac256 | 364 | //play the recording back a little faster than it was recorded |
mvanderpohl | 0:660f0e3ac256 | 365 | wait_ms(450); |
mvanderpohl | 0:660f0e3ac256 | 366 | } |
mvanderpohl | 0:660f0e3ac256 | 367 | led1 = !led1; |
mvanderpohl | 0:660f0e3ac256 | 368 | tone=0; |
mvanderpohl | 0:660f0e3ac256 | 369 | } |
mvanderpohl | 0:660f0e3ac256 | 370 | }//end play |
mvanderpohl | 0:660f0e3ac256 | 371 | led1 = !led1; |
mvanderpohl | 0:660f0e3ac256 | 372 | wait_ms(100); |
mvanderpohl | 0:660f0e3ac256 | 373 | |
mvanderpohl | 0:660f0e3ac256 | 374 | }//end main while loop |
mvanderpohl | 0:660f0e3ac256 | 375 | |
mvanderpohl | 0:660f0e3ac256 | 376 | }//main closes |
mvanderpohl | 0:660f0e3ac256 | 377 | |
mvanderpohl | 0:660f0e3ac256 | 378 | //used to change the current octave even in the middle of playing a preset song but |
mvanderpohl | 0:660f0e3ac256 | 379 | //has no effect during playback of recorded music |
mvanderpohl | 0:660f0e3ac256 | 380 | void changeOctave() |
mvanderpohl | 0:660f0e3ac256 | 381 | { |
mvanderpohl | 0:660f0e3ac256 | 382 | tonelevel+=1; |
mvanderpohl | 0:660f0e3ac256 | 383 | if(tonelevel > 6) |
mvanderpohl | 0:660f0e3ac256 | 384 | tonelevel = 2; |
mvanderpohl | 0:660f0e3ac256 | 385 | led2 = !led2; |
mvanderpohl | 0:660f0e3ac256 | 386 | |
mvanderpohl | 0:660f0e3ac256 | 387 | //account for change in octave level |
mvanderpohl | 0:660f0e3ac256 | 388 | if(odeSet == true) |
mvanderpohl | 0:660f0e3ac256 | 389 | { |
mvanderpohl | 0:660f0e3ac256 | 390 | for(int i=0; i<ODE2JOYLENGTH; i++) |
mvanderpohl | 0:660f0e3ac256 | 391 | { |
mvanderpohl | 0:660f0e3ac256 | 392 | ode2joy[i] = octave[tonelevel][ode2joyNotes[i]]; |
mvanderpohl | 0:660f0e3ac256 | 393 | } |
mvanderpohl | 0:660f0e3ac256 | 394 | } |
mvanderpohl | 0:660f0e3ac256 | 395 | else if(jingleSet == true) |
mvanderpohl | 0:660f0e3ac256 | 396 | { |
mvanderpohl | 0:660f0e3ac256 | 397 | for(int i=0; i<JINGLELENGTH; i++) |
mvanderpohl | 0:660f0e3ac256 | 398 | { |
mvanderpohl | 0:660f0e3ac256 | 399 | jingle[i]= octave[tonelevel][jingleNotes[i]]; |
mvanderpohl | 0:660f0e3ac256 | 400 | } |
mvanderpohl | 0:660f0e3ac256 | 401 | } |
mvanderpohl | 0:660f0e3ac256 | 402 | }//end change octave |
mvanderpohl | 0:660f0e3ac256 | 403 | |
mvanderpohl | 0:660f0e3ac256 | 404 | //Write to the SD card |
mvanderpohl | 0:660f0e3ac256 | 405 | bool writeSD() |
mvanderpohl | 0:660f0e3ac256 | 406 | { |
mvanderpohl | 0:660f0e3ac256 | 407 | FILE *fp = fopen("/sd/sdfile.txt", "w"); // open file for writing |
mvanderpohl | 0:660f0e3ac256 | 408 | |
mvanderpohl | 0:660f0e3ac256 | 409 | if (fp==NULL) |
mvanderpohl | 0:660f0e3ac256 | 410 | { |
mvanderpohl | 0:660f0e3ac256 | 411 | pc.printf("Could not open file to write\n"); |
mvanderpohl | 0:660f0e3ac256 | 412 | return false; |
mvanderpohl | 0:660f0e3ac256 | 413 | } |
mvanderpohl | 0:660f0e3ac256 | 414 | else |
mvanderpohl | 0:660f0e3ac256 | 415 | { |
mvanderpohl | 0:660f0e3ac256 | 416 | pc.printf("SC card opened\r\n"); |
mvanderpohl | 0:660f0e3ac256 | 417 | //wait_ms(1000); |
mvanderpohl | 0:660f0e3ac256 | 418 | } |
mvanderpohl | 0:660f0e3ac256 | 419 | |
mvanderpohl | 0:660f0e3ac256 | 420 | if(fprintf(fp, "%d", recordLength)) //first store the size of the array |
mvanderpohl | 0:660f0e3ac256 | 421 | pc.printf("Write of length of sucessful and it is %d\r\n\n", recordLength); |
mvanderpohl | 0:660f0e3ac256 | 422 | |
mvanderpohl | 0:660f0e3ac256 | 423 | //wait_ms(1000); |
mvanderpohl | 0:660f0e3ac256 | 424 | fprintf(fp, " "); //delimit the values |
mvanderpohl | 0:660f0e3ac256 | 425 | |
mvanderpohl | 0:660f0e3ac256 | 426 | for(int i=0; i<recordLength; i++) //copy all values over |
mvanderpohl | 0:660f0e3ac256 | 427 | { |
mvanderpohl | 0:660f0e3ac256 | 428 | if(fprintf(fp, "%f", record[i])) |
mvanderpohl | 0:660f0e3ac256 | 429 | { |
mvanderpohl | 0:660f0e3ac256 | 430 | fprintf(fp," "); //delimit the values |
mvanderpohl | 0:660f0e3ac256 | 431 | pc.printf("Number of tones stored is : %d\r\n\n", i+1); |
mvanderpohl | 0:660f0e3ac256 | 432 | pc.printf("The tone is %f \r\n", record[i]); |
mvanderpohl | 0:660f0e3ac256 | 433 | } |
mvanderpohl | 0:660f0e3ac256 | 434 | } |
mvanderpohl | 0:660f0e3ac256 | 435 | //wait_ms(1000); |
mvanderpohl | 0:660f0e3ac256 | 436 | fclose(fp); |
mvanderpohl | 0:660f0e3ac256 | 437 | |
mvanderpohl | 0:660f0e3ac256 | 438 | return true; |
mvanderpohl | 0:660f0e3ac256 | 439 | }//end write |
mvanderpohl | 0:660f0e3ac256 | 440 | |
mvanderpohl | 0:660f0e3ac256 | 441 | //read from a SD card |
mvanderpohl | 0:660f0e3ac256 | 442 | bool readSD() |
mvanderpohl | 0:660f0e3ac256 | 443 | { |
mvanderpohl | 0:660f0e3ac256 | 444 | FILE *fp = fopen("/sd/sdfile.txt", "r"); // open file for writing |
mvanderpohl | 0:660f0e3ac256 | 445 | |
mvanderpohl | 0:660f0e3ac256 | 446 | if (fp==NULL) |
mvanderpohl | 0:660f0e3ac256 | 447 | { |
mvanderpohl | 0:660f0e3ac256 | 448 | pc.printf("Could not open file to write\n"); |
mvanderpohl | 0:660f0e3ac256 | 449 | return false; |
mvanderpohl | 0:660f0e3ac256 | 450 | } |
mvanderpohl | 0:660f0e3ac256 | 451 | else |
mvanderpohl | 0:660f0e3ac256 | 452 | { |
mvanderpohl | 0:660f0e3ac256 | 453 | pc.printf("SC card opened\r\n"); |
mvanderpohl | 0:660f0e3ac256 | 454 | //wait_ms(1000); |
mvanderpohl | 0:660f0e3ac256 | 455 | } |
mvanderpohl | 0:660f0e3ac256 | 456 | |
mvanderpohl | 0:660f0e3ac256 | 457 | |
mvanderpohl | 0:660f0e3ac256 | 458 | |
mvanderpohl | 0:660f0e3ac256 | 459 | if(fscanf(fp, "%d", &recordLength)) //first read the size of the array |
mvanderpohl | 0:660f0e3ac256 | 460 | { |
mvanderpohl | 0:660f0e3ac256 | 461 | pc.printf("Write of length of sucessful and its value is %d\r\n\n", recordLength); |
mvanderpohl | 0:660f0e3ac256 | 462 | //wait_ms(1000); |
mvanderpohl | 0:660f0e3ac256 | 463 | } |
mvanderpohl | 0:660f0e3ac256 | 464 | else |
mvanderpohl | 0:660f0e3ac256 | 465 | return false; |
mvanderpohl | 0:660f0e3ac256 | 466 | |
mvanderpohl | 0:660f0e3ac256 | 467 | for(int i=0; i<recordLength; i++) //copy all values over |
mvanderpohl | 0:660f0e3ac256 | 468 | { |
mvanderpohl | 0:660f0e3ac256 | 469 | if(fscanf(fp, "%f", &record[i])) |
mvanderpohl | 0:660f0e3ac256 | 470 | pc.printf("Tone stored is %f\r\n\n", record[i]); |
mvanderpohl | 0:660f0e3ac256 | 471 | else |
mvanderpohl | 0:660f0e3ac256 | 472 | return false; |
mvanderpohl | 0:660f0e3ac256 | 473 | } |
mvanderpohl | 0:660f0e3ac256 | 474 | //wait_ms(1000); |
mvanderpohl | 0:660f0e3ac256 | 475 | fclose(fp); |
mvanderpohl | 0:660f0e3ac256 | 476 | return true; |
mvanderpohl | 0:660f0e3ac256 | 477 | }//end read |
mvanderpohl | 0:660f0e3ac256 | 478 | |
mvanderpohl | 0:660f0e3ac256 | 479 | //remove the file from the SD card before we create a new one |
mvanderpohl | 0:660f0e3ac256 | 480 | bool removeFile() |
mvanderpohl | 0:660f0e3ac256 | 481 | { |
mvanderpohl | 0:660f0e3ac256 | 482 | //create a string |
mvanderpohl | 0:660f0e3ac256 | 483 | char filename[] = "/sd/sdfile.txt"; |
mvanderpohl | 0:660f0e3ac256 | 484 | |
mvanderpohl | 0:660f0e3ac256 | 485 | int ret = remove(filename); |
mvanderpohl | 0:660f0e3ac256 | 486 | |
mvanderpohl | 0:660f0e3ac256 | 487 | if(ret == 0) |
mvanderpohl | 0:660f0e3ac256 | 488 | { |
mvanderpohl | 0:660f0e3ac256 | 489 | pc.printf("File deleted successfully"); |
mvanderpohl | 0:660f0e3ac256 | 490 | return false; |
mvanderpohl | 0:660f0e3ac256 | 491 | } |
mvanderpohl | 0:660f0e3ac256 | 492 | else |
mvanderpohl | 0:660f0e3ac256 | 493 | { |
mvanderpohl | 0:660f0e3ac256 | 494 | pc.printf("Error: unable to delete the file"); |
mvanderpohl | 0:660f0e3ac256 | 495 | } |
mvanderpohl | 0:660f0e3ac256 | 496 | return true; |
mvanderpohl | 0:660f0e3ac256 | 497 | } |