Bluetooth Enabled Keyboard/Synthesizer for mbed

Dependencies:   mbed 4DGL-uLCD-SE SDFileSystem mbed-rtos

Committer:
Jake867
Date:
Sat Apr 30 23:01:52 2016 +0000
Revision:
23:cf9d43d5a5b4
Parent:
22:9c80f7bcef86
Child:
24:3bd4e691ae59
Changed generation of ADSR tables.

Who changed what in which revision?

UserRevisionLine numberNew 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 3:3aba1d783730 25 volatile int currentAttackVal = 3; // values will range from 1-5, default to 3
jmpin 6:68c6a50e1437 26 volatile int currentDecayVal = 3; // values will range from 1-5, default to 3
jmpin 3:3aba1d783730 27 volatile int currentSustainVal = 3; // values will range from 1-5, default to 3
jmpin 3:3aba1d783730 28 volatile int currentReleaseVal = 3; // values will range from 1-5, default to 3
Jake867 23:cf9d43d5a5b4 29 float currentAttackTable[4] = {0 , 0.63 , 0.84 , 1}; // pointer to the correct attack coefficient table
Jake867 23:cf9d43d5a5b4 30 float currentDecayTable[4] = {0.77 , 0.7 , 0.63 , 0.60}; // pointer to the correct decay coefficient table
Jake867 23:cf9d43d5a5b4 31 float currentSustainTable[20]= {0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6}; // pointer to the correct sustain coefficient table
Jake867 23:cf9d43d5a5b4 32 float currentReleaseTable[4] = {0.33 , 0.16 , 0.08 , 0}; // pointer to the correct release coefficient table
Jake867 21:0df25c61c475 33 short unsigned Analog_out_data[32];
Jake867 23:cf9d43d5a5b4 34 float coefficientMatrix[32]; // Array to hold all 32 coefficients for modulating the amplitude of the waveform
jmpin 6:68c6a50e1437 35 volatile int noteFreq; // the current frequency of the note being played
jmpin 5:afd67e985df0 36
jmpin 5:afd67e985df0 37 /* Coefficient Matrices Corresponding to Different Attack Values
jmpin 22:9c80f7bcef86 38 each matrix is comprised of 4 elements (32/8). The first matrix corresponds
jmpin 12:d60a9d0052a7 39 to an attack value of 5.
jmpin 5:afd67e985df0 40 */
jmpin 5:afd67e985df0 41
Jake867 23:cf9d43d5a5b4 42 float attackVals5[4] = {0 , 0.9 , 0.98 , 1}; //Approaches the maximum amplitude the quickest - corresponds to an attackValue of 5
jmpin 22:9c80f7bcef86 43
Jake867 23:cf9d43d5a5b4 44 float attackVals4[4] = {0 , 0.78 , 0.92 , 1}; //Corresponds to an attackValue of 4
jmpin 22:9c80f7bcef86 45
Jake867 23:cf9d43d5a5b4 46 float attackVals3[4] = {0 , 0.63 , 0.84 , 1}; //Corresponds to an attackValue of 3
jmpin 22:9c80f7bcef86 47
Jake867 23:cf9d43d5a5b4 48 float attackVals2[4] = {0 , 0.5 , 0.75 , 1}; //Corresponds to an attackValue of 2
jmpin 22:9c80f7bcef86 49
Jake867 23:cf9d43d5a5b4 50 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 51
jmpin 5:afd67e985df0 52
jmpin 12:d60a9d0052a7 53 /* Coefficient Matrices Corresponding to Different Decay Values
jmpin 22:9c80f7bcef86 54 each matrix is comprised of 4 elements (32/8). The first matrix corresponds
jmpin 12:d60a9d0052a7 55 to a decay value of 5.
jmpin 12:d60a9d0052a7 56 */
jmpin 12:d60a9d0052a7 57
Jake867 23:cf9d43d5a5b4 58 float decayVals5[4] = {0.67 , 0.63 , 0.62 , 0.6}; //Approaches the sustain amplitude the quickest - corresponds to a decay value of 5
Jake867 23:cf9d43d5a5b4 59 float decayVals4[4] = {0.73 , 0.675 , 0.63 , 0.60}; // Decay value of 4
Jake867 23:cf9d43d5a5b4 60 float decayVals3[4] = {0.77 , 0.7 , 0.63 , 0.60}; // Decay value of 3
Jake867 23:cf9d43d5a5b4 61 float decayVals2[4] = {0.84 , 0.73 , 0.65 , 0.6}; // Decay value of 2
Jake867 23:cf9d43d5a5b4 62 float decayVals1[4] = {0.9 , 0.8 , 0.7 , 0.6}; // Decays the slowest, in a linear fashion - corresponds to a decay value of 1
jmpin 8:f6699fd30737 63
jmpin 12:d60a9d0052a7 64 /* Coefficient Matrices Corresponding to Different sustain values
jmpin 22:9c80f7bcef86 65 each matrix is comprised of 20 elements 5 * (32/8). The first matrix corresponds
jmpin 12:d60a9d0052a7 66 to a sustain value of 5. The matrices get initialized later in a for loop due to their size.
jmpin 12:d60a9d0052a7 67 */
jmpin 12:d60a9d0052a7 68
Jake867 23:cf9d43d5a5b4 69 float sustainVals5[20];
Jake867 23:cf9d43d5a5b4 70 float sustainVals4[20];
Jake867 23:cf9d43d5a5b4 71 float sustainVals3[20];
Jake867 23:cf9d43d5a5b4 72 float sustainVals2[20];
Jake867 23:cf9d43d5a5b4 73 float sustainVals1[20];
jmpin 12:d60a9d0052a7 74
jmpin 12:d60a9d0052a7 75 /* Coefficient Matrices Corresponding to Different release values
jmpin 12:d60a9d0052a7 76 each matrix is comprised of 32 elements (256/8). The first matrix corresponds
jmpin 12:d60a9d0052a7 77 to a release value of 5.
jmpin 12:d60a9d0052a7 78 */
jmpin 12:d60a9d0052a7 79
Jake867 23:cf9d43d5a5b4 80 float releaseVals5[4] = {0.1 , 0.03 , 0.01 , 0}; // Releases (goes to 0 amplitude) the quickest - corresponds to a release value of 5
Jake867 23:cf9d43d5a5b4 81 float releaseVals4[4] = {0.2 , 0.1 , .04 , 0}; // Release value of 4
Jake867 23:cf9d43d5a5b4 82 float releaseVals3[4] = {0.33 , 0.16 , 0.08 , 0}; // Release value of 3
Jake867 23:cf9d43d5a5b4 83 float releaseVals2[4] = {0.4 , 0.23 , 0.1 , 0}; // Release value of 2
Jake867 23:cf9d43d5a5b4 84 float releaseVals1[4] = {0.45 , 0.30 , 0.15 , 0}; // Release value of 1 - proceeds slowest, in a linear fashion
jmpin 22:9c80f7bcef86 85
jmpin 5:afd67e985df0 86
jmpin 6:68c6a50e1437 87 int noteArray[7][7] = { // Array holding different note frequencies
jmpin 6:68c6a50e1437 88 C1 , D1 , E1 , F1 , G1 , A1 , B1 ,
jmpin 6:68c6a50e1437 89 C2 , D2 , E2 , F2 , G2 , A2 , B2,
jmpin 6:68c6a50e1437 90 C3 , D3 , E3 , F3 , G3 , A3 , B2 ,
jmpin 6:68c6a50e1437 91 C4 , D4 , E4 , F4 , G4 , A4 , B4 ,
jmpin 6:68c6a50e1437 92 C5 , D5 , E5 , F5 , G5 , A5 , B5 ,
jmpin 6:68c6a50e1437 93 C6 , D6 , E6 , F6 , G6 , A6 , B6 ,
jmpin 6:68c6a50e1437 94 C7 , D7 , E7 , F7 , G7 , A7 , B7
jmpin 6:68c6a50e1437 95 };
jmpin 5:afd67e985df0 96
jmpin 12:d60a9d0052a7 97 void uLCD_Display_Thread(void const *args){ // uLCD displays curernt waveform shape, current octave, and the values for the ADSR coefficients
Jake867 11:c87f55a3b9e0 98 while(1){
Jake867 11:c87f55a3b9e0 99 uLCD.locate(0,0);
jmpin 12:d60a9d0052a7 100 switch(myWave){
jmpin 12:d60a9d0052a7 101 case sine:
jmpin 15:8ff317cc5d2c 102 uLCD.printf("Shape: Sine \r\n"); // if wave type is sine wave, display sine
jmpin 12:d60a9d0052a7 103 break;
jmpin 12:d60a9d0052a7 104 case square:
jmpin 15:8ff317cc5d2c 105 uLCD.printf("Shape: Square \r\n"); // if wave type is square wave, display square
jmpin 12:d60a9d0052a7 106 break;
jmpin 12:d60a9d0052a7 107 case sawtooth:
jmpin 12:d60a9d0052a7 108 uLCD.printf("Shape: Sawtooth\r\n"); // if wave type is sawtooth wave, display sawtooth
jmpin 12:d60a9d0052a7 109 break;
jmpin 12:d60a9d0052a7 110 default:
jmpin 12:d60a9d0052a7 111 break;
jmpin 12:d60a9d0052a7 112 }
jmpin 12:d60a9d0052a7 113 uLCD.printf("Octave: %i\r\n",currentOctave); // displays octave
jmpin 12:d60a9d0052a7 114 uLCD.printf("Attack: %i\r\n",currentAttackVal); // displays attack value
jmpin 12:d60a9d0052a7 115 uLCD.printf("Decay: %i\r\n",currentDecayVal); // displays decay value
jmpin 12:d60a9d0052a7 116 uLCD.printf("Sustain: %i\r\n",currentSustainVal); // displays sustain value
jmpin 12:d60a9d0052a7 117 uLCD.printf("Release: %i\r\n",currentReleaseVal); // displays release value
Jake867 11:c87f55a3b9e0 118 }
jmpin 12:d60a9d0052a7 119 }
jmpin 6:68c6a50e1437 120
jmpin 12:d60a9d0052a7 121 void set_Note_Freq(int frequency){ // updates the frequency of the note being played
jmpin 6:68c6a50e1437 122 noteFreq = frequency;
jmpin 6:68c6a50e1437 123 }
jmpin 6:68c6a50e1437 124
jmpin 12:d60a9d0052a7 125 void change_Attack_Table(int attackVal) // change which table of coefficients to use for altering the attack portion of the waveform
jmpin 6:68c6a50e1437 126 {
Jake867 23:cf9d43d5a5b4 127 for(int i = 0; i < 4; i++){
Jake867 23:cf9d43d5a5b4 128 if( attackVal == 5){
Jake867 23:cf9d43d5a5b4 129 currentAttackTable[i] = attackVals5[i];
Jake867 23:cf9d43d5a5b4 130 }
Jake867 23:cf9d43d5a5b4 131 else if( attackVal == 4){
Jake867 23:cf9d43d5a5b4 132 currentAttackTable[i] = attackVals4[i];
Jake867 23:cf9d43d5a5b4 133 }
Jake867 23:cf9d43d5a5b4 134 else if( attackVal == 3){
Jake867 23:cf9d43d5a5b4 135 currentAttackTable[i] = attackVals3[i];
Jake867 23:cf9d43d5a5b4 136 }
Jake867 23:cf9d43d5a5b4 137 else if( attackVal == 2){
Jake867 23:cf9d43d5a5b4 138 currentAttackTable[i] = attackVals2[i];
Jake867 23:cf9d43d5a5b4 139 }
Jake867 23:cf9d43d5a5b4 140 else if( attackVal == 1){
Jake867 23:cf9d43d5a5b4 141 currentAttackTable[i] = attackVals1[i];
Jake867 23:cf9d43d5a5b4 142 }
jmpin 6:68c6a50e1437 143 }
jmpin 6:68c6a50e1437 144 }
jmpin 5:afd67e985df0 145
jmpin 12:d60a9d0052a7 146 void change_Decay_Table(int decayVal) // change which table of coefficients to use for altering the decay portion of the waveform
jmpin 6:68c6a50e1437 147 {
Jake867 23:cf9d43d5a5b4 148 for(int i = 0; i < 4; i++){
Jake867 23:cf9d43d5a5b4 149 if( decayVal == 5){
Jake867 23:cf9d43d5a5b4 150 currentDecayTable[i] = decayVals5[i];
Jake867 23:cf9d43d5a5b4 151 }
Jake867 23:cf9d43d5a5b4 152 else if( decayVal == 4){
Jake867 23:cf9d43d5a5b4 153 currentDecayTable[i] = decayVals4[i];
Jake867 23:cf9d43d5a5b4 154 }
Jake867 23:cf9d43d5a5b4 155 else if( decayVal == 3){
Jake867 23:cf9d43d5a5b4 156 currentDecayTable[i] = decayVals3[i];
Jake867 23:cf9d43d5a5b4 157 }
Jake867 23:cf9d43d5a5b4 158 else if( decayVal == 2){
Jake867 23:cf9d43d5a5b4 159 currentDecayTable[i] = decayVals2[i];
Jake867 23:cf9d43d5a5b4 160 }
Jake867 23:cf9d43d5a5b4 161 else if( decayVal == 1){
Jake867 23:cf9d43d5a5b4 162 currentDecayTable[i] = decayVals1[i];
Jake867 23:cf9d43d5a5b4 163 }
jmpin 6:68c6a50e1437 164 }
jmpin 6:68c6a50e1437 165 }
jmpin 5:afd67e985df0 166
jmpin 12:d60a9d0052a7 167 void change_Sustain_Table(int sustainVal) // change which table of coefficients to use for altering the sustain portion of the waveform
jmpin 6:68c6a50e1437 168 {
Jake867 23:cf9d43d5a5b4 169
Jake867 23:cf9d43d5a5b4 170 for(int i = 0; i < 20; i++){
Jake867 23:cf9d43d5a5b4 171 if( sustainVal == 5){
Jake867 23:cf9d43d5a5b4 172 currentSustainTable[i] = sustainVals5[i];
Jake867 23:cf9d43d5a5b4 173 }
Jake867 23:cf9d43d5a5b4 174 else if( sustainVal == 4){
Jake867 23:cf9d43d5a5b4 175 currentSustainTable[i] = sustainVals4[i];
Jake867 23:cf9d43d5a5b4 176 }
Jake867 23:cf9d43d5a5b4 177 else if( sustainVal == 3){
Jake867 23:cf9d43d5a5b4 178 currentSustainTable[i] = sustainVals3[i];
Jake867 23:cf9d43d5a5b4 179 }
Jake867 23:cf9d43d5a5b4 180 else if( sustainVal == 2){
Jake867 23:cf9d43d5a5b4 181 currentSustainTable[i] = sustainVals2[i];
Jake867 23:cf9d43d5a5b4 182 }
Jake867 23:cf9d43d5a5b4 183 else if( sustainVal == 1){
Jake867 23:cf9d43d5a5b4 184 currentSustainTable[i] = sustainVals1[i];
Jake867 23:cf9d43d5a5b4 185 }
jmpin 6:68c6a50e1437 186 }
jmpin 6:68c6a50e1437 187 }
jmpin 6:68c6a50e1437 188
jmpin 12:d60a9d0052a7 189 void change_Release_Table(int releaseVal) // change which table of coefficients to use for altering the release portion of the waveform
jmpin 6:68c6a50e1437 190 {
Jake867 23:cf9d43d5a5b4 191 for(int i = 0; i < 4; i++){
Jake867 23:cf9d43d5a5b4 192 if( releaseVal == 5){
Jake867 23:cf9d43d5a5b4 193 currentReleaseTable[i] = releaseVals5[i];
Jake867 23:cf9d43d5a5b4 194 }
Jake867 23:cf9d43d5a5b4 195 else if( releaseVal == 4){
Jake867 23:cf9d43d5a5b4 196 currentReleaseTable[i] = releaseVals4[i];
Jake867 23:cf9d43d5a5b4 197 }
Jake867 23:cf9d43d5a5b4 198 else if( releaseVal == 3){
Jake867 23:cf9d43d5a5b4 199 currentReleaseTable[i] = releaseVals3[i];
Jake867 23:cf9d43d5a5b4 200 }
Jake867 23:cf9d43d5a5b4 201 else if( releaseVal == 2){
Jake867 23:cf9d43d5a5b4 202 currentReleaseTable[i] = releaseVals2[i];
Jake867 23:cf9d43d5a5b4 203 }
Jake867 23:cf9d43d5a5b4 204 else if( releaseVal == 1){
Jake867 23:cf9d43d5a5b4 205 currentReleaseTable[i] = releaseVals1[i];
Jake867 23:cf9d43d5a5b4 206 }
jmpin 6:68c6a50e1437 207 }
jmpin 6:68c6a50e1437 208 }
jmpin 12:d60a9d0052a7 209
jmpin 12:d60a9d0052a7 210 /* Having different sustain values for the amplitude of the wave would make the math neccesary to generate the other
jmpin 12:d60a9d0052a7 211 coefficient matrices very complex, so only .6 is used, meaning a sustain value of 1-5 will all correspond to a sustain amplitude
jmpin 22:9c80f7bcef86 212 of .6. Since the sustain coefficient matrices are 20 elements long, they are all filled in a for loop with this function call.
jmpin 12:d60a9d0052a7 213 */
jmpin 12:d60a9d0052a7 214
jmpin 12:d60a9d0052a7 215 void initialize_sustainVals()
jmpin 8:f6699fd30737 216 {
jmpin 22:9c80f7bcef86 217 for(int j = 0; j < 20; j++)
jmpin 8:f6699fd30737 218 {
jmpin 8:f6699fd30737 219 sustainVals5[j] = .6;
jmpin 8:f6699fd30737 220 sustainVals4[j] = .6;
jmpin 8:f6699fd30737 221 sustainVals3[j] = .6;
jmpin 8:f6699fd30737 222 sustainVals2[j] = .6;
jmpin 8:f6699fd30737 223 sustainVals1[j] = .6;
jmpin 8:f6699fd30737 224 }
jmpin 8:f6699fd30737 225 }
jmpin 12:d60a9d0052a7 226 /* 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 227 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 228 are applied to samples 9 - 28, and the release coefficients are appplied to samples 29-32.
jmpin 12:d60a9d0052a7 229 */
jmpin 6:68c6a50e1437 230
jmpin 12:d60a9d0052a7 231
jmpin 12:d60a9d0052a7 232 void apply_Envelope(void){
jmpin 22:9c80f7bcef86 233 for(int j = 0; j < 32 ; j++)
jmpin 6:68c6a50e1437 234 {
Jake867 23:cf9d43d5a5b4 235 if( j < 4 ){
jmpin 22:9c80f7bcef86 236 coefficientMatrix[j] = currentAttackTable[j];
Jake867 23:cf9d43d5a5b4 237 //PC.printf("%f\n\r", currentAttackTable[j]);
Jake867 23:cf9d43d5a5b4 238 }
Jake867 23:cf9d43d5a5b4 239 else if(( j < 8) && ( j > 3)){
Jake867 23:cf9d43d5a5b4 240 coefficientMatrix[j] = currentDecayTable[j-4];
Jake867 23:cf9d43d5a5b4 241 //PC.printf("%f\n\r", currentDecayTable[j-4]);
Jake867 23:cf9d43d5a5b4 242 }
Jake867 23:cf9d43d5a5b4 243 else if(( j < 28) && (j > 7)){
Jake867 23:cf9d43d5a5b4 244 coefficientMatrix[j] = currentSustainTable[j-8];
Jake867 23:cf9d43d5a5b4 245 //PC.printf("%f\n\r", currentSustainTable[j-8]);
Jake867 23:cf9d43d5a5b4 246 }
Jake867 23:cf9d43d5a5b4 247 else if(( j < 32) && (j > 27)){
Jake867 23:cf9d43d5a5b4 248 coefficientMatrix[j] = currentReleaseTable[j-28];
Jake867 23:cf9d43d5a5b4 249 //PC.printf("%f\n\r", currentReleaseTable[j-28]);
Jake867 23:cf9d43d5a5b4 250 }
Jake867 23:cf9d43d5a5b4 251 PC.printf("%f\n\r", coefficientMatrix[j]);
jmpin 6:68c6a50e1437 252 }
jmpin 6:68c6a50e1437 253 }
jmpin 5:afd67e985df0 254
jmpin 12:d60a9d0052a7 255 void generate_sineWave(int frequency) // Generates samples for a sine wave of a given input frequency
jmpin 9:e4df1a31a098 256 {
Jake867 21:0df25c61c475 257 for(int i = 0; i < 32 ; i++)
jmpin 9:e4df1a31a098 258 {
Jake867 21:0df25c61c475 259 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 260 }
jmpin 9:e4df1a31a098 261 }
jmpin 9:e4df1a31a098 262
jmpin 12:d60a9d0052a7 263 void generate_sawtoothWave(int frequency) // Generates samples for a sawtooth wave of a given input frequency
jmpin 9:e4df1a31a098 264 {
Jake867 21:0df25c61c475 265 float t = 0; // Represents time
Jake867 21:0df25c61c475 266 for(int i = 0; i<32 ; i++)
jmpin 9:e4df1a31a098 267 {
Jake867 21:0df25c61c475 268 Analog_out_data[i] = int(t * 65536.0); //scaled to 16bit
Jake867 21:0df25c61c475 269 t+= 1.0/32.0; // increment t for calculation of next value in the waveform
jmpin 9:e4df1a31a098 270 }
jmpin 9:e4df1a31a098 271 }
jmpin 9:e4df1a31a098 272
jmpin 12:d60a9d0052a7 273 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 274 {
Jake867 21:0df25c61c475 275 for(int i = 0; i < 32; i++){
Jake867 21:0df25c61c475 276 if(i<16){
Jake867 21:0df25c61c475 277 Analog_out_data[i] = 65535; //scaled to 16bit
Jake867 21:0df25c61c475 278 }
Jake867 21:0df25c61c475 279 else{
Jake867 21:0df25c61c475 280 Analog_out_data[i] = 0; //scaled to 16bit
Jake867 21:0df25c61c475 281 }
jmpin 9:e4df1a31a098 282 }
jmpin 9:e4df1a31a098 283 }
jmpin 9:e4df1a31a098 284
jmpin 12:d60a9d0052a7 285 /* Generates the waveforms that will be output to the AnalogOut pin after being altered by the ADSR coefficient matrices.
jmpin 12:d60a9d0052a7 286 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 287 @param: frequency - the frequency of the waveform to be generated
jmpin 12:d60a9d0052a7 288 @param: currentWaveType - the shape of the wave that needs to be generated
jmpin 12:d60a9d0052a7 289 */
jmpin 12:d60a9d0052a7 290
jmpin 12:d60a9d0052a7 291
jmpin 9:e4df1a31a098 292 void create_samples(int frequency, WaveType currentWaveType)
jmpin 8:f6699fd30737 293 {
jmpin 8:f6699fd30737 294 switch(currentWaveType){
jmpin 8:f6699fd30737 295 case sine:
jmpin 8:f6699fd30737 296 //Generate sine wave values
jmpin 8:f6699fd30737 297 generate_sineWave(frequency);
Jake867 23:cf9d43d5a5b4 298 apply_Envelope();
jmpin 8:f6699fd30737 299 break;
jmpin 8:f6699fd30737 300 case square:
jmpin 8:f6699fd30737 301 //Generate square wave values
jmpin 8:f6699fd30737 302 generate_squareWave(frequency);
Jake867 23:cf9d43d5a5b4 303 apply_Envelope();
jmpin 8:f6699fd30737 304 break;
jmpin 8:f6699fd30737 305 case sawtooth:
jmpin 8:f6699fd30737 306 //Generate sawtooth wave values
jmpin 8:f6699fd30737 307 generate_sawtoothWave(frequency);
Jake867 23:cf9d43d5a5b4 308 apply_Envelope();
jmpin 8:f6699fd30737 309 break;
jmpin 8:f6699fd30737 310 default:
jmpin 8:f6699fd30737 311 break;
jmpin 8:f6699fd30737 312 }
jmpin 8:f6699fd30737 313 }
jmpin 8:f6699fd30737 314
jmpin 5:afd67e985df0 315
jmpin 0:48311ffdfa96 316 //Interrupt routine to parse message with one new character per serial RX interrupt
jmpin 0:48311ffdfa96 317 void parse_message()
jmpin 0:48311ffdfa96 318 {
jmpin 12:d60a9d0052a7 319 //PC.printf("Parse_message was called");
Jake867 11:c87f55a3b9e0 320 while(Blue.readable())
jmpin 10:085c49fe2509 321 {
Jake867 11:c87f55a3b9e0 322 keyPress = Blue.getc();
Jake867 11:c87f55a3b9e0 323 readyFlag = true;
jmpin 10:085c49fe2509 324 }
jmpin 0:48311ffdfa96 325 }
jmpin 3:3aba1d783730 326
jmpin 3:3aba1d783730 327
jmpin 3:3aba1d783730 328 /*
jmpin 3:3aba1d783730 329 This function writes which note was just played to a text file on the SDCard.
jmpin 3:3aba1d783730 330 The note played will be encoded in hexadecimal, as well as the octave, Attack Value,
jmpin 3:3aba1d783730 331 Delay Value, Sustain Value, and Release Value. The format of the bits will be as follows:
jmpin 3:3aba1d783730 332 | 3 bits | 3 bits | 3 bits | 3 bits | 3 bits | 3 bits |
jmpin 6:68c6a50e1437 333 | Attack | Decay | Susttain | Release | Octave | Note |
jmpin 3:3aba1d783730 334 For the 3 bits representing note, A will correspond to 1, B to 2, and so on.
jmpin 3:3aba1d783730 335 For example, if the lower 3 bits corresponding to note are 001, then the note is an A.
jmpin 3:3aba1d783730 336
jmpin 3:3aba1d783730 337 @param: The note that is being played/recorded into the text file
jmpin 3:3aba1d783730 338 */
jmpin 3:3aba1d783730 339
jmpin 3:3aba1d783730 340 void write_to_SDCard(char note)
jmpin 3:3aba1d783730 341 {
jmpin 6:68c6a50e1437 342 int AttackBits, SustainBits, DecayBits, ReleaseBits, OctaveBits, NoteBits;
jmpin 2:f06ba516b1ad 343
jmpin 12:d60a9d0052a7 344 AttackBits = currentAttackVal; // Holds the value of the attack parameter
jmpin 12:d60a9d0052a7 345 DecayBits = currentDecayVal; // Holds the value of the decay parameter
jmpin 12:d60a9d0052a7 346 SustainBits = currentSustainVal;// Holds the value of the sustain parameter
jmpin 12:d60a9d0052a7 347 ReleaseBits = currentReleaseVal;// Holds the value of the release parameter
jmpin 3:3aba1d783730 348 OctaveBits = currentOctave;
jmpin 3:3aba1d783730 349 switch(note){
jmpin 12:d60a9d0052a7 350 case 'C': // a C corresponds to a 3
jmpin 3:3aba1d783730 351 NoteBits = 3;
jmpin 3:3aba1d783730 352 break;
jmpin 3:3aba1d783730 353 case 'D':
jmpin 12:d60a9d0052a7 354 NoteBits = 4; // a D corresponds to a 4
jmpin 3:3aba1d783730 355 break;
jmpin 3:3aba1d783730 356 case 'E':
jmpin 12:d60a9d0052a7 357 NoteBits = 5; // an E corresponds to a 5
jmpin 3:3aba1d783730 358 break;
jmpin 3:3aba1d783730 359 case 'F':
jmpin 12:d60a9d0052a7 360 NoteBits = 6; // an F corresponds to a 6
jmpin 3:3aba1d783730 361 break;
jmpin 3:3aba1d783730 362 case 'G':
jmpin 12:d60a9d0052a7 363 NoteBits = 7; // a G corresponds to a 7
jmpin 3:3aba1d783730 364 break;
jmpin 3:3aba1d783730 365 case 'A':
jmpin 12:d60a9d0052a7 366 NoteBits = 1; // an A corresponds to a 1
jmpin 3:3aba1d783730 367 break;
jmpin 3:3aba1d783730 368 case 'B':
jmpin 12:d60a9d0052a7 369 NoteBits = 2; // a B corresponds to a 2
jmpin 3:3aba1d783730 370 break;
jmpin 3:3aba1d783730 371 default:
jmpin 3:3aba1d783730 372 NoteBits = 0;
jmpin 3:3aba1d783730 373 break;
jmpin 3:3aba1d783730 374 }
jmpin 3:3aba1d783730 375 int writeVal;
jmpin 6:68c6a50e1437 376 writeVal = (AttackBits << 15) | (DecayBits << 12) | (SustainBits << 9) | (ReleaseBits << 6) | (OctaveBits << 3) | (NoteBits);
jmpin 22:9c80f7bcef86 377 FILE *fp = fopen("/sd/noteRecords/note_record_01.txt", "a"); // creates handle for file we want to write to
jmpin 3:3aba1d783730 378 if(fp == NULL) {
jmpin 12:d60a9d0052a7 379 error("Could not open file for write\n"); // if this is not a valid name, tell user there is an error
jmpin 3:3aba1d783730 380 }
jmpin 3:3aba1d783730 381 fprintf(fp,"%X\r\n",writeVal); // writes value to the text file in hexadecimal
jmpin 3:3aba1d783730 382 fclose(fp);
jmpin 3:3aba1d783730 383 }
jmpin 3:3aba1d783730 384
jmpin 0:48311ffdfa96 385 int main()
jmpin 0:48311ffdfa96 386 {
jmpin 12:d60a9d0052a7 387 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 388
jmpin 12:d60a9d0052a7 389
jmpin 12:d60a9d0052a7 390 mkdir("/sd/noteRecords", 0777); // make directory to hold the record of notes played
jmpin 3:3aba1d783730 391
jmpin 12:d60a9d0052a7 392 initialize_sustainVals(); // fill the lookup tables with the sustain values in them
Jake867 11:c87f55a3b9e0 393
jmpin 12:d60a9d0052a7 394 PC.baud(9600); // setup baud rate for PC serial connection
jmpin 12:d60a9d0052a7 395 Blue.baud(9600); // setup baud rate for bluetooth serial connection
jmpin 3:3aba1d783730 396
jmpin 12:d60a9d0052a7 397
jmpin 12:d60a9d0052a7 398 Blue.attach(&parse_message,Serial::RxIrq); //attach interrupt function for each new Bluetooth serial character
jmpin 0:48311ffdfa96 399 while(1) {
jmpin 0:48311ffdfa96 400 //check for a new button message ready
jmpin 13:25d53936d385 401 if((keyPress == C_NOTE_KEY) && (readyFlag)){ // Play note C
jmpin 12:d60a9d0052a7 402 set_Note_Freq(noteArray[currentOctave-1][0]); // set the note frequency to the proper value
jmpin 13:25d53936d385 403 create_samples(noteFreq, myWave); // creates the samples that are going to be output to the waveform
Jake867 23:cf9d43d5a5b4 404 mySpeaker.PlayNote(noteFreq, 2, coefficientMatrix, Analog_out_data); // outputs the samples that are currently in the buffer to p18
jmpin 13:25d53936d385 405 write_to_SDCard('C'); // writes to the SD card
jmpin 13:25d53936d385 406 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 407
Jake867 11:c87f55a3b9e0 408 }
jmpin 13:25d53936d385 409 else if((keyPress == D_NOTE_KEY) && (readyFlag)){ // Play note D
jmpin 15:8ff317cc5d2c 410 set_Note_Freq(noteArray[currentOctave-1][1]);
jmpin 15:8ff317cc5d2c 411 create_samples(noteFreq, myWave);
Jake867 23:cf9d43d5a5b4 412 mySpeaker.PlayNote(noteFreq, 2, coefficientMatrix, Analog_out_data);
jmpin 15:8ff317cc5d2c 413 write_to_SDCard('D');
jmpin 15:8ff317cc5d2c 414 readyFlag = false;
jmpin 13:25d53936d385 415
Jake867 11:c87f55a3b9e0 416 }
jmpin 13:25d53936d385 417 else if((keyPress == E_NOTE_KEY) && (readyFlag)){ // Play note E
jmpin 6:68c6a50e1437 418 set_Note_Freq(noteArray[currentOctave-1][2]);
jmpin 9:e4df1a31a098 419 create_samples(noteFreq, myWave);
Jake867 23:cf9d43d5a5b4 420 mySpeaker.PlayNote(noteFreq, 2, coefficientMatrix, Analog_out_data);
jmpin 3:3aba1d783730 421 write_to_SDCard('E');
jmpin 4:406f59c6a1a6 422 readyFlag = false;
Jake867 11:c87f55a3b9e0 423 }
jmpin 13:25d53936d385 424 else if((keyPress == F_NOTE_KEY) && (readyFlag)){ // Play note F
jmpin 6:68c6a50e1437 425 set_Note_Freq(noteArray[currentOctave-1][3]);
jmpin 9:e4df1a31a098 426 create_samples(noteFreq, myWave);
Jake867 23:cf9d43d5a5b4 427 mySpeaker.PlayNote(noteFreq, 2, coefficientMatrix, Analog_out_data);
jmpin 3:3aba1d783730 428 write_to_SDCard('F');
jmpin 4:406f59c6a1a6 429 readyFlag = false;
Jake867 11:c87f55a3b9e0 430 }
jmpin 13:25d53936d385 431 else if((keyPress == G_NOTE_KEY) && (readyFlag)){ // Play note G
jmpin 6:68c6a50e1437 432 set_Note_Freq(noteArray[currentOctave-1][4]);
jmpin 9:e4df1a31a098 433 create_samples(noteFreq, myWave);
Jake867 23:cf9d43d5a5b4 434 mySpeaker.PlayNote(noteFreq, 2, coefficientMatrix, Analog_out_data);
jmpin 3:3aba1d783730 435 write_to_SDCard('G');
jmpin 4:406f59c6a1a6 436 readyFlag = false;
Jake867 11:c87f55a3b9e0 437 }
jmpin 13:25d53936d385 438 else if((keyPress == A_NOTE_KEY) && (readyFlag)){ // Play note A
jmpin 6:68c6a50e1437 439 set_Note_Freq(noteArray[currentOctave][5]);
jmpin 9:e4df1a31a098 440 create_samples(noteFreq, myWave);
Jake867 23:cf9d43d5a5b4 441 mySpeaker.PlayNote(noteFreq, 2, coefficientMatrix, Analog_out_data);
jmpin 3:3aba1d783730 442 write_to_SDCard('A');
jmpin 4:406f59c6a1a6 443 readyFlag = false;
Jake867 11:c87f55a3b9e0 444 }
jmpin 15:8ff317cc5d2c 445 else if((keyPress == B_NOTE_KEY) && (readyFlag)){ // Play note B
jmpin 6:68c6a50e1437 446 set_Note_Freq(noteArray[currentOctave][6]);
jmpin 9:e4df1a31a098 447 create_samples(noteFreq, myWave);
Jake867 23:cf9d43d5a5b4 448 mySpeaker.PlayNote(noteFreq, 2, coefficientMatrix, Analog_out_data);
jmpin 3:3aba1d783730 449 write_to_SDCard('B');
jmpin 4:406f59c6a1a6 450 readyFlag = false;
Jake867 11:c87f55a3b9e0 451 }
jmpin 2:f06ba516b1ad 452 else if((keyPress == RAISE_OCTAVE_KEY) && (readyFlag)){ // button O pressed
jmpin 0:48311ffdfa96 453 // Raise an octave
jmpin 6:68c6a50e1437 454 if(currentOctave < 7)
jmpin 2:f06ba516b1ad 455 currentOctave++;
jmpin 4:406f59c6a1a6 456 else
jmpin 4:406f59c6a1a6 457 printf("Cannot raise octave above 7.\r\n");
Jake867 11:c87f55a3b9e0 458 readyFlag = false;
Jake867 11:c87f55a3b9e0 459 }
jmpin 2:f06ba516b1ad 460 else if((keyPress == LOWER_OCTAVE_KEY) && (readyFlag)){ // button L pressed
jmpin 2:f06ba516b1ad 461 // Lower an octave
jmpin 4:406f59c6a1a6 462 if(currentOctave > 1)
jmpin 2:f06ba516b1ad 463 currentOctave--;
jmpin 4:406f59c6a1a6 464 else
jmpin 4:406f59c6a1a6 465 printf("Cannot lower octave below 1.\r\n");
Jake867 11:c87f55a3b9e0 466 readyFlag = false;
Jake867 11:c87f55a3b9e0 467 }
jmpin 2:f06ba516b1ad 468 else if((keyPress == RAISE_ATTACK_KEY) && (readyFlag)){ // button Q pressed
jmpin 0:48311ffdfa96 469 // Raise Attack Value
jmpin 6:68c6a50e1437 470 if(currentAttackVal < 5){
jmpin 2:f06ba516b1ad 471 currentAttackVal++;
jmpin 6:68c6a50e1437 472 change_Attack_Table(currentAttackVal);
jmpin 6:68c6a50e1437 473 }
jmpin 4:406f59c6a1a6 474 else
jmpin 4:406f59c6a1a6 475 printf("Cannot raise value above 5.\r\n");
Jake867 11:c87f55a3b9e0 476 readyFlag = false;
Jake867 11:c87f55a3b9e0 477 }
jmpin 2:f06ba516b1ad 478 else if((keyPress == LOWER_ATTACK_KEY) && (readyFlag)){ // button A pressed
jmpin 0:48311ffdfa96 479 // Lower Attack Value
jmpin 6:68c6a50e1437 480 if(currentAttackVal > 1){
jmpin 2:f06ba516b1ad 481 currentAttackVal--;
jmpin 6:68c6a50e1437 482 change_Attack_Table(currentAttackVal);
jmpin 6:68c6a50e1437 483 }
jmpin 4:406f59c6a1a6 484 else
jmpin 6:68c6a50e1437 485 printf("Cannot lower value below 1.\r\n");
Jake867 11:c87f55a3b9e0 486 readyFlag = false;
Jake867 11:c87f55a3b9e0 487 }
jmpin 2:f06ba516b1ad 488 else if((keyPress == RAISE_DELAY_KEY) && (readyFlag)){ // button W pressed
jmpin 0:48311ffdfa96 489 // Raise Delay Value
jmpin 6:68c6a50e1437 490 if(currentDecayVal < 5){
jmpin 6:68c6a50e1437 491 currentDecayVal++;
jmpin 6:68c6a50e1437 492 change_Decay_Table(currentDecayVal);
jmpin 6:68c6a50e1437 493 }
jmpin 4:406f59c6a1a6 494 else
jmpin 4:406f59c6a1a6 495 printf("Cannot raise value above 5.\r\n");
Jake867 11:c87f55a3b9e0 496 readyFlag = false;
Jake867 11:c87f55a3b9e0 497 }
jmpin 2:f06ba516b1ad 498 else if((keyPress == LOWER_DELAY_KEY) && (readyFlag)){ // button S pressed
jmpin 0:48311ffdfa96 499 // Lower Delay Value
jmpin 6:68c6a50e1437 500 if(currentDecayVal > 1){
jmpin 6:68c6a50e1437 501 currentDecayVal--;
jmpin 6:68c6a50e1437 502 change_Decay_Table(currentDecayVal);
jmpin 6:68c6a50e1437 503 }
jmpin 4:406f59c6a1a6 504 else
jmpin 6:68c6a50e1437 505 printf("Cannot lower value below 1.\r\n");
Jake867 11:c87f55a3b9e0 506 readyFlag = false;
Jake867 11:c87f55a3b9e0 507 }
jmpin 2:f06ba516b1ad 508 else if((keyPress == RAISE_SUSTAIN_KEY) && (readyFlag)){ // button E pressed
jmpin 0:48311ffdfa96 509 // Raise Sustain Value
jmpin 6:68c6a50e1437 510 if(currentSustainVal < 5){
jmpin 2:f06ba516b1ad 511 currentSustainVal++;
jmpin 6:68c6a50e1437 512 change_Sustain_Table(currentSustainVal);
jmpin 6:68c6a50e1437 513 }
jmpin 4:406f59c6a1a6 514 else
jmpin 4:406f59c6a1a6 515 printf("Cannot raise value above 5.\r\n");
Jake867 11:c87f55a3b9e0 516 readyFlag = false;
Jake867 11:c87f55a3b9e0 517 }
jmpin 2:f06ba516b1ad 518 else if((keyPress == LOWER_SUSTAIN_KEY) && (readyFlag)){ // button D pressed
jmpin 0:48311ffdfa96 519 // Lower Sustain Value
jmpin 6:68c6a50e1437 520 if(currentSustainVal > 1){
jmpin 2:f06ba516b1ad 521 currentSustainVal--;
jmpin 6:68c6a50e1437 522 change_Sustain_Table(currentSustainVal);
jmpin 6:68c6a50e1437 523 }
jmpin 4:406f59c6a1a6 524 else
jmpin 6:68c6a50e1437 525 printf("Cannot lower value below 1.\r\n");
Jake867 11:c87f55a3b9e0 526 readyFlag = false;
Jake867 11:c87f55a3b9e0 527 }
jmpin 2:f06ba516b1ad 528 else if((keyPress == RAISE_RELEASE_KEY) && (readyFlag)){ // button R pressed
jmpin 0:48311ffdfa96 529 // Raise Release Value
jmpin 6:68c6a50e1437 530 if(currentReleaseVal < 5){
jmpin 2:f06ba516b1ad 531 currentReleaseVal++;
jmpin 6:68c6a50e1437 532 change_Release_Table(currentReleaseVal);
jmpin 6:68c6a50e1437 533 }
jmpin 4:406f59c6a1a6 534 else
jmpin 4:406f59c6a1a6 535 printf("Cannot raise value above 5.\r\n");
Jake867 11:c87f55a3b9e0 536 readyFlag = false;
Jake867 11:c87f55a3b9e0 537 }
jmpin 2:f06ba516b1ad 538 else if((keyPress == LOWER_RELEASE_KEY) && (readyFlag)){ // button F pressed
jmpin 0:48311ffdfa96 539 // Lower Release Value
jmpin 6:68c6a50e1437 540 if(currentReleaseVal > 1){
jmpin 2:f06ba516b1ad 541 currentReleaseVal--;
jmpin 6:68c6a50e1437 542 change_Release_Table(currentReleaseVal);
jmpin 6:68c6a50e1437 543 }
jmpin 4:406f59c6a1a6 544 else
jmpin 6:68c6a50e1437 545 printf("Cannot lower value below 1.\r\n");
Jake867 11:c87f55a3b9e0 546 readyFlag = false;
Jake867 11:c87f55a3b9e0 547 }
jmpin 2:f06ba516b1ad 548 else if((keyPress == CHANGE_WAVESHAPE_UP) && (readyFlag)){ // button T pressed
jmpin 2:f06ba516b1ad 549 // Change waveform shape to next waveform type
jmpin 2:f06ba516b1ad 550 switch(myWave){
jmpin 2:f06ba516b1ad 551 case sine:
jmpin 2:f06ba516b1ad 552 myWave = square;
jmpin 2:f06ba516b1ad 553 break;
jmpin 2:f06ba516b1ad 554 case square:
jmpin 2:f06ba516b1ad 555 myWave = sawtooth;
jmpin 2:f06ba516b1ad 556 break;
jmpin 2:f06ba516b1ad 557 case sawtooth:
jmpin 2:f06ba516b1ad 558 myWave = sine;
jmpin 2:f06ba516b1ad 559 break;
jmpin 2:f06ba516b1ad 560 default:
jmpin 2:f06ba516b1ad 561 break;
jmpin 2:f06ba516b1ad 562 }
Jake867 11:c87f55a3b9e0 563 readyFlag = false;
Jake867 11:c87f55a3b9e0 564 }
jmpin 2:f06ba516b1ad 565 else if((keyPress == CHANGE_WAVESHAPE_DOWN) && (readyFlag)){ // button G pressed
jmpin 2:f06ba516b1ad 566 // Change waveform shape to previous waveform type
jmpin 2:f06ba516b1ad 567 switch(myWave){
jmpin 2:f06ba516b1ad 568 case sine:
jmpin 2:f06ba516b1ad 569 myWave = sawtooth;
jmpin 2:f06ba516b1ad 570 break;
jmpin 2:f06ba516b1ad 571 case square:
jmpin 2:f06ba516b1ad 572 myWave = sine;
jmpin 2:f06ba516b1ad 573 break;
jmpin 2:f06ba516b1ad 574 case sawtooth:
jmpin 2:f06ba516b1ad 575 myWave = square;
jmpin 2:f06ba516b1ad 576 break;
jmpin 2:f06ba516b1ad 577 default:
jmpin 2:f06ba516b1ad 578 break;
jmpin 2:f06ba516b1ad 579 }
Jake867 11:c87f55a3b9e0 580 readyFlag = false;
Jake867 11:c87f55a3b9e0 581
Jake867 11:c87f55a3b9e0 582 }
jmpin 10:085c49fe2509 583 }
jmpin 0:48311ffdfa96 584 }