Bluetooth Enabled Keyboard/Synthesizer for mbed

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

main.cpp

Committer:
jmpin
Date:
2016-04-28
Revision:
7:d4c3260cb092
Parent:
6:68c6a50e1437
Child:
8:f6699fd30737

File content as of revision 7:d4c3260cb092:

#include "mbed.h"
#include "SDFileSystem.h"
#include "rtos.h"
#include <vector>
#include "uLCD_4DGL.h"
#include "synthesizer.h"
Serial Blue(p28,p27);
Serial PC(USBTX,USBRX);
DigitalOut myled(LED1);
DigitalOut myled4(LED4);

SDFileSystem sd(p5, p6, p7, p8, "sd"); //SD card setup

Mutex mtx;  //Mutex lock

uLCD_4DGL uLCD(p13,p14,p11); // serial tx, serial rx, reset pin;


//global variables for main and interrupt routine
volatile bool readyFlag = true;
volatile char keyPress;
WaveType myWave = sine; // default to sine wave
volatile int currentOctave = 4; // default to 4 because thats where middle C is
volatile int currentAttackVal = 3;   // values will range from 1-5, default to 3
volatile int currentDecayVal = 3;    // values will range from 1-5, default to 3
volatile int currentSustainVal = 3;  // values will range from 1-5, default to 3
volatile int currentReleaseVal = 3;  // values will range from 1-5, default to 3
int *currentLookupTable;            // pointer to the correct lookup table of values
int *currentAttackTable;            // pointer to the correct attack coefficient table
int *currentDecayTable;             // pointer to the correct decay coefficient table
int *currentSustainTable;           // pointer to the correct sustain coefficient table
int *currentReleaseTable;           // pointer to the correct release coefficient table
vector<double> sampleBuffer;        // vector to hold samples of generated waveform
volatile int lookupTableIndex;      // index used to find values in the lookup table for the waveforms
volatile int phaseAccumulator;      // stores phase accumulator which is used to index into the lookup table
int num_samples = 256;              // number of samples 
int shift_factor = 0x01000000;      // shifting factor
int sampling_frequency = 40000;     // sampling frequency is 40kHz
volatile int frequencyTuner;        // the frequency tuner used to increment the accumulator which indexes values in the lookup table
volatile int noteFreq;              // the current frequency of the note being played
volatile int sustainAmplitude;      // the desired amplitude of the sustain level

/* Coefficient Matrices Corresponding to Different Attack Values
each matrix is comprised of 32 elements (256/8). The first matrix corresponds
to an attack value of 1.
*/

double attackVals5[32] = {    //Approaches the maximum amplitude the quickest - corresponds to an attackValue of 5
0, 0.275 , 0.55 , 0.7 ,
0.8 , 0.85 , 0.9 , 0.91 ,
0.92 , 0.93 , 0.939 , 0.948 ,
0.956 , 0.963 , 0.969 , 0.974 ,
0.978 , 0.982 , 0.986 , 0.989 ,
0.991 , 0.992 , 0.993 , 0.994 ,
0.995 , 0.996 , 0.997 , 0.998 ,
0.9985 , 0.999 , 0.9995 , 1
};
double attackVals4[32] = {    //Corresponds to an attackValue of 4
0 , 0.18 , 0.38 , 0.58 , 
0.66 , 0.69 , 0.72 , 0.74 , 
0.76 , 0.78 , 0.795 , 0.81 , 
0.825 , 0.84 , 0.85 , 0.86 , 
0.87 , 0.88 , 0.89 , 0.9 , 
0.91 , 0.92 , 0.93 , 0.94 , 
0.95 , 0.96 , 0.97 , 0.98 , 
0.985 , 0.99 , 0.995 , 1
};
double attackVals3[32] = {    //Corresponds to an attackValue of 3
0 , 0.09 , 0.18 , 0.27 , 
0.35 , 0.43 , 0.5 , 0.57 , 
0.61 , 0.65 , 0.68 , 0.71 , 
0.74 , 0.76 , 0.78 , 0.8 , 
0.82 , 0.84 , 0.86 , 0.88 , 
0.895 , 0.91 , 0.925 , 0.94 , 
0.95 , 0.96 , 0.97 , 0.98 , 
0.985 , 0.99 , 0.995 , 1
};
double attackVals2[32] = {    //Corresponds to an attackValue of 2
0 , 0.06 , 0.12 , 0.18 , 
0.23 , 0.28 , 0.32 , 0.36 , 
0.4 , 0.44 , 0.48 , 0.52 , 
0.55 , 0.58 , 0.61 , 0.64 , 
0.67 , 0.695 , 0.72 , 0.745 , 
0.77 , 0.795 , 0.82 , 0.845 , 
0.87 , 0.895 , 0.92 , 0.945 , 
0.965 , 0.985 , 0.995 , 1
};
double attackVals1[32] = {    //Approaches the mamimum amplitude the slowest, in a linear fashion - corresponds to an attackValue of 1
0 , 0.032258065 , 0.064516129 , 0.096774194 , 
0.129032258 , 0.161290323 , 0.193548387 , 0.225806452 , 
0.258064516 , 0.290322581 , 0.322580645 , 0.35483871 , 
0.387096774 , 0.419354839 , 0.451612903 , 0.483870968 , 
0.516129032 , 0.548387097 , 0.580645161 , 0.612903226 , 
0.64516129 , 0.677419355 , 0.709677419 , 0.741935484 , 
0.774193548 , 0.806451613 , 0.838709677 , 0.870967742 , 
0.903225806 , 0.935483871 , 0.967741935 , 1
};

double decayVals5[32] = {   //Approaches the sustain amplitude the quickest - corresponds to a decay value of 5
1 , 0.8 , 0.75 , 0.71 , 
0.68 , 0.66 , 0.65 , 0.64 , 
0.635 , 0.63 , 0.625 , 0.62 , 
0.615 , 0.61 , 0.605 , 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
};
double decayVals4[32] = {
1 , 0.93 , 0.86 , 0.8 , 
0.75 , 0.71 , 0.69 , 0.68 , 
0.67 , 0.66 , 0.655 , 0.65 , 
0.645 , 0.64 , 0.635 , 0.63 , 
0.625 , 0.62 , 0.615 , 0.61 , 
0.605 , 0.6 , 0.6 , 0.6 , 
0.6 , 0.6 , 0.6 , 0.6 , 
0.6 , 0.6 , 0.6 , 0.6
};
double decayVals3[32] = {
1 , 0.96 , 0.92 , 0.88 , 
0.85 , 0.82 , 0.79 , 0.76 , 
0.74 , 0.72 , 0.705 , 0.69 , 
0.68 , 0.67 , 0.665 , 0.66 , 
0.655 , 0.65 , 0.645 , 0.64 , 
0.635 , 0.63 , 0.625 , 0.62 , 
0.615 , 0.61 , 0.605 , 0.6 , 
0.6 , 0.6 , 0.6 , 0.6
};
double decayVals2[32] = {
1 , 0.98 , 0.96 , 0.94 , 
0.92 , 0.9 , 0.88 , 0.86 , 
0.84 , 0.82 , 0.8 , 0.79 , 
0.78 , 0.77 , 0.76 , 0.75 , 
0.74 , 0.73 , 0.72 , 0.71 , 
0.7 , 0.69 , 0.68 , 0.67 , 
0.66 , 0.65 , 0.64 , 0.63 , 
0.62 , 0.61 , 0.6 , 0.6
};
double decayVals1[32] = {
1 , 0.987096774 , 0.974193548 , 0.961290323 , 
0.948387097 , 0.935483871 , 0.922580645 , 0.909677419 , 
0.896774194 , 0.883870968 , 0.870967742 , 0.858064516 , 
0.84516129 , 0.832258065 , 0.819354839 , 0.806451613 , 
0.793548387 , 0.780645161 , 0.767741935 , 0.75483871 , 
0.741935484 , 0.729032258 , 0.716129032 , 0.703225806 , 
0.690322581 , 0.677419355 , 0.664516129 , 0.651612903 , 
0.638709677 , 0.625806452 , 0.612903226 , 0.6
};
double sustainVals5[160] = {  //Highest level of sustain, the note will cap out at an amplitude of 1 - corresponds to sustain value of 5
.8 , .6 , .6 , .6 ,
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6  
};
double sustainVal4[160] = {   //Sustain value of 4
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6
};
double sustainVals3[160] = {  //Sustain value of 3
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6
};
double sustainVals2[160] = {  //Sustain value of 2
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6
};
double sustainVals1[160] = {  //Lowest level of sustain, the note will cap at at an amplitude of .2 - corresponds to sustain value of 1
.6 , .6 , .6 , .6 ,
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6 , 
.6 , .6 , .6 , .6
};
double releaseVals5[32] = {
    };
double releaseVals4[32] = {
    };
double releaseVals3[32] = {
    };
double releaseVals2[32] = {
    };
double releaseVals1[32] = {
    };
    
/* Values for the sine wave shaped waveform */
int sineTable[256] = {
0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,
0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,
0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,
0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8,
0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,
0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5,
0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,
0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,
0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,
0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,
0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc,
0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9,
0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3,
0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,
0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83,
0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a,
0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51,
0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b,
0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,
0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,
0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a,
0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,
0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,
0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08,
0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13,
0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23,
0x25,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,
0x38,0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c,
0x4f,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,
0x67,0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c
};
 
/* Values for the square shaped waveform */
int squareTable[256] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
};
 
/* Values for the sawtooth shaped waveform */
int sawtoothTable[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,
0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,
0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,
0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,
0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,
0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
};

int noteArray[7][7] = { // Array holding different note frequencies
  C1 , D1 , E1 , F1 , G1 , A1 , B1 ,
  C2 , D2 , E2 , F2 , G2 , A2 , B2,
  C3 , D3 , E3 , F3 , G3 , A3 , B2 , 
  C4 , D4 , E4 , F4 , G4 , A4 , B4 ,
  C5 , D5 , E5 , F5 , G5 , A5 , B5 ,
  C6 , D6 , E6 , F6 , G6 , A6 , B6 ,
  C7 , D7 , E7 , F7 , G7 , A7 , B7 
};

void uLCD_Display_Thread(void const *args){
    mtx.lock();
    uLCD.locate(0,0);
    uLCD.printf("Current Waveform Shape: %s\r\n",myWave);
    uLCD.printf("Current Octave: %i\r\n",currentOctave);
    uLCD.printf("Current Attack Value: %i\r\n",currentAttackVal);
    uLCD.printf("Current Decay Value: %i\r\n",currentDecayVal);
    uLCD.printf("Current Sustain Value: %i\r\n",currentSustainVal);
    uLCD.printf("Current Release Value: %i\r\n",currentReleaseVal);
    mtx.unlock();
    Thread::wait(250);
    }
    
void set_Frequency_Tuner(void) {
  frequencyTuner = ((((int)noteFreq) * num_samples) *
            (shift_factor / sampling_frequency));
}

void accumulator_Increment(void) {
  phaseAccumulator += frequencyTuner;
}

void accumulator_reset(void) {
  phaseAccumulator = 0;
}

void set_Note_Freq(int frequency){
    accumulator_reset();
    noteFreq = frequency;
    set_Frequency_Tuner();
    clear_buffer();
}

void change_Wave(const WaveType currentWave) {
  switch(currentWave) {
  case sine:
    currentLookupTable = sineTable;
    break;
  case square:
    currentLookupTable = squareTable;
    break;
  case sawtooth:
    currentLookupTable = sawtoothTable;
    break;
  default:
    break;
  }
}

void change_Attack_Table(int attackVal)
{
    switch(attackVal){
    case 5:
        currentAttackTable = attackVals5;
        break;
    case 4:
        currentAttackTable = attackVals4;
        break;
    case 3:
        currentAttackTable = attackVals3;
        break;
    case 2:
        currentAttackTable = attackVals2;
        break;
    case 1:
        currentAttackTable = attackVals1;
        break;
    default:
    break;
    }
}

void change_Decay_Table(int decayVal)
{
    switch(decayVal){
    case 5:
        currentDecayTable = decayVals5;
        break;
    case 4:
        currentDecayTable = decayVals4;
        break;
    case 3:
        currentDecayTable = decayVals3;
        break;
    case 2:
        currentDecayTable = decayVals2;
        break;
    case 1:
        currentDecayTable = decayVals1;
        break;
    default:
    break;
    }
}

void change_Sustain_Table(int sustainVal)
{
    switch(sustainVal){
    case 5:
        //sustainAmplitude = .8;
        currentSustainTable = sustainVals5;
        break;
    case 4:
        //sustainAmplitude = .65;
        currentSustainTable = sustainVals4;
        break;
    case 3:
        //sustainAmplitude = .5;
        currentSustainTable = sustainVals3;
        break;
    case 2:
        //sustainAmplitude = .35;
        currentSustainTable = sustainVals2;
        break;
    case 1:
        //sustainAmplitude = .2;
        currentSustainTable = sustainVals1;
        break;
    default:
    break;
    }
}

void change_Release_Table(int releaseVal)
{
    switch(releaseVal){
    case 5:
        currentReleaseTable = releaseVals5;
        break;
    case 4:
        currentReleaseTable = releaseVals4;
        break;
    case 3:
        currentReleaseTable = releaseVals3;
        break;
    case 2:
        currentReleaseTable = releaseVals2;
        break;
    case 1:
        currentReleaseTable = releaseVals1;
        break;
    default:
    break;
    }
} 

void clear_Buffer(void){
    sampleBuffer.clear();
}
    
void buffer_Samples(void){
    for(int j=0;j<num_samples;j++){
    accumulator_Increment(); // Increment the phase accumulator
    lookupTableIndex = phaseAccumulator >> 24; // Get address into wavetable    
    sampleBuffer.push_back(currentLookupTable[lookupTableIndex] / 255);  // divide by 255 so that we get values between 0 and 1
    }
}

void apply_Envelope(void){
    int attack_range, decay_range, sustain_range, release_range;
    attack_range = sampleBuffer.size() * (1/8);                     // The attack portion of the waveform will take (1/8) of the note's duration
    decay_range = attack_range + (sampleBuffer.size() * (1/8));     // The decay portion of the waveform will take (1/8) of the note's duration
    sustain_range = sustain_range + (sampleBuffer.size() * (5/8));  // The sustain portion of the waveform will take (5/8) of the note's duration
    release_range = release_range + (sampleBuffer.size() * (1/8));  // The release portion of the waveform will take (1/8) of the note's duration
    for(int i = 0; i < attack_range; i++)
    {
        sampleBuffer[i] = sampleBuffer[i] * currentAttackTable[i];
    }
    for(int k = attack_range; k < decay_range; k++)
    {
        sampleBuffer[k] = sampleBuffer[k] * currentDecayTable[k-attack_range];
    }
    for(int m = decay_range; m < sustain_range; m++)
    {
        sampleBuffer[m] = sampleBuffer[m] * currentSustainTable[m-decay_range];
    }
    for(int n = sustain_range; n < release_range; n++)
    {
        sampleBuffer[n] = sampleBuffer[n] * currentReleaseTable[n-sustain_range];
    }     
}










//Interrupt routine to parse message with one new character per serial RX interrupt
void parse_message()
{
    keyPress = Blue.getc();
    PC.putc(keyPress);
    readyFlag = true;
    PC.printf("\n\r Value of readyFlag is: %i",readyFlag);
    
    //PC.printf("Value of keyPress is: %c\n\r",keyPress);
}


/*
This function writes which note was just played to a text file on the SDCard.
The note played will be encoded in hexadecimal, as well as the octave, Attack Value,
Delay Value, Sustain Value, and Release Value. The format of the bits will be as follows:
| 3 bits | 3 bits | 3 bits | 3 bits | 3 bits | 3 bits |
| Attack | Decay | Susttain | Release | Octave | Note |
For the 3 bits representing note, A will correspond to 1, B to 2, and so on.
For example, if the lower 3 bits corresponding to note are 001, then the note is an A.

@param: The note that is being played/recorded into the text file
*/

void write_to_SDCard(char note)
{
    int AttackBits, SustainBits, DecayBits, ReleaseBits, OctaveBits, NoteBits;
 
    AttackBits = currentAttackVal;
    DecayBits = currentDecayVal;
    SustainBits = currentSustainVal;
    ReleaseBits = currentReleaseVal;
    OctaveBits = currentOctave;
    switch(note){
        case 'C':
            NoteBits = 3;
            break;
        case 'D':
            NoteBits = 4;
            break;
        case 'E':
            NoteBits = 5;
            break;
        case 'F':
            NoteBits = 6;
            break;
        case 'G':
            NoteBits = 7;
            break;
        case 'A':
            NoteBits = 1;
            break;
        case 'B':
            NoteBits = 2;
            break;
        default:
            NoteBits = 0;
            break;
        }
    int writeVal;
    writeVal  = (AttackBits << 15) | (DecayBits << 12) | (SustainBits << 9) | (ReleaseBits << 6) | (OctaveBits << 3) | (NoteBits);
    
    FILE *fp = fopen("/sd/noteRecords/note_record_01.txt", "w");
    if(fp == NULL) {
        error("Could not open file for write\n");
    }
    fprintf(fp,"%X\r\n",writeVal);      // writes value to the text file in hexadecimal
    fclose(fp);
}

int main()
{
// make directory to hold the record of notes played
mkdir("/sd/noteRecords", 0777);


//attach interrupt function for each new Bluetooth serial character
    Blue.attach(&parse_message,Serial::RxIrq);
    while(1) {
        //check for a new button message ready
        if((keyPress == C_NOTE_KEY) && (readyFlag)){ // button Z pressed
            set_Note_Freq(noteArray[currentOctave-1][0]);
            write_to_SDCard('C');
            readyFlag = false;
            // Play note that corresponds to Z
            }
        else if((keyPress == D_NOTE_KEY) && (readyFlag)){ // button X pressed
                set_Note_Freq(noteArray[currentOctave-1][1]);
                write_to_SDCard('D');
                readyFlag = false;
            // Play note that corresponds to X
            }
        else if((keyPress == E_NOTE_KEY) && (readyFlag)){ // button C pressed
            set_Note_Freq(noteArray[currentOctave-1][2]);
            // Play note that corresponds to C
            // Make note of which note was played in file on SD Card
            write_to_SDCard('E');
            readyFlag = false;
            }
        else if((keyPress == F_NOTE_KEY) && (readyFlag)){ // button V pressed
            set_Note_Freq(noteArray[currentOctave-1][3]);
            // Play note that corresponds to V
            // Make note of which note was played in file on SD Card
            write_to_SDCard('F');
            readyFlag = false;
            }
        else if((keyPress == G_NOTE_KEY) && (readyFlag)){ // button B pressed
            set_Note_Freq(noteArray[currentOctave-1][4]);
            // Play note that corresponds to B
            // Make note of which note was played in file on SD Card
            write_to_SDCard('G');
            readyFlag = false;
            }
        else if((keyPress == A_NOTE_KEY) && (readyFlag)){ // button N pressed
            set_Note_Freq(noteArray[currentOctave][5]);
            buffer_Samples();
            // Play note that corresponds to N
            // Make note of which note was played in file on SD Card
            write_to_SDCard('A');
            readyFlag = false;
            }
        else if((keyPress == B_NOTE_KEY) && (readyFlag)){ // button M pressed
            set_Note_Freq(noteArray[currentOctave][6]);
            // Play note that corresponds to M
            // Make note of which note was played in file on SD Card
            write_to_SDCard('B');
            readyFlag = false;
            }
        else if((keyPress == RAISE_OCTAVE_KEY) && (readyFlag)){ // button O pressed
            // Raise an octave
            if(currentOctave < 7)
            currentOctave++;
            else
            printf("Cannot raise octave above 7.\r\n");
            }
        else if((keyPress == LOWER_OCTAVE_KEY) && (readyFlag)){ // button L pressed
            // Lower an octave
            if(currentOctave > 1)
            currentOctave--;
            else
            printf("Cannot lower octave below 1.\r\n");
            }
        else if((keyPress == RAISE_ATTACK_KEY) && (readyFlag)){ // button Q pressed
            // Raise Attack Value
            if(currentAttackVal < 5){
            currentAttackVal++;
            change_Attack_Table(currentAttackVal);
            }
            else
            printf("Cannot raise value above 5.\r\n");
            }
        else if((keyPress == LOWER_ATTACK_KEY) && (readyFlag)){ // button A pressed
            // Lower Attack Value
            if(currentAttackVal > 1){
            currentAttackVal--;
            change_Attack_Table(currentAttackVal);
            }
            else
            printf("Cannot lower value below 1.\r\n");
            }
        else if((keyPress == RAISE_DELAY_KEY) && (readyFlag)){ // button W pressed
            // Raise Delay Value
            if(currentDecayVal < 5){
            currentDecayVal++;
            change_Decay_Table(currentDecayVal);
            }
            else
            printf("Cannot raise value above 5.\r\n");
            }
        else if((keyPress == LOWER_DELAY_KEY) && (readyFlag)){ // button S pressed
            // Lower Delay Value
            if(currentDecayVal > 1){
            currentDecayVal--;
            change_Decay_Table(currentDecayVal);
            }
            else
            printf("Cannot lower value below 1.\r\n");
            }
        else if((keyPress == RAISE_SUSTAIN_KEY) && (readyFlag)){ // button E pressed
            // Raise Sustain Value
            if(currentSustainVal < 5){
            currentSustainVal++;
            change_Sustain_Table(currentSustainVal);
            }
            else
            printf("Cannot raise value above 5.\r\n");
            }
        else if((keyPress == LOWER_SUSTAIN_KEY) && (readyFlag)){ // button D pressed
            // Lower Sustain Value
            if(currentSustainVal > 1){
            currentSustainVal--;
            change_Sustain_Table(currentSustainVal);
            }
            else
            printf("Cannot lower value below 1.\r\n");
            }
        else if((keyPress == RAISE_RELEASE_KEY) && (readyFlag)){ // button R pressed
            // Raise Release Value
            if(currentReleaseVal < 5){
            currentReleaseVal++;
            change_Release_Table(currentReleaseVal);
            }
            else
            printf("Cannot raise value above 5.\r\n");
            }
        else if((keyPress == LOWER_RELEASE_KEY) && (readyFlag)){ // button F pressed
            // Lower Release Value
            if(currentReleaseVal > 1){
            currentReleaseVal--;
            change_Release_Table(currentReleaseVal);
            }
            else
            printf("Cannot lower value below 1.\r\n");
            }
        else if((keyPress == CHANGE_WAVESHAPE_UP) && (readyFlag)){ // button T pressed
            // Change waveform shape to next waveform type
            switch(myWave){
                case sine:
                    myWave = square;
                    change_Wave(myWave);
                    break;
                case square:
                    myWave = sawtooth;
                    change_Wave(myWave);
                    break;
                case sawtooth:
                    myWave = sine;
                    change_Wave(myWave);
                    break;
                default:
                break;
                }
            }
        else if((keyPress == CHANGE_WAVESHAPE_DOWN) && (readyFlag)){ // button G pressed
            // Change waveform shape to previous waveform type
            switch(myWave){
                case sine:
                    myWave = sawtooth;
                    change_Wave(myWave);
                    break;
                case square:
                    myWave = sine;
                    change_Wave(myWave);
                    break;
                case sawtooth:
                    myWave = square;
                    change_Wave(myWave);
                    break;
                default:
                break;
                }
            }
        
        }
        //do other tasks in main - interrupts will process button message characters
        myled = 1;
        wait(0.1);
        myled = 0;
        wait(0.1);
    
}