
Bluetooth Enabled Keyboard/Synthesizer for mbed
Dependencies: mbed 4DGL-uLCD-SE SDFileSystem mbed-rtos
Diff: main.cpp
- Revision:
- 8:f6699fd30737
- Parent:
- 7:d4c3260cb092
- Child:
- 9:e4df1a31a098
--- a/main.cpp Thu Apr 28 19:31:28 2016 +0000 +++ b/main.cpp Thu Apr 28 22:16:40 2016 +0000 @@ -15,6 +15,8 @@ uLCD_4DGL uLCD(p13,p14,p11); // 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 = true; @@ -39,6 +41,7 @@ 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 +double timeIncrement = (2/256); // 2 seconds with 256 samples /* Coefficient Matrices Corresponding to Different Attack Values each matrix is comprised of 32 elements (256/8). The first matrix corresponds @@ -146,56 +149,12 @@ 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 sustainVals5[160]; +double sustainVals4[160]; +double sustainVals3[160]; +double sustainVals2[160]; +double sustainVals1[160]; double releaseVals5[32] = { }; double releaseVals4[32] = { @@ -470,6 +429,17 @@ break; } } +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; + } +} void clear_Buffer(void){ sampleBuffer.clear(); @@ -507,14 +477,73 @@ } } - +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; + } +} - +void generate_sineWave(int frequency) +{ + double t = 0; + for(i = 0; i < 256 ; i++) + { + sampleBuffer.push_back(((sin(2*(PI)*frequency*t)) + 1)/2); // scaled to be a % of maximum output voltage (3.3V) + t = t + timeIncrement; // increment t for calculation of next value in the waveform + } +} - +void generate_sawtoothWave(int frequency) +{ + double t = 0; + for(i = 0; i<256 ; i++) + { + sampleBuffer.push_back((2*(t*frequency) - (.5 + (t*frequency)) + 1) / 2); + t = t + timeIncrement; // increment t for calculation of next value in the waveform + } +} +void generate_squareWave(int frequency) +{ + double width = (1 / 2 * frequency); //Width of a half period of the square wave + double t = 0; + for(i = 0; i < 256; i++) + { + if((int)(t / width) % 2 ) == 0) // Even, write a 1 for the square wave + sampleBuffer.push_back(1.0); + else // Odd, write a 0 for the square wave + sampleBuffer.push_back(0.0); + t = t + timeIncrement; // increment t for calculation of next value in the waveform + } +} - +void output_samples() +{ + for( int sample = 0; sample < 256; sample++) + { + synthPin = sampleBuffer[sample]; + Thread::wait(timeIncrement * 1000); + } + + + //Interrupt routine to parse message with one new character per serial RX interrupt void parse_message() @@ -591,6 +620,7 @@ // make directory to hold the record of notes played mkdir("/sd/noteRecords", 0777); +initialize_sustainVals(); // fill the lookup tables with the sustain values in them //attach interrupt function for each new Bluetooth serial character Blue.attach(&parse_message,Serial::RxIrq); @@ -598,6 +628,7 @@ //check for a new button message ready if((keyPress == C_NOTE_KEY) && (readyFlag)){ // button Z pressed set_Note_Freq(noteArray[currentOctave-1][0]); + create_samples(note_freq, myWave); write_to_SDCard('C'); readyFlag = false; // Play note that corresponds to Z