
Bluetooth Enabled Keyboard/Synthesizer
Dependencies: 4DGL-uLCD-SE SDFileSystem mbed-rtos mbed
Fork of 4180_Final_Design_Project by
main.cpp@26:d4000870deab, 2016-05-01 (annotated)
- Committer:
- Jake867
- Date:
- Sun May 01 22:51:18 2016 +0000
- Revision:
- 26:d4000870deab
- Parent:
- 25:5a312725710a
Set
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jmpin | 0:48311ffdfa96 | 1 | #include "mbed.h" |
jmpin | 3:3aba1d783730 | 2 | #include "SDFileSystem.h" |
jmpin | 6:68c6a50e1437 | 3 | #include "rtos.h" |
jmpin | 6:68c6a50e1437 | 4 | #include <vector> |
jmpin | 6:68c6a50e1437 | 5 | #include "uLCD_4DGL.h" |
jmpin | 3:3aba1d783730 | 6 | #include "synthesizer.h" |
Jake867 | 21:0df25c61c475 | 7 | #include "Speaker.h" |
Jake867 | 11:c87f55a3b9e0 | 8 | RawSerial Blue(p13,p14); |
Jake867 | 11:c87f55a3b9e0 | 9 | RawSerial PC(USBTX,USBRX); |
jmpin | 0:48311ffdfa96 | 10 | DigitalOut myled(LED1); |
jmpin | 0:48311ffdfa96 | 11 | DigitalOut myled4(LED4); |
jmpin | 3:3aba1d783730 | 12 | |
jmpin | 3:3aba1d783730 | 13 | SDFileSystem sd(p5, p6, p7, p8, "sd"); //SD card setup |
jmpin | 3:3aba1d783730 | 14 | |
Jake867 | 11:c87f55a3b9e0 | 15 | uLCD_4DGL uLCD(p28,p27,p30); // serial tx, serial rx, reset pin; |
jmpin | 6:68c6a50e1437 | 16 | |
Jake867 | 21:0df25c61c475 | 17 | Speaker mySpeaker(p18);; // p18 is the pin that will have the output voltages on it |
jmpin | 8:f6699fd30737 | 18 | |
jmpin | 6:68c6a50e1437 | 19 | |
jmpin | 0:48311ffdfa96 | 20 | //global variables for main and interrupt routine |
Jake867 | 11:c87f55a3b9e0 | 21 | volatile bool readyFlag = false; |
jmpin | 0:48311ffdfa96 | 22 | volatile char keyPress; |
jmpin | 3:3aba1d783730 | 23 | WaveType myWave = sine; // default to sine wave |
jmpin | 3:3aba1d783730 | 24 | volatile int currentOctave = 4; // default to 4 because thats where middle C is |
jmpin | 24:3bd4e691ae59 | 25 | int currentADSR = 3; // value representing which envelope shape is currently selected. default is 3 |
jmpin | 24:3bd4e691ae59 | 26 | float attackVals[32] = {}; // array that holds the attack coefficients |
jmpin | 24:3bd4e691ae59 | 27 | float decayVals[32] = {}; // array that holds the decay coefficients |
jmpin | 24:3bd4e691ae59 | 28 | float sustainVals[32]= {}; // array that holds the sustain coefficients |
jmpin | 24:3bd4e691ae59 | 29 | float releaseVals[32] = {}; // array that holds the release coefficients |
jmpin | 24:3bd4e691ae59 | 30 | short unsigned Analog_out_data[32]; // holds the samples that will be output to p18 |
jmpin | 6:68c6a50e1437 | 31 | volatile int noteFreq; // the current frequency of the note being played |
jmpin | 24:3bd4e691ae59 | 32 | float noteDuration = 2.0f; // default note duration will be 2 seconds |
Jake867 | 26:d4000870deab | 33 | float attackPercentage[5] = {0.7, 0.05, 0.25, 0.05, 0.1}; // holds values for percentage of waveform that the attack should take up |
Jake867 | 26:d4000870deab | 34 | float decayPercentage[5] = {0.1, 0.05, 0.25, 0.05, 0.1}; // holds values for percentage of waveform that the decay should take up |
Jake867 | 26:d4000870deab | 35 | float sustainPercentage[5] = {0.1, 0.8, 0.25, 0.05, 0.3}; // holds values for the percentage of waveform that the sustain should take up |
Jake867 | 26:d4000870deab | 36 | float releasePercentage[5] = {0.1, 0.1, 0.25, 0.05, 0.1}; // holds values for the percentage of waveform that the sutain should take up |
Jake867 | 26:d4000870deab | 37 | float attackDuration; |
Jake867 | 26:d4000870deab | 38 | float decayDuration; |
Jake867 | 26:d4000870deab | 39 | float sustainDuration; |
Jake867 | 26:d4000870deab | 40 | float releaseDuration; |
Jake867 | 26:d4000870deab | 41 | float sustainAmplitude = 0.6; |
jmpin | 5:afd67e985df0 | 42 | |
jmpin | 5:afd67e985df0 | 43 | /* Coefficient Matrices Corresponding to Different Attack Values |
jmpin | 22:9c80f7bcef86 | 44 | each matrix is comprised of 4 elements (32/8). The first matrix corresponds |
jmpin | 12:d60a9d0052a7 | 45 | to an attack value of 5. |
jmpin | 5:afd67e985df0 | 46 | */ |
jmpin | 5:afd67e985df0 | 47 | |
Jake867 | 23:cf9d43d5a5b4 | 48 | float attackVals5[4] = {0 , 0.9 , 0.98 , 1}; //Approaches the maximum amplitude the quickest - corresponds to an attackValue of 5 |
jmpin | 22:9c80f7bcef86 | 49 | |
Jake867 | 23:cf9d43d5a5b4 | 50 | float attackVals4[4] = {0 , 0.78 , 0.92 , 1}; //Corresponds to an attackValue of 4 |
jmpin | 22:9c80f7bcef86 | 51 | |
Jake867 | 23:cf9d43d5a5b4 | 52 | float attackVals3[4] = {0 , 0.63 , 0.84 , 1}; //Corresponds to an attackValue of 3 |
jmpin | 22:9c80f7bcef86 | 53 | |
Jake867 | 23:cf9d43d5a5b4 | 54 | float attackVals2[4] = {0 , 0.5 , 0.75 , 1}; //Corresponds to an attackValue of 2 |
jmpin | 22:9c80f7bcef86 | 55 | |
Jake867 | 23:cf9d43d5a5b4 | 56 | float attackVals1[4] = {0 , 0.33 , 0.66 , 1}; //Approaches the mamimum amplitude the slowest, in a linear fashion - corresponds to an attackValue of 1 |
jmpin | 22:9c80f7bcef86 | 57 | |
jmpin | 6:68c6a50e1437 | 58 | int noteArray[7][7] = { // Array holding different note frequencies |
jmpin | 6:68c6a50e1437 | 59 | C1 , D1 , E1 , F1 , G1 , A1 , B1 , |
jmpin | 6:68c6a50e1437 | 60 | C2 , D2 , E2 , F2 , G2 , A2 , B2, |
jmpin | 6:68c6a50e1437 | 61 | C3 , D3 , E3 , F3 , G3 , A3 , B2 , |
jmpin | 6:68c6a50e1437 | 62 | C4 , D4 , E4 , F4 , G4 , A4 , B4 , |
jmpin | 6:68c6a50e1437 | 63 | C5 , D5 , E5 , F5 , G5 , A5 , B5 , |
jmpin | 6:68c6a50e1437 | 64 | C6 , D6 , E6 , F6 , G6 , A6 , B6 , |
jmpin | 6:68c6a50e1437 | 65 | C7 , D7 , E7 , F7 , G7 , A7 , B7 |
jmpin | 6:68c6a50e1437 | 66 | }; |
jmpin | 5:afd67e985df0 | 67 | |
jmpin | 12:d60a9d0052a7 | 68 | void uLCD_Display_Thread(void const *args){ // uLCD displays curernt waveform shape, current octave, and the values for the ADSR coefficients |
Jake867 | 11:c87f55a3b9e0 | 69 | while(1){ |
Jake867 | 11:c87f55a3b9e0 | 70 | uLCD.locate(0,0); |
jmpin | 12:d60a9d0052a7 | 71 | switch(myWave){ |
jmpin | 12:d60a9d0052a7 | 72 | case sine: |
jmpin | 15:8ff317cc5d2c | 73 | uLCD.printf("Shape: Sine \r\n"); // if wave type is sine wave, display sine |
jmpin | 12:d60a9d0052a7 | 74 | break; |
jmpin | 12:d60a9d0052a7 | 75 | case square: |
jmpin | 15:8ff317cc5d2c | 76 | uLCD.printf("Shape: Square \r\n"); // if wave type is square wave, display square |
jmpin | 12:d60a9d0052a7 | 77 | break; |
jmpin | 12:d60a9d0052a7 | 78 | case sawtooth: |
jmpin | 12:d60a9d0052a7 | 79 | uLCD.printf("Shape: Sawtooth\r\n"); // if wave type is sawtooth wave, display sawtooth |
jmpin | 12:d60a9d0052a7 | 80 | break; |
jmpin | 12:d60a9d0052a7 | 81 | default: |
jmpin | 12:d60a9d0052a7 | 82 | break; |
jmpin | 12:d60a9d0052a7 | 83 | } |
jmpin | 12:d60a9d0052a7 | 84 | uLCD.printf("Octave: %i\r\n",currentOctave); // displays octave |
Jake867 | 26:d4000870deab | 85 | uLCD.printf("ADSR: %i\r\n",currentADSR); // displays attack value |
Jake867 | 26:d4000870deab | 86 | uLCD.printf("Duration: %f\r\n", noteDuration); |
Jake867 | 11:c87f55a3b9e0 | 87 | } |
jmpin | 12:d60a9d0052a7 | 88 | } |
jmpin | 6:68c6a50e1437 | 89 | |
jmpin | 12:d60a9d0052a7 | 90 | void set_Note_Freq(int frequency){ // updates the frequency of the note being played |
jmpin | 6:68c6a50e1437 | 91 | noteFreq = frequency; |
jmpin | 6:68c6a50e1437 | 92 | } |
jmpin | 6:68c6a50e1437 | 93 | |
jmpin | 24:3bd4e691ae59 | 94 | /* Generates the coefficients that will shape the waveform */ |
jmpin | 24:3bd4e691ae59 | 95 | |
jmpin | 24:3bd4e691ae59 | 96 | void initialize_ADSRVals() |
jmpin | 6:68c6a50e1437 | 97 | { |
jmpin | 24:3bd4e691ae59 | 98 | for(int j = 0; j < 32; j++) |
jmpin | 24:3bd4e691ae59 | 99 | { |
jmpin | 24:3bd4e691ae59 | 100 | attackVals[j] = (float)j/32.0f; |
Jake867 | 26:d4000870deab | 101 | decayVals[j] = 1.0f - (j*((1-sustainAmplitude)/32)); |
jmpin | 24:3bd4e691ae59 | 102 | sustainVals[j] = (float)sustainAmplitude; |
jmpin | 24:3bd4e691ae59 | 103 | releaseVals[j] = (float)sustainAmplitude - (((sustainAmplitude)/32)*j); |
jmpin | 6:68c6a50e1437 | 104 | } |
jmpin | 6:68c6a50e1437 | 105 | } |
jmpin | 5:afd67e985df0 | 106 | |
jmpin | 24:3bd4e691ae59 | 107 | /* Generates the durations of each part of the waveform (attack,decay,sustain, and release)*/ |
jmpin | 6:68c6a50e1437 | 108 | |
jmpin | 24:3bd4e691ae59 | 109 | void generate_durations(int index) |
jmpin | 6:68c6a50e1437 | 110 | { |
jmpin | 24:3bd4e691ae59 | 111 | attackDuration = attackPercentage[index-1] * noteDuration; |
jmpin | 24:3bd4e691ae59 | 112 | decayDuration = decayPercentage[index-1] * noteDuration; |
jmpin | 24:3bd4e691ae59 | 113 | sustainDuration = sustainPercentage[index-1] * noteDuration; |
jmpin | 24:3bd4e691ae59 | 114 | releaseDuration = releasePercentage[index-1] * noteDuration; |
jmpin | 24:3bd4e691ae59 | 115 | } |
jmpin | 24:3bd4e691ae59 | 116 | |
jmpin | 12:d60a9d0052a7 | 117 | |
jmpin | 12:d60a9d0052a7 | 118 | |
jmpin | 12:d60a9d0052a7 | 119 | /* Applies the envelope to the waveform. Each set of coefficients is applied to a certain portion of the waveform to alter its shape. |
jmpin | 22:9c80f7bcef86 | 120 | The attack coefficients are appplied to the first 4 samples, the decay coefficients are applied to samples 5-8, the sustain coefficients |
jmpin | 22:9c80f7bcef86 | 121 | are applied to samples 9 - 28, and the release coefficients are appplied to samples 29-32. |
jmpin | 12:d60a9d0052a7 | 122 | */ |
jmpin | 6:68c6a50e1437 | 123 | |
jmpin | 12:d60a9d0052a7 | 124 | |
jmpin | 24:3bd4e691ae59 | 125 | |
jmpin | 5:afd67e985df0 | 126 | |
jmpin | 12:d60a9d0052a7 | 127 | void generate_sineWave(int frequency) // Generates samples for a sine wave of a given input frequency |
jmpin | 9:e4df1a31a098 | 128 | { |
Jake867 | 21:0df25c61c475 | 129 | for(int i = 0; i < 32 ; i++) |
jmpin | 9:e4df1a31a098 | 130 | { |
Jake867 | 21:0df25c61c475 | 131 | Analog_out_data[i] = int (65536.0 * ((1.0 + sin((float(i)/32.0*6.28318530717959)))/2.0)); // scaled to be 16bit |
jmpin | 9:e4df1a31a098 | 132 | } |
jmpin | 9:e4df1a31a098 | 133 | } |
jmpin | 9:e4df1a31a098 | 134 | |
jmpin | 12:d60a9d0052a7 | 135 | void generate_sawtoothWave(int frequency) // Generates samples for a sawtooth wave of a given input frequency |
jmpin | 9:e4df1a31a098 | 136 | { |
Jake867 | 21:0df25c61c475 | 137 | float t = 0; // Represents time |
Jake867 | 21:0df25c61c475 | 138 | for(int i = 0; i<32 ; i++) |
jmpin | 9:e4df1a31a098 | 139 | { |
Jake867 | 21:0df25c61c475 | 140 | Analog_out_data[i] = int(t * 65536.0); //scaled to 16bit |
Jake867 | 21:0df25c61c475 | 141 | t+= 1.0/32.0; // increment t for calculation of next value in the waveform |
jmpin | 9:e4df1a31a098 | 142 | } |
jmpin | 9:e4df1a31a098 | 143 | } |
jmpin | 9:e4df1a31a098 | 144 | |
jmpin | 12:d60a9d0052a7 | 145 | void generate_squareWave(int frequency) // Generates samples for a square wave of a given input frequency. Looks at whether we have seen an even or odd number of 'widths' to determine if wave should be high or low at given t |
jmpin | 9:e4df1a31a098 | 146 | { |
Jake867 | 21:0df25c61c475 | 147 | for(int i = 0; i < 32; i++){ |
Jake867 | 21:0df25c61c475 | 148 | if(i<16){ |
Jake867 | 21:0df25c61c475 | 149 | Analog_out_data[i] = 65535; //scaled to 16bit |
Jake867 | 21:0df25c61c475 | 150 | } |
Jake867 | 21:0df25c61c475 | 151 | else{ |
Jake867 | 21:0df25c61c475 | 152 | Analog_out_data[i] = 0; //scaled to 16bit |
Jake867 | 21:0df25c61c475 | 153 | } |
jmpin | 9:e4df1a31a098 | 154 | } |
jmpin | 9:e4df1a31a098 | 155 | } |
jmpin | 9:e4df1a31a098 | 156 | |
jmpin | 12:d60a9d0052a7 | 157 | /* Generates the waveforms that will be output to the AnalogOut pin after being altered by the ADSR coefficient matrices. |
jmpin | 12:d60a9d0052a7 | 158 | The envelope is only applied to sine waves here because when applied to the other wave shapes, the sound does not sounds good. |
jmpin | 12:d60a9d0052a7 | 159 | @param: frequency - the frequency of the waveform to be generated |
jmpin | 12:d60a9d0052a7 | 160 | @param: currentWaveType - the shape of the wave that needs to be generated |
jmpin | 12:d60a9d0052a7 | 161 | */ |
jmpin | 12:d60a9d0052a7 | 162 | |
jmpin | 12:d60a9d0052a7 | 163 | |
jmpin | 9:e4df1a31a098 | 164 | void create_samples(int frequency, WaveType currentWaveType) |
jmpin | 8:f6699fd30737 | 165 | { |
jmpin | 8:f6699fd30737 | 166 | switch(currentWaveType){ |
jmpin | 8:f6699fd30737 | 167 | case sine: |
jmpin | 8:f6699fd30737 | 168 | //Generate sine wave values |
jmpin | 8:f6699fd30737 | 169 | generate_sineWave(frequency); |
Jake867 | 26:d4000870deab | 170 | generate_durations(currentADSR); |
jmpin | 8:f6699fd30737 | 171 | break; |
jmpin | 8:f6699fd30737 | 172 | case square: |
jmpin | 8:f6699fd30737 | 173 | //Generate square wave values |
jmpin | 8:f6699fd30737 | 174 | generate_squareWave(frequency); |
Jake867 | 26:d4000870deab | 175 | generate_durations(currentADSR); |
jmpin | 8:f6699fd30737 | 176 | break; |
jmpin | 8:f6699fd30737 | 177 | case sawtooth: |
jmpin | 8:f6699fd30737 | 178 | //Generate sawtooth wave values |
jmpin | 8:f6699fd30737 | 179 | generate_sawtoothWave(frequency); |
Jake867 | 26:d4000870deab | 180 | generate_durations(currentADSR); |
jmpin | 8:f6699fd30737 | 181 | break; |
jmpin | 8:f6699fd30737 | 182 | default: |
jmpin | 8:f6699fd30737 | 183 | break; |
jmpin | 8:f6699fd30737 | 184 | } |
jmpin | 8:f6699fd30737 | 185 | } |
jmpin | 8:f6699fd30737 | 186 | |
jmpin | 5:afd67e985df0 | 187 | |
jmpin | 0:48311ffdfa96 | 188 | //Interrupt routine to parse message with one new character per serial RX interrupt |
jmpin | 0:48311ffdfa96 | 189 | void parse_message() |
jmpin | 0:48311ffdfa96 | 190 | { |
jmpin | 12:d60a9d0052a7 | 191 | //PC.printf("Parse_message was called"); |
Jake867 | 11:c87f55a3b9e0 | 192 | while(Blue.readable()) |
jmpin | 10:085c49fe2509 | 193 | { |
Jake867 | 11:c87f55a3b9e0 | 194 | keyPress = Blue.getc(); |
Jake867 | 11:c87f55a3b9e0 | 195 | readyFlag = true; |
jmpin | 10:085c49fe2509 | 196 | } |
jmpin | 0:48311ffdfa96 | 197 | } |
jmpin | 3:3aba1d783730 | 198 | |
jmpin | 3:3aba1d783730 | 199 | |
jmpin | 3:3aba1d783730 | 200 | /* |
jmpin | 3:3aba1d783730 | 201 | This function writes which note was just played to a text file on the SDCard. |
jmpin | 3:3aba1d783730 | 202 | The note played will be encoded in hexadecimal, as well as the octave, Attack Value, |
jmpin | 3:3aba1d783730 | 203 | Delay Value, Sustain Value, and Release Value. The format of the bits will be as follows: |
jmpin | 3:3aba1d783730 | 204 | | 3 bits | 3 bits | 3 bits | 3 bits | 3 bits | 3 bits | |
jmpin | 6:68c6a50e1437 | 205 | | Attack | Decay | Susttain | Release | Octave | Note | |
jmpin | 3:3aba1d783730 | 206 | For the 3 bits representing note, A will correspond to 1, B to 2, and so on. |
jmpin | 3:3aba1d783730 | 207 | For example, if the lower 3 bits corresponding to note are 001, then the note is an A. |
jmpin | 3:3aba1d783730 | 208 | |
jmpin | 3:3aba1d783730 | 209 | @param: The note that is being played/recorded into the text file |
jmpin | 3:3aba1d783730 | 210 | */ |
jmpin | 3:3aba1d783730 | 211 | |
jmpin | 3:3aba1d783730 | 212 | void write_to_SDCard(char note) |
jmpin | 3:3aba1d783730 | 213 | { |
Jake867 | 26:d4000870deab | 214 | int ADSRBits, OctaveBits, NoteBits; |
Jake867 | 26:d4000870deab | 215 | ADSRBits = currentADSR; |
jmpin | 2:f06ba516b1ad | 216 | |
jmpin | 3:3aba1d783730 | 217 | OctaveBits = currentOctave; |
jmpin | 3:3aba1d783730 | 218 | switch(note){ |
jmpin | 12:d60a9d0052a7 | 219 | case 'C': // a C corresponds to a 3 |
jmpin | 3:3aba1d783730 | 220 | NoteBits = 3; |
jmpin | 3:3aba1d783730 | 221 | break; |
jmpin | 3:3aba1d783730 | 222 | case 'D': |
jmpin | 12:d60a9d0052a7 | 223 | NoteBits = 4; // a D corresponds to a 4 |
jmpin | 3:3aba1d783730 | 224 | break; |
jmpin | 3:3aba1d783730 | 225 | case 'E': |
jmpin | 12:d60a9d0052a7 | 226 | NoteBits = 5; // an E corresponds to a 5 |
jmpin | 3:3aba1d783730 | 227 | break; |
jmpin | 3:3aba1d783730 | 228 | case 'F': |
jmpin | 12:d60a9d0052a7 | 229 | NoteBits = 6; // an F corresponds to a 6 |
jmpin | 3:3aba1d783730 | 230 | break; |
jmpin | 3:3aba1d783730 | 231 | case 'G': |
jmpin | 12:d60a9d0052a7 | 232 | NoteBits = 7; // a G corresponds to a 7 |
jmpin | 3:3aba1d783730 | 233 | break; |
jmpin | 3:3aba1d783730 | 234 | case 'A': |
jmpin | 12:d60a9d0052a7 | 235 | NoteBits = 1; // an A corresponds to a 1 |
jmpin | 3:3aba1d783730 | 236 | break; |
jmpin | 3:3aba1d783730 | 237 | case 'B': |
jmpin | 12:d60a9d0052a7 | 238 | NoteBits = 2; // a B corresponds to a 2 |
jmpin | 3:3aba1d783730 | 239 | break; |
jmpin | 3:3aba1d783730 | 240 | default: |
jmpin | 3:3aba1d783730 | 241 | NoteBits = 0; |
jmpin | 3:3aba1d783730 | 242 | break; |
jmpin | 3:3aba1d783730 | 243 | } |
jmpin | 3:3aba1d783730 | 244 | int writeVal; |
Jake867 | 26:d4000870deab | 245 | writeVal = (ADSRBits << 6) | (OctaveBits << 3) | (NoteBits); |
jmpin | 22:9c80f7bcef86 | 246 | FILE *fp = fopen("/sd/noteRecords/note_record_01.txt", "a"); // creates handle for file we want to write to |
jmpin | 3:3aba1d783730 | 247 | if(fp == NULL) { |
jmpin | 12:d60a9d0052a7 | 248 | error("Could not open file for write\n"); // if this is not a valid name, tell user there is an error |
jmpin | 3:3aba1d783730 | 249 | } |
jmpin | 3:3aba1d783730 | 250 | fprintf(fp,"%X\r\n",writeVal); // writes value to the text file in hexadecimal |
jmpin | 3:3aba1d783730 | 251 | fclose(fp); |
jmpin | 3:3aba1d783730 | 252 | } |
jmpin | 3:3aba1d783730 | 253 | |
jmpin | 0:48311ffdfa96 | 254 | int main() |
jmpin | 0:48311ffdfa96 | 255 | { |
jmpin | 12:d60a9d0052a7 | 256 | Thread thread1(uLCD_Display_Thread); // the thread that displays the current values of the parameters as well as the octave and wave shape |
jmpin | 10:085c49fe2509 | 257 | |
jmpin | 12:d60a9d0052a7 | 258 | |
jmpin | 12:d60a9d0052a7 | 259 | mkdir("/sd/noteRecords", 0777); // make directory to hold the record of notes played |
Jake867 | 26:d4000870deab | 260 | FILE *fp = fopen("/sd/noteRecords/note_record_01.txt", "w"); // creates handle for file we want to write to |
Jake867 | 26:d4000870deab | 261 | if(fp == NULL) { |
Jake867 | 26:d4000870deab | 262 | error("Could not open file for write\n"); // if this is not a valid name, tell user there is an error |
Jake867 | 26:d4000870deab | 263 | } |
Jake867 | 26:d4000870deab | 264 | fprintf(fp,""); // writes value to the text file in hexadecimal |
Jake867 | 26:d4000870deab | 265 | fclose(fp); |
jmpin | 3:3aba1d783730 | 266 | |
jmpin | 24:3bd4e691ae59 | 267 | initialize_ADSRVals(); // fill the lookup tables for ADSR percentages |
Jake867 | 11:c87f55a3b9e0 | 268 | |
jmpin | 12:d60a9d0052a7 | 269 | PC.baud(9600); // setup baud rate for PC serial connection |
jmpin | 12:d60a9d0052a7 | 270 | Blue.baud(9600); // setup baud rate for bluetooth serial connection |
jmpin | 3:3aba1d783730 | 271 | |
jmpin | 12:d60a9d0052a7 | 272 | |
jmpin | 12:d60a9d0052a7 | 273 | Blue.attach(&parse_message,Serial::RxIrq); //attach interrupt function for each new Bluetooth serial character |
jmpin | 0:48311ffdfa96 | 274 | while(1) { |
jmpin | 0:48311ffdfa96 | 275 | //check for a new button message ready |
jmpin | 13:25d53936d385 | 276 | if((keyPress == C_NOTE_KEY) && (readyFlag)){ // Play note C |
jmpin | 12:d60a9d0052a7 | 277 | set_Note_Freq(noteArray[currentOctave-1][0]); // set the note frequency to the proper value |
jmpin | 13:25d53936d385 | 278 | create_samples(noteFreq, myWave); // creates the samples that are going to be output to the waveform |
Jake867 | 26:d4000870deab | 279 | mySpeaker.PlayNote(noteFreq, attackDuration, attackVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 280 | mySpeaker.PlayNote(noteFreq, decayDuration, decayVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 281 | mySpeaker.PlayNote(noteFreq, sustainDuration, sustainVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 282 | mySpeaker.PlayNote(noteFreq, releaseDuration, releaseVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
jmpin | 13:25d53936d385 | 283 | write_to_SDCard('C'); // writes to the SD card |
jmpin | 13:25d53936d385 | 284 | readyFlag = false; // set this flag to false so that the program will not try to process the key press more than once |
jmpin | 13:25d53936d385 | 285 | |
Jake867 | 11:c87f55a3b9e0 | 286 | } |
jmpin | 13:25d53936d385 | 287 | else if((keyPress == D_NOTE_KEY) && (readyFlag)){ // Play note D |
jmpin | 15:8ff317cc5d2c | 288 | set_Note_Freq(noteArray[currentOctave-1][1]); |
jmpin | 15:8ff317cc5d2c | 289 | create_samples(noteFreq, myWave); |
Jake867 | 26:d4000870deab | 290 | mySpeaker.PlayNote(noteFreq, attackDuration, attackVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 291 | mySpeaker.PlayNote(noteFreq, decayDuration, decayVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 292 | mySpeaker.PlayNote(noteFreq, sustainDuration, sustainVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 293 | mySpeaker.PlayNote(noteFreq, releaseDuration, releaseVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
jmpin | 15:8ff317cc5d2c | 294 | write_to_SDCard('D'); |
jmpin | 15:8ff317cc5d2c | 295 | readyFlag = false; |
jmpin | 13:25d53936d385 | 296 | |
Jake867 | 11:c87f55a3b9e0 | 297 | } |
jmpin | 13:25d53936d385 | 298 | else if((keyPress == E_NOTE_KEY) && (readyFlag)){ // Play note E |
jmpin | 6:68c6a50e1437 | 299 | set_Note_Freq(noteArray[currentOctave-1][2]); |
jmpin | 9:e4df1a31a098 | 300 | create_samples(noteFreq, myWave); |
Jake867 | 26:d4000870deab | 301 | mySpeaker.PlayNote(noteFreq, attackDuration, attackVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 302 | mySpeaker.PlayNote(noteFreq, decayDuration, decayVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 303 | mySpeaker.PlayNote(noteFreq, sustainDuration, sustainVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 304 | mySpeaker.PlayNote(noteFreq, releaseDuration, releaseVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
jmpin | 3:3aba1d783730 | 305 | write_to_SDCard('E'); |
jmpin | 4:406f59c6a1a6 | 306 | readyFlag = false; |
Jake867 | 11:c87f55a3b9e0 | 307 | } |
jmpin | 13:25d53936d385 | 308 | else if((keyPress == F_NOTE_KEY) && (readyFlag)){ // Play note F |
jmpin | 6:68c6a50e1437 | 309 | set_Note_Freq(noteArray[currentOctave-1][3]); |
jmpin | 9:e4df1a31a098 | 310 | create_samples(noteFreq, myWave); |
Jake867 | 26:d4000870deab | 311 | mySpeaker.PlayNote(noteFreq, attackDuration, attackVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 312 | mySpeaker.PlayNote(noteFreq, decayDuration, decayVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 313 | mySpeaker.PlayNote(noteFreq, sustainDuration, sustainVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 314 | mySpeaker.PlayNote(noteFreq, releaseDuration, releaseVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
jmpin | 3:3aba1d783730 | 315 | write_to_SDCard('F'); |
jmpin | 4:406f59c6a1a6 | 316 | readyFlag = false; |
Jake867 | 11:c87f55a3b9e0 | 317 | } |
jmpin | 13:25d53936d385 | 318 | else if((keyPress == G_NOTE_KEY) && (readyFlag)){ // Play note G |
jmpin | 6:68c6a50e1437 | 319 | set_Note_Freq(noteArray[currentOctave-1][4]); |
jmpin | 9:e4df1a31a098 | 320 | create_samples(noteFreq, myWave); |
Jake867 | 26:d4000870deab | 321 | mySpeaker.PlayNote(noteFreq, attackDuration, attackVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 322 | mySpeaker.PlayNote(noteFreq, decayDuration, decayVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 323 | mySpeaker.PlayNote(noteFreq, sustainDuration, sustainVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 324 | mySpeaker.PlayNote(noteFreq, releaseDuration, releaseVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
jmpin | 3:3aba1d783730 | 325 | write_to_SDCard('G'); |
jmpin | 4:406f59c6a1a6 | 326 | readyFlag = false; |
Jake867 | 11:c87f55a3b9e0 | 327 | } |
jmpin | 13:25d53936d385 | 328 | else if((keyPress == A_NOTE_KEY) && (readyFlag)){ // Play note A |
jmpin | 6:68c6a50e1437 | 329 | set_Note_Freq(noteArray[currentOctave][5]); |
jmpin | 9:e4df1a31a098 | 330 | create_samples(noteFreq, myWave); |
Jake867 | 26:d4000870deab | 331 | mySpeaker.PlayNote(noteFreq, attackDuration, attackVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 332 | mySpeaker.PlayNote(noteFreq, decayDuration, decayVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 333 | mySpeaker.PlayNote(noteFreq, sustainDuration, sustainVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 334 | mySpeaker.PlayNote(noteFreq, releaseDuration, releaseVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
jmpin | 3:3aba1d783730 | 335 | write_to_SDCard('A'); |
jmpin | 4:406f59c6a1a6 | 336 | readyFlag = false; |
Jake867 | 11:c87f55a3b9e0 | 337 | } |
jmpin | 15:8ff317cc5d2c | 338 | else if((keyPress == B_NOTE_KEY) && (readyFlag)){ // Play note B |
jmpin | 6:68c6a50e1437 | 339 | set_Note_Freq(noteArray[currentOctave][6]); |
jmpin | 9:e4df1a31a098 | 340 | create_samples(noteFreq, myWave); |
Jake867 | 26:d4000870deab | 341 | mySpeaker.PlayNote(noteFreq, attackDuration, attackVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 342 | mySpeaker.PlayNote(noteFreq, decayDuration, decayVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 343 | mySpeaker.PlayNote(noteFreq, sustainDuration, sustainVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
Jake867 | 26:d4000870deab | 344 | mySpeaker.PlayNote(noteFreq, releaseDuration, releaseVals, Analog_out_data); // outputs the samples that are currently in the buffer to p18 |
jmpin | 3:3aba1d783730 | 345 | write_to_SDCard('B'); |
jmpin | 4:406f59c6a1a6 | 346 | readyFlag = false; |
Jake867 | 11:c87f55a3b9e0 | 347 | } |
jmpin | 2:f06ba516b1ad | 348 | else if((keyPress == RAISE_OCTAVE_KEY) && (readyFlag)){ // button O pressed |
jmpin | 0:48311ffdfa96 | 349 | // Raise an octave |
jmpin | 6:68c6a50e1437 | 350 | if(currentOctave < 7) |
jmpin | 2:f06ba516b1ad | 351 | currentOctave++; |
jmpin | 4:406f59c6a1a6 | 352 | else |
jmpin | 4:406f59c6a1a6 | 353 | printf("Cannot raise octave above 7.\r\n"); |
Jake867 | 11:c87f55a3b9e0 | 354 | readyFlag = false; |
Jake867 | 11:c87f55a3b9e0 | 355 | } |
jmpin | 2:f06ba516b1ad | 356 | else if((keyPress == LOWER_OCTAVE_KEY) && (readyFlag)){ // button L pressed |
jmpin | 2:f06ba516b1ad | 357 | // Lower an octave |
jmpin | 4:406f59c6a1a6 | 358 | if(currentOctave > 1) |
jmpin | 2:f06ba516b1ad | 359 | currentOctave--; |
jmpin | 4:406f59c6a1a6 | 360 | else |
jmpin | 4:406f59c6a1a6 | 361 | printf("Cannot lower octave below 1.\r\n"); |
Jake867 | 11:c87f55a3b9e0 | 362 | readyFlag = false; |
Jake867 | 11:c87f55a3b9e0 | 363 | } |
jmpin | 24:3bd4e691ae59 | 364 | |
jmpin | 24:3bd4e691ae59 | 365 | else if((keyPress == RAISE_DURATION_KEY) && (readyFlag)){ // button E pressed |
jmpin | 24:3bd4e691ae59 | 366 | noteDuration++; |
Jake867 | 11:c87f55a3b9e0 | 367 | readyFlag = false; |
Jake867 | 11:c87f55a3b9e0 | 368 | } |
jmpin | 24:3bd4e691ae59 | 369 | else if((keyPress == LOWER_DURATION_KEY) && (readyFlag)){ // button D pressed |
jmpin | 24:3bd4e691ae59 | 370 | if(noteDuration >= 2) |
jmpin | 24:3bd4e691ae59 | 371 | noteDuration--; |
jmpin | 4:406f59c6a1a6 | 372 | else |
jmpin | 24:3bd4e691ae59 | 373 | printf("Cannot decrease duration further.\n\r"); |
Jake867 | 11:c87f55a3b9e0 | 374 | readyFlag = false; |
Jake867 | 11:c87f55a3b9e0 | 375 | } |
jmpin | 24:3bd4e691ae59 | 376 | else if((keyPress == RAISE_ADSR_KEY) && (readyFlag)){ // button R pressed |
jmpin | 24:3bd4e691ae59 | 377 | // Raise Release Value |
Jake867 | 26:d4000870deab | 378 | if(currentADSR < 5){ |
jmpin | 24:3bd4e691ae59 | 379 | currentADSR++; |
jmpin | 6:68c6a50e1437 | 380 | } |
jmpin | 4:406f59c6a1a6 | 381 | else |
jmpin | 4:406f59c6a1a6 | 382 | printf("Cannot raise value above 5.\r\n"); |
Jake867 | 11:c87f55a3b9e0 | 383 | readyFlag = false; |
Jake867 | 11:c87f55a3b9e0 | 384 | } |
jmpin | 24:3bd4e691ae59 | 385 | else if((keyPress == LOWER_ADSR_KEY) && (readyFlag)){ // button F pressed |
jmpin | 0:48311ffdfa96 | 386 | // Lower Release Value |
Jake867 | 26:d4000870deab | 387 | if(currentADSR > 1){ |
jmpin | 24:3bd4e691ae59 | 388 | currentADSR--; |
jmpin | 6:68c6a50e1437 | 389 | } |
jmpin | 4:406f59c6a1a6 | 390 | else |
jmpin | 6:68c6a50e1437 | 391 | printf("Cannot lower value below 1.\r\n"); |
Jake867 | 11:c87f55a3b9e0 | 392 | readyFlag = false; |
Jake867 | 11:c87f55a3b9e0 | 393 | } |
jmpin | 2:f06ba516b1ad | 394 | else if((keyPress == CHANGE_WAVESHAPE_UP) && (readyFlag)){ // button T pressed |
jmpin | 2:f06ba516b1ad | 395 | // Change waveform shape to next waveform type |
jmpin | 2:f06ba516b1ad | 396 | switch(myWave){ |
jmpin | 2:f06ba516b1ad | 397 | case sine: |
jmpin | 2:f06ba516b1ad | 398 | myWave = square; |
jmpin | 2:f06ba516b1ad | 399 | break; |
jmpin | 2:f06ba516b1ad | 400 | case square: |
jmpin | 2:f06ba516b1ad | 401 | myWave = sawtooth; |
jmpin | 2:f06ba516b1ad | 402 | break; |
jmpin | 2:f06ba516b1ad | 403 | case sawtooth: |
jmpin | 2:f06ba516b1ad | 404 | myWave = sine; |
jmpin | 2:f06ba516b1ad | 405 | break; |
jmpin | 2:f06ba516b1ad | 406 | default: |
jmpin | 2:f06ba516b1ad | 407 | break; |
jmpin | 2:f06ba516b1ad | 408 | } |
Jake867 | 11:c87f55a3b9e0 | 409 | readyFlag = false; |
Jake867 | 11:c87f55a3b9e0 | 410 | } |
jmpin | 2:f06ba516b1ad | 411 | else if((keyPress == CHANGE_WAVESHAPE_DOWN) && (readyFlag)){ // button G pressed |
jmpin | 2:f06ba516b1ad | 412 | // Change waveform shape to previous waveform type |
jmpin | 2:f06ba516b1ad | 413 | switch(myWave){ |
jmpin | 2:f06ba516b1ad | 414 | case sine: |
jmpin | 2:f06ba516b1ad | 415 | myWave = sawtooth; |
jmpin | 2:f06ba516b1ad | 416 | break; |
jmpin | 2:f06ba516b1ad | 417 | case square: |
jmpin | 2:f06ba516b1ad | 418 | myWave = sine; |
jmpin | 2:f06ba516b1ad | 419 | break; |
jmpin | 2:f06ba516b1ad | 420 | case sawtooth: |
jmpin | 2:f06ba516b1ad | 421 | myWave = square; |
jmpin | 2:f06ba516b1ad | 422 | break; |
jmpin | 2:f06ba516b1ad | 423 | default: |
jmpin | 2:f06ba516b1ad | 424 | break; |
jmpin | 2:f06ba516b1ad | 425 | } |
Jake867 | 11:c87f55a3b9e0 | 426 | readyFlag = false; |
Jake867 | 11:c87f55a3b9e0 | 427 | |
Jake867 | 11:c87f55a3b9e0 | 428 | } |
jmpin | 10:085c49fe2509 | 429 | } |
jmpin | 0:48311ffdfa96 | 430 | } |