Bluetooth Enabled Keyboard/Synthesizer for mbed

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

main.cpp

Committer:
jmpin
Date:
2016-04-30
Revision:
20:f3e994db66be
Parent:
19:2f635d03467c

File content as of revision 20:f3e994db66be:

#include "mbed.h"
#include "SDFileSystem.h"
#include "rtos.h"
#include <vector>
#include "uLCD_4DGL.h"
#include "synthesizer.h"
#include <iostream>
#include <cstring>
#include <iomanip>
RawSerial Blue(p13,p14);
RawSerial PC(USBTX,USBRX);
DigitalOut myled(LED1);
DigitalOut myled4(LED4);

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

uLCD_4DGL uLCD(p28,p27,p30); // serial tx, serial rx, reset pin;

AnalogOut synthPin(p18);     // p18 is the pin that will have the output voltages on it


//global variables for main and interrupt routine
volatile bool readyFlag = false;
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
double *currentAttackTable;            // pointer to the correct attack coefficient table
double *currentDecayTable;             // pointer to the correct decay coefficient table
double *currentSustainTable;           // pointer to the correct sustain coefficient table
double *currentReleaseTable;           // pointer to the correct release coefficient table
vector<float> sampleBuffer;        // vector to hold samples of generated waveform
int num_samples = 256;              // number of samples 
volatile int noteFreq;              // the current frequency of the note being played
double timeIncrement = (2.0/256.0);     // 2 seconds with 256 samples
short unsigned Analog_Out_Data[32];

/* 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 5.
*/

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
};

/* Coefficient Matrices Corresponding to Different Decay Values
each matrix is comprised of 32 elements (256/8). The first matrix corresponds
to a decay value of 5.
*/

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] = {   // Decay value of 4
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] = {   // Decay value of 3
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] = {   // Decay value of 2
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] = {   // Decays the slowest, in a linear fashion - corresponds to a decay value of 1
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
};

/* Coefficient Matrices Corresponding to Different sustain values
each matrix is comprised of 160 elements 5 * (256/8). The first matrix corresponds
to a sustain value of 5. The matrices get initialized later in a for loop due to their size.
*/

double sustainVals5[160]; 
double sustainVals4[160];
double sustainVals3[160];
double sustainVals2[160];
double sustainVals1[160];

/* Coefficient Matrices Corresponding to Different release values
each matrix is comprised of 32 elements (256/8). The first matrix corresponds
to a release value of 5.
*/

double releaseVals5[32] = {     // Releases (goes to 0 amplitude) the quickest - corresponds to a release value of 5
0.6 , 0.3 , 0.15 , 0.1 , 
0.09 , 0.08 , 0.07 , 0.06 , 
0.05 , 0.045 , 0.04 , 0.035 , 
0.03 , 0.025 , 0.02 , 0.015 , 
0.01 , 0.0075 , 0.005 , 0.0025 , 
0 , 0 , 0 , 0 , 
0 , 0 , 0 , 0 , 
0 , 0 , 0 , 0};
double releaseVals4[32] = {     // Release value of 4
0.6 , 0.45 , 0.3 , 0.2 , 
0.17 , 0.16 , 0.15 , 0.14 , 
0.13 , 0.125 , 0.12 , 0.115 , 
0.11 , 0.105 , 0.1 , 0.095 , 
0.09 , 0.085 , 0.08 , 0.075 , 
0.07 , 0.065 , 0.06 , 0.055 , 
0.05 , 0.045 , 0.04 , 0.035 , 
0.03 , 0.02 , 0.01 , 0};
double releaseVals3[32] = {     // Release value of 3
0.6 , 0.5 , 0.43 , 0.37 , 
0.32 , 0.28 , 0.26 , 0.24 , 
0.22 , 0.2 , 0.18 , 0.17 , 
0.16 , 0.15 , 0.14 , 0.13 , 
0.12 , 0.11 , 0.1 , 0.09 , 
0.08 , 0.07 , 0.06 , 0.05 , 
0.04 , 0.035 , 0.03 , 0.025 , 
0.02 , 0.015 , 0.01 , 0};
double releaseVals2[32] = {     // Release value of 2
0.6 , 0.55 , 0.5 , 0.46 , 
0.43 , 0.4 , 0.37 , 0.34 , 
0.32 , 0.3 , 0.28 , 0.26 , 
0.24 , 0.22 , 0.2 , 0.18 , 
0.16 , 0.15 , 0.14 , 0.13 , 
0.12 , 0.11 , 0.1 , 0.09 , 
0.08 , 0.07 , 0.06 , 0.05 , 
0.04 , 0.03 , 0.015 , 0};
double releaseVals1[32] = {     // Release value of 1 - proceeds slowest, in a linear fashion
0.6 , 0.580645161 , 0.561290323 , 0.541935484 , 
0.522580645 , 0.503225806 , 0.483870968 , 0.464516129 , 
0.44516129 , 0.425806452 , 0.406451613 , 0.387096774 , 
0.367741935 , 0.348387097 , 0.329032258 , 0.309677419 , 
0.290322581 , 0.270967742 , 0.251612903 , 0.232258065 , 
0.212903226 , 0.193548387 , 0.174193548 , 0.15483871 , 
0.135483871 , 0.116129032 , 0.096774194 , 0.077419355 , 
0.058064516 , 0.038709677 , 0.019354839 , -1.38778E-16};

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){     // uLCD displays curernt waveform shape, current octave, and the values for the ADSR coefficients
    while(1){
        uLCD.locate(0,0);
        switch(myWave){
        case sine:
            uLCD.printf("Shape: Sine    \r\n");     // if wave type is sine wave, display sine
            break;
        case square:
            uLCD.printf("Shape: Square  \r\n");   // if wave type is square wave, display square
            break;
        case sawtooth:
            uLCD.printf("Shape: Sawtooth\r\n"); // if wave type is sawtooth wave, display sawtooth
            break;
        default:
        break;
        }
        uLCD.printf("Octave: %i\r\n",currentOctave);        // displays octave
        uLCD.printf("Attack: %i\r\n",currentAttackVal);     // displays attack value
        uLCD.printf("Decay: %i\r\n",currentDecayVal);       // displays decay value
        uLCD.printf("Sustain: %i\r\n",currentSustainVal);   // displays sustain value
        uLCD.printf("Release: %i\r\n",currentReleaseVal);   // displays release value
    }
}

void clear_Buffer(void){        // clears buffer that holds samples
    sampleBuffer.clear();
}

void set_Note_Freq(int frequency){      // updates the frequency of the note being played
    noteFreq = frequency;
    clear_Buffer();
}

void change_Attack_Table(int attackVal)     // change which table of coefficients to use for altering the attack portion of the waveform
{
    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)       // change which table of coefficients to use for altering the decay portion of the waveform
{
    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)   // change which table of coefficients to use for altering the sustain portion of the waveform
{
    switch(sustainVal){
    case 5:
        currentSustainTable = sustainVals5;
        break;
    case 4:
        currentSustainTable = sustainVals4;
        break;
    case 3:
        currentSustainTable = sustainVals3;
        break;
    case 2:
        currentSustainTable = sustainVals2;
        break;
    case 1:
        currentSustainTable = sustainVals1;
        break;
    default:
    break;
    }
}

void change_Release_Table(int releaseVal)       // change which table of coefficients to use for altering the release portion of the waveform
{
    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;
    }
} 

/* Having different sustain values for the amplitude of the wave would make the math neccesary to generate the other
coefficient matrices very complex, so only .6 is used, meaning a sustain value of 1-5 will all correspond to a sustain amplitude
of .6. Since the sustain coefficient matrices are 160 elements long, they are all filled in a for loop with this function call.
*/

void initialize_sustainVals()   
{
    for(int j = 0; j < 160; j++)
    {
        sustainVals5[j] = .6;
        sustainVals4[j] = .6;
        sustainVals3[j] = .6;
        sustainVals2[j] = .6;
        sustainVals1[j] = .6;
    }
}
/* Applies the envelope to the waveform. Each set of coefficients is applied to a certain portion of the waveform to alter its shape.
The attack coefficients are appplied to the first 32 samples, the decay coefficients are applied to samples 33-64, the sustain coefficients
are applied to samples 65 - 224, and the release coefficients are appplied to samples 225-256.
*/


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
    
    full_envelope = 
    
    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];
    }     
}

void generateSquareWave(){
    for(int i = 0; i < 32; i++)
    {
    if(i<16)
        Analog_Out_Data[k] = 1 * 65536;
    else
        Analog_Out_Data[k] = 0;
    }
}

void generateSawtoothWave(){
    float t = 0;
    for(int i = 0; i < 32; i++)
    {
        Analog_Out_Data[k] = t * 65536;
        t += (1/32);
    }
}


/* Generates the waveforms that will be output to the AnalogOut pin after being altered by the ADSR coefficient matrices.
The envelope is only applied to sine waves here because when applied to the other wave shapes, the sound does not sounds good.
@param: frequency - the frequency of the waveform to be generated
@param: currentWaveType - the shape of the wave that needs to be generated
*/


void create_samples(int frequency, WaveType currentWaveType)
{
    switch(currentWaveType){
        case sine:
            //Generate sine wave values
            generate_sineWave(frequency);
            apply_Envelope();
            break;
        case square:
            //Generate square wave values
            generate_squareWave(frequency);
            //apply_Envelope();
            break;
        case sawtooth:
            //Generate sawtooth wave values
            generate_sawtoothWave(frequency);
            //apply_Envelope();
            break;
        default:
        break;
    }
}


/* Outputs the samples that are currently in the buffer one at a time. There is a period of time
where the program waits so that the 256 samples fill up the entire 2 seconds. The buffer is cleared
after the output is finished so that next time the buffer will be ready for new samples.
*/
void output_samples()
{
    for( int sample = 0; sample < 256; sample++)
    {
        //synthPin = sampleBuffer[sample];
        PC.printf("Current Sample: %f",sampleBuffer[sample]);
    }
    clear_Buffer();
}
        
    
    

//Interrupt routine to parse message with one new character per serial RX interrupt
void parse_message()
{
    //PC.printf("Parse_message was called");
    while(Blue.readable())
    {
        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);
        //wait(1);
    }
}


/*
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;  // Holds the value of the attack parameter
    DecayBits = currentDecayVal;    // Holds the value of the decay parameter
    SustainBits = currentSustainVal;// Holds the value of the sustain parameter
    ReleaseBits = currentReleaseVal;// Holds the value of the release parameter
    OctaveBits = currentOctave;
    switch(note){
        case 'C':                   // a C corresponds to a 3
            NoteBits = 3;
            break;
        case 'D':
            NoteBits = 4;           // a D corresponds to a 4
            break;
        case 'E':
            NoteBits = 5;           // an E corresponds to a 5
            break;
        case 'F':
            NoteBits = 6;           // an F corresponds to a 6
            break;
        case 'G':
            NoteBits = 7;           // a G corresponds to a 7
            break;
        case 'A':
            NoteBits = 1;           // an A corresponds to a 1
            break;
        case 'B':
            NoteBits = 2;           // a B corresponds to a 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");        // creates handle for file we want to write to
    if(fp == NULL) {
        error("Could not open file for write\n");                       // if this is not a valid name, tell user there is an error
    }
    fprintf(fp,"%X\r\n",writeVal);      // writes value to the text file in hexadecimal
    fclose(fp);
}

int main()
{
    Thread thread1(uLCD_Display_Thread);        // the thread that displays the current values of the parameters as well as the octave and wave shape
    
    
    mkdir("/sd/noteRecords", 0777);             // make directory to hold the record of notes played

    initialize_sustainVals();                   // fill the lookup tables with the sustain values in them
    
    PC.baud(9600);                              // setup baud rate for PC serial connection
    Blue.baud(9600);                            // setup baud rate for bluetooth serial connection

    
    Blue.attach(&parse_message,Serial::RxIrq);  //attach interrupt function for each new Bluetooth serial character
    while(1) {
        //check for a new button message ready
        if((keyPress == C_NOTE_KEY) && (readyFlag)){        // Play note C
            set_Note_Freq(noteArray[currentOctave-1][0]);   // set the note frequency to the proper value 
            create_samples(noteFreq, myWave);               // creates the samples that are going to be output to the waveform
            output_samples();                               // outputs the samples that are currently in the buffer to p18
            write_to_SDCard('C');                           // writes to the SD card
            readyFlag = false;                              // set this flag to false so that the program will not try to process the key press more than once
            
        }
        else if((keyPress == D_NOTE_KEY) && (readyFlag)){ // Play note D
            set_Note_Freq(noteArray[currentOctave-1][1]);
            create_samples(noteFreq, myWave);
            output_samples();
            write_to_SDCard('D');
            readyFlag = false;
            
        }
        else if((keyPress == E_NOTE_KEY) && (readyFlag)){ // Play note E
            set_Note_Freq(noteArray[currentOctave-1][2]);
            create_samples(noteFreq, myWave);
            output_samples();
            write_to_SDCard('E');
            readyFlag = false;
        }
        else if((keyPress == F_NOTE_KEY) && (readyFlag)){ // Play note F
            set_Note_Freq(noteArray[currentOctave-1][3]);
            create_samples(noteFreq, myWave);
            output_samples();
            write_to_SDCard('F');
            readyFlag = false;
        }
        else if((keyPress == G_NOTE_KEY) && (readyFlag)){ // Play note G
            set_Note_Freq(noteArray[currentOctave-1][4]);
            create_samples(noteFreq, myWave);
            output_samples();
            write_to_SDCard('G');
            readyFlag = false;
        }
        else if((keyPress == A_NOTE_KEY) && (readyFlag)){ // Play note A
            set_Note_Freq(noteArray[currentOctave][5]);
            create_samples(noteFreq, myWave);
            output_samples();
            write_to_SDCard('A');
            readyFlag = false;
        }
        else if((keyPress == B_NOTE_KEY) && (readyFlag)){ // Play note B
            set_Note_Freq(noteArray[currentOctave][6]);
            create_samples(noteFreq, myWave);
            output_samples();
            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");
            readyFlag = false;
        }
        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");
            readyFlag = false;
        }
        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");
            readyFlag = false;
        }
        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");
            readyFlag = false;
        }
        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");
            readyFlag = false;
        }
        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");
            readyFlag = false;
        }
        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");
            readyFlag = false;
        }
        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");
            readyFlag = false;
        }
        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");
            readyFlag = false;
        }
        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");
            readyFlag = false;
        }
        else if((keyPress == CHANGE_WAVESHAPE_UP) && (readyFlag)){ // button T pressed
            // Change waveform shape to next waveform type
            switch(myWave){
                case sine:
                    myWave = square;
                    break;
                case square:
                    myWave = sawtooth;
                    break;
                case sawtooth:
                    myWave = sine;
                    break;
                default:
                break;
                }
                readyFlag = false;
        }
        else if((keyPress == CHANGE_WAVESHAPE_DOWN) && (readyFlag)){ // button G pressed
            // Change waveform shape to previous waveform type
            switch(myWave){
                case sine:
                    myWave = sawtooth;
                    break;
                case square:
                    myWave = sine;
                    break;
                case sawtooth:
                    myWave = square;
                    break;
                default:
                break;
                }
                readyFlag = false;
                
        }
    }
}