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